dhcp 服务探测-凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 752867
  • 博文数量: 144
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1150
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-17 14:32
个人简介

小公司研发总监,既当司令也当兵!

文章分类

全部博文(144)

相关博文
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·
  • ·

分类: linux

2020-11-05 11:03:53


在一些网络环境中,需要用到dhcp服务探测技术,动态调整本地dhcp服务的。本文提供一个探测的demo实现。
原理:
发送dhcp discover 报文,如果能够接受到 dhcp offer回应,则可以获取到服务信息。

代码如下:

点击(此处)折叠或打开

  1. #include <errno.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <stddef.h>
  6. #include <time.h>
  7. #include <string.h>
  8. #include <signal.h>
  9. #include <sys/ioctl.h>
  10. #include <arpa/inet.h>
  11. #include <netpacket/packet.h>
  12. #include <netinet/if_ether.h>
  13. #include <netinet/ip.h>
  14. #include <netinet/udp.h>
  15. #include <linux/if.h>

  16. #define max_wait_time 15
  17. #define max_error_length 1500

  18. /* endianness check */
  19. #define is_big_endian (*(uint16_t *)"\0\xff" < 0x100)


  20. /* dhcp protocol. rfc 2131, rfc 2132 */
  21. #define dhcp_magic                 0x63825363
  22. #define dhcp_fixed_len            240 /* with dhcp magic */
  23. #define dhcp_udp_overhead        28 /* ip udp headers */
  24. #define dhcp_mtu_max            1500
  25. #define dhcp_mtu_min            576
  26. #define dhcp_options_buf_min    (dhcp_mtu_min - dhcp_fixed_len - dhcp_udp_overhead)
  27. #define dhcp_options_buf_max    (dhcp_mtu_max - dhcp_fixed_len - dhcp_udp_overhead)

  28. #define bootrequest                1
  29. #define bootreply                2

  30. /* dhcp ports and addresses */
  31. #define client_port        68
  32. #define server_port        67

  33. /* dhcp packet */
  34. struct dhcp_packet
  35. {
  36.     uint8_t op;                /* bootrequest or bootreply */
  37.     uint8_t htype;            /* hardware address type. 1 = 10mb ethernet */
  38.     uint8_t hlen;            /* hardware address length */
  39.     uint8_t hops;            /* used by relay agents only */
  40.     uint32_t xid;            /* unuque id */
  41.     uint16_t secs;             /* seconds since client started looking */
  42.     uint16_t flags;            /* only one flag */
  43.     uint32_t ciaddr;        /* clients ip address (if already in use) */
  44.     uint32_t yiaddr;        /* client ip address */
  45.     uint32_t siaddr_nip;    /* next server used in bootstrap */
  46.     uint32_t gateway_nip;    /* relay agent ip address */
  47.     uint8_t chaddr[16];        /* mac address of client */
  48.     uint8_t sname[64];        /* server host name (asciz) */
  49.     uint8_t file[128];        /* boot file name (asciiz) */
  50.     uint32_t cookie;        /* fixed first four option bytes (99, 130, 83, 99 dec) */
  51.     uint8_t options[dhcp_options_buf_max];
  52. };

  53. /* ip packet with dhcp */
  54. struct ip_udp_dhcp_packet
  55. {
  56.     struct iphdr ip;            /* ip header */
  57.     struct udphdr udp;            /* udp header */
  58.     struct dhcp_packet data;    /* udp payload */
  59. };

  60. /* udp packet with dhcp */
  61. struct udp_dhcp_packet
  62. {
  63.     struct udphdr udp;            /* udp header */
  64.     struct dhcp_packet data;    /* udp payload */
  65. };

  66. /* packets size */
  67. enum
  68. {
  69.     ip_udp_dhcp_size = sizeof(struct ip_udp_dhcp_packet),
  70.     udp_dhcp_size = sizeof(struct udp_dhcp_packet),
  71.     dhcp_size = sizeof(struct dhcp_packet),
  72. };

  73. /* dhcp options codes */
  74. #define dhcp_padding             0x00
  75. #define dhcp_subnet             0x01
  76. #define dhcp_router                0x03
  77. #define dhcp_dns                0x06
  78. #define dhcp_broadcast            0x1c
  79. #define dhcp_static                0x21
  80. #define dhcp_ntp                0x2a
  81. #define dhcp_vendor                0x2b
  82. #define dhcp_netbios_name_srv    0x2c
  83. #define dhcp_lease_time         0x33
  84. #define dhcp_overload            0x34
  85. #define dhcp_message_type        0x35
  86. #define dhcp_server_id            0x36 /* dhcp server ip */
  87. #define dhcp_param_req            0x37 /* list of options client wants */
  88. #define dhcp_max_size            0x39
  89. #define dhcp_renewal_time        0x3a
  90. #define dhcp_rebinding_time        0x3b
  91. #define dhcp_vendor_class_id    0x3c
  92. #define dhcp_client_id            0x3d /* client's mac addr*/
  93. #define dhcp_sip                0x78
  94. #define dhcp_classless_static    0x79
  95. #define dhcp_end                0xff

  96. /* dhcp_message_type values */
  97. #define dhcpdiscover    1 /* client -> server */
  98. #define dhcpoffer        2 /* client <- server */

  99. /* offsets in option byte sequence */
  100. #define opt_code 0
  101. #define opt_len 1
  102. #define opt_data 2

  103. /* bits in "overload" option */
  104. #define option_field            0
  105. #define file_field                1
  106. #define sname_field                2


  107. static volatile sig_atomic_t got_alarm = 0;

  108. /**
  109.  * get mac address of interface.
  110.  *
  111.  * @param ifname interface name.
  112.  * @param addr array for mac address.
  113.  *
  114.  * @return -1 on failure, 0 on success.
  115.  */
  116. int get_if_mac(const char* ifname, uint8_t addr[eth_alen])
  117. {
  118.     /* copy interface name into ifreq */
  119.     struct ifreq ifr;
  120.     memset(&ifr, 0, sizeof(struct ifreq));

  121.     size_t if_name_len = strlen(ifname);

  122.     if (if_name_len < sizeof(ifr.ifr_name))
  123.     {
  124.         memcpy(ifr.ifr_name, ifname, if_name_len);
  125.         ifr.ifr_name[if_name_len] = 0;
  126.     }
  127.     else
  128.     {
  129.         return -1;
  130.     }

  131.     /* create socket */
  132.     int fd = socket(af_unix, sock_dgram, 0);

  133.     if (fd < 0)
  134.     {
  135.         return -1;
  136.     }

  137.     /* get hw address */
  138.     if (ioctl(fd, siocgifhwaddr, &ifr) < 0)
  139.     {
  140.         close (fd);
  141.         return -1;
  142.     }

  143.     close(fd);
  144.     memcpy (addr, ifr.ifr_hwaddr.sa_data, eth_alen);
  145.     return 0;
  146. }


  147. /**
  148.  * get interface index.
  149.  *
  150.  * @param ifname interface name.
  151.  *
  152.  * @return interface index on success, zero on failure.
  153.  */
  154. unsigned int get_if_index(const char* ifname)
  155. {
  156.     /* copy interface name into ifreq */
  157.     struct ifreq ifr;
  158.     memset(&ifr, 0, sizeof(struct ifreq));

  159.     size_t if_name_len = strlen(ifname);

  160.     if (if_name_len < sizeof(ifr.ifr_name))
  161.     {
  162.         memcpy(ifr.ifr_name, ifname, if_name_len);
  163.         ifr.ifr_name[if_name_len] = 0;
  164.     }
  165.     else
  166.     {
  167.         return -1;
  168.     }

  169.     /* create socket */
  170.     int fd = socket(af_unix, sock_dgram, 0);

  171.     if (fd < 0)
  172.     {
  173.         return 0;
  174.     }

  175.     /* get interface index */
  176.     if (ioctl(fd, siocgifindex, &ifr) < 0)
  177.     {
  178.         close (fd);
  179.         return 0;
  180.     }

  181.     close(fd);
  182.     return ifr.ifr_ifindex;
  183. }

  184. /**
  185.  * calculate internet checksum.
  186.  *
  187.  * @param addr start address.
  188.  * @param nleft length in bytes.
  189.  *
  190.  * @return checksum.
  191.  */
  192. uint16_t inet_chksum(uint16_t* addr, int nleft)
  193. {
  194.     /*
  195.      * algorithm is simple, using a 32 bit accumulator,
  196.      * we add sequential 16 bit words to it, and at the end, fold
  197.      * back all the carry bits from the top 16 bits into the lower
  198.      * 16 bits.
  199.      */
  200.     unsigned sum = 0;
  201.     while (nleft > 1)
  202.     {
  203.         sum = *addr;
  204.         nleft -= 2;
  205.     }
  206.     /* mop up an odd byte, if necessary */
  207.     if (nleft == 1)
  208.     {
  209.         if (is_big_endian)
  210.             sum = *(uint8_t*)addr << 8;
  211.         else
  212.             sum = *(uint8_t*)addr;
  213.     }

  214.     /* add back carry outs from top 16 bits to low 16 bits */
  215.     sum = (sum >> 16) (sum & 0xffff); /* add hi 16 to low 16 */
  216.     sum = (sum >> 16); /* add carry */

  217.     return (uint16_t)~sum;
  218. }

  219. /**
  220.  * calculate random id (unsigned 32-bit value).
  221.  *
  222.  * @param void.
  223.  * @return id
  224.  */
  225. uint32_t random_id(void)
  226. {
  227.     srand(time(null));
  228.     return rand();
  229. }


  230. /**
  231.  * fill dhcp packet.
  232.  *
  233.  * @param packet dhcp packet.
  234.  * @param hwaddr mac address of interface.
  235.  * @return void.
  236.  */
  237. static void dhcp_init_packet(struct dhcp_packet* packet, uint8_t* hwaddr)
  238. {
  239.     unsigned index = 0;

  240.     /* dhcp header */
  241.     memset(packet, 0, sizeof(*packet));
  242.     packet->op = bootrequest;
  243.     packet->htype = 1; /* ethernet */
  244.     packet->hlen = eth_alen;
  245.     packet->cookie = htonl(dhcp_magic);
  246.     packet->secs = 0;
  247.     memcpy(packet->chaddr, hwaddr, eth_alen);

  248.     /* dhcp options */
  249.     /* message type */
  250.     packet->options[index] = dhcp_message_type;
  251.     packet->options[index] = 1; //length of option data
  252.     packet->options[index] = dhcpdiscover;

  253.     /* requested parameters */
  254.     packet->options[index] = dhcp_param_req;
  255.     packet->options[index] = 9; // number of options
  256.     packet->options[index] = dhcp_subnet;
  257.     packet->options[index] = dhcp_router;
  258.     packet->options[index] = dhcp_dns;
  259.     packet->options[index] = dhcp_broadcast;
  260.     packet->options[index] = dhcp_static;
  261.     packet->options[index] = dhcp_ntp;
  262.     packet->options[index] = dhcp_vendor;
  263.     packet->options[index] = dhcp_sip;
  264.     packet->options[index] = dhcp_classless_static;

  265.     /* client id */
  266.     packet->options[index] = dhcp_client_id;
  267.     packet->options[index] = eth_alen 1;
  268.     packet->options[index] = 1; //ethernet
  269.     memcpy(&packet->options[index], hwaddr, eth_alen);
  270.     index = eth_alen;

  271.     /* end option */
  272.     packet->options[index] = dhcp_end;
  273. }

  274. /**
  275.  * calculate position of the end option.
  276.  *
  277.  * @param optionptr beginning of dhcp options.
  278.  * @return position of 'end' option.
  279.  */
  280. static int dhcp_end_option(uint8_t* optionptr)
  281. {
  282.     int i = 0;
  283.     while (optionptr[i] != dhcp_end)
  284.     {
  285.         if (optionptr[i] != dhcp_padding)
  286.             i = optionptr[i opt_len] opt_data - 1;
  287.         i;
  288.     }
  289.     return i;
  290. }

  291. /**
  292.  * get an option with bounds checking
  293.  *
  294.  * @param packet dhcp packet.
  295.  * @param code option code.
  296.  *
  297.  * @return null or pointer to beginning of the option data.
  298.  */
  299. static uint8_t* dhcp_get_option(struct dhcp_packet* packet, int code)
  300. {
  301.     uint8_t* optionptr;
  302.     int len;
  303.     int rem;
  304.     int overload = 0;
  305.     enum
  306.     {
  307.         file_field101 = file_field * 0x101,
  308.         sname_field101 = sname_field * 0x101,
  309.     };

  310.     /* option bytes: [code][len][data1][data2]...[datalen] */
  311.     optionptr = packet->options;
  312.     rem = sizeof(packet->options);
  313.     while (1)
  314.     {
  315.         if (rem <= 0)
  316.         {
  317.             return null;
  318.         }
  319.         if (optionptr[opt_code] == dhcp_padding)
  320.         {
  321.             rem--;
  322.             optionptr;
  323.             continue;
  324.         }
  325.         if (optionptr[opt_code] == dhcp_end)
  326.         {
  327.             if ((overload & file_field101) == file_field)
  328.             {
  329.                 /* we can use packet->file */
  330.                 overload |= file_field101;
  331.                 optionptr = packet->file;
  332.                 rem = sizeof(packet->file);
  333.                 continue;
  334.             }
  335.             if ((overload & sname_field101) == sname_field)
  336.             {
  337.                 /* we can use packet->sname */
  338.                 overload |= sname_field101;
  339.                 optionptr = packet->sname;
  340.                 rem = sizeof(packet->sname);
  341.                 continue;
  342.             }
  343.             break;
  344.         }
  345.         len = opt_data optionptr[opt_len];
  346.         rem -= len;
  347.         if (rem < 0)
  348.             continue;

  349.         if (optionptr[opt_code] == code)
  350.             return optionptr opt_data;

  351.         if (optionptr[opt_code] == dhcp_overload)
  352.             overload |= optionptr[opt_data];

  353.         optionptr = len;
  354.     }

  355.     return null;
  356. }

  357. /**
  358.  * send dhcp discover
  359.  *
  360.  * @param fd socket descriptor.
  361.  * @param ifindex interface index.
  362.  * @param hwaddr mac address of interface.
  363.  * @param id unique id.
  364.  *
  365.  * @return number of bytes sent on success, -1 on error.
  366.  */
  367. static int dhcp_send_discover(int fd, int ifindex, uint8_t* hwaddr, uint32_t id)
  368. {
  369.     struct sockaddr_ll sa;
  370.     struct ip_udp_dhcp_packet packet;
  371.     unsigned padding;
  372.     int result = -1;

  373.     /* bind */
  374.     memset(&sa, 0, sizeof(sa));
  375.     sa.sll_family = af_packet;
  376.     sa.sll_protocol = htons(eth_p_ip);
  377.     sa.sll_ifindex = ifindex;
  378.     sa.sll_halen = eth_alen;
  379.     memset(&sa.sll_addr, 0xff, eth_alen);

  380.     if (bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0)
  381.     {
  382.         return result;
  383.     }

  384.     /* craft packet */
  385.     memset(&packet, 0, sizeof(packet));
  386.     dhcp_init_packet(&packet.data, hwaddr);
  387.     packet.data.xid = id;

  388.     /* for badly configured servers (they drop dhcp packets > 576 octets (with ethernet header),
  389.      * but they may only drop packets > 576 octets without ethernet header (590 with ethernet header).
  390.      * rfc 1542: minimal bootp header 300 octets.
  391.      */
  392.     padding = dhcp_options_buf_max - 1 - dhcp_end_option(packet.data.options);
  393.     if (padding > dhcp_size - 300)
  394.         padding = dhcp_size - 300;

  395.     /* ip and udp headers */
  396.     packet.ip.protocol = ipproto_udp;
  397.     packet.ip.saddr = htonl(inaddr_any);
  398.     packet.ip.daddr = htonl(inaddr_broadcast);
  399.     packet.udp.source = htons(client_port);
  400.     packet.udp.dest = htons(server_port);
  401.     /* size, excluding ip header */
  402.     packet.udp.len = htons(udp_dhcp_size - padding);
  403.     /* for udp checksumming, ip.len is set to udp packet len */
  404.     packet.ip.tot_len = packet.udp.len;

  405.     packet.udp.check = inet_chksum((uint16_t*)&packet,
  406.      ip_udp_dhcp_size - padding);
  407.     /* for sending, it is set to ip packet len */
  408.     packet.ip.tot_len = htons(ip_udp_dhcp_size - padding);
  409.     packet.ip.version = ipversion;
  410.     packet.ip.ihl = sizeof(packet.ip) >> 2;
  411.     packet.ip.ttl = ipdefttl;
  412.     packet.ip.check = inet_chksum((uint16_t*)&packet.ip, sizeof(packet.ip));

  413.     /* send packet */
  414.     result = sendto(fd, &packet, ip_udp_dhcp_size - padding, 0,
  415.      (struct sockaddr*)&sa, sizeof(sa));

  416.     return result;
  417. }


  418. /**
  419.  * receive offer
  420.  *
  421.  * @param fd socket descriptor.
  422.  * @param id unique id.
  423.  * @param hwaddr mac address of interface.
  424.  *
  425.  * @return 0 on success, -1 on read error,
  426.  * -2 packet is not correct, -3 on eintr (time is out).
  427.  */
  428. static int dhcp_recv_offer(int fd, uint32_t id, uint8_t* hwaddr)
  429. {
  430.     int bytes;
  431.     struct ip_udp_dhcp_packet packet;
  432.     struct dhcp_packet data;

  433.     uint8_t* opt_data;
  434.     uint16_t check;
  435.     char ip_str[inet_addrstrlen];
  436.     uint32_t ip_addr;
  437.     int i;

  438.     memset(&packet, 0, sizeof(packet));
  439.     memset(&data, 0, sizeof(data));

  440.     /* read packet */
  441.     bytes = read(fd, &packet, sizeof(packet));

  442.     if (bytes < 0)
  443.     {
  444.         if (errno == eintr)
  445.         {
  446.             return -3;
  447.         }
  448.         else
  449.         {
  450.             return -1;
  451.         }
  452.     }
  453.     /* packet is too short */
  454.     if (bytes < (int) (sizeof(packet.ip) sizeof(packet.udp)))
  455.         return -2;
  456.     /* oversized packet */
  457.     if (bytes < (int) ntohs(packet.ip.tot_len))
  458.         return -2;

  459.     /* ignore any extra garbage bytes */
  460.     bytes = ntohs(packet.ip.tot_len);

  461.     /* unrelated/bogus packet */
  462.     if (packet.ip.protocol != ipproto_udp
  463.      || packet.ip.version != ipversion
  464.      || packet.ip.ihl != (sizeof(packet.ip) >> 2)
  465.      || packet.udp.dest != htons(client_port)
  466.      || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) )
  467.         return -2;

  468.     /* verify ip checksum */
  469.     check = packet.ip.check;
  470.     packet.ip.check = 0;
  471.     if (check != inet_chksum((uint16_t*)&packet.ip, sizeof(packet.ip)))
  472.         return -2;

  473.     /* verify udp checksum, ip header has to be modified for this */
  474.     memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
  475.     /* ip.xx fields which are not memset: protocol, check, saddr, daddr */
  476.     packet.ip.tot_len = packet.udp.len;
  477.     check = packet.udp.check;
  478.     packet.udp.check = 0;
  479.     if (check && check != inet_chksum((uint16_t*)&packet, bytes))
  480.         return -2;

  481.     memcpy(&data, &packet.data, sizeof(data));

  482.     /* check dhcp magic */
  483.     if (bytes < (int)offsetof(struct dhcp_packet, options)
  484.      || data.cookie != htonl(dhcp_magic))
  485.         return    -2;

  486.     /* check xid */
  487.     if (data.xid != id)
  488.         return -2;

  489.     /* ignore packets that aren't for us */
  490.     if (data.hlen != eth_alen || memcmp(&data.chaddr, hwaddr, eth_alen))
  491.         return -2;

  492.     /* check message type */
  493.     opt_data = dhcp_get_option(&data, dhcp_message_type);
  494.     if (!opt_data || *opt_data != dhcpoffer)
  495.         return -2;

  496.     /* print output */
  497.     /* get dhcp server id */
  498.     opt_data = dhcp_get_option(&data, dhcp_server_id);
  499.     if (opt_data)
  500.     {
  501.         ip_addr = *(uint32_t*)opt_data;
  502.         if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  503.             printf("-->> server:%s\n", ip_str);
  504.     }

  505.     /* get netmask */
  506.     opt_data = dhcp_get_option(&data, dhcp_subnet);
  507.     if (opt_data)
  508.     {
  509.         ip_addr = *(uint32_t*)opt_data;
  510.         if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  511.             printf("-->> mask:%s\n", ip_str);
  512.     }

  513.     /* get router */
  514.     opt_data = dhcp_get_option(&data, dhcp_router);
  515.     if (opt_data)
  516.     {
  517.         ip_addr = *(uint32_t*)opt_data;
  518.         if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  519.             printf("-->> router:%s\n", ip_str);

  520.     }

  521.     /* get dns servers */
  522.     opt_data = dhcp_get_option(&data, dhcp_dns);
  523.     if (opt_data)
  524.     {

  525.         int num = *(opt_data - 1) >> 2; /* get number of servers */
  526.         for (i = 0; i < num; i)
  527.         {
  528.             ip_addr = (*((uint32_t*)opt_data i));
  529.             if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  530.                 printf("-->> dns%d:%s\n", i 1, ip_str);
  531.             else
  532.                 break;
  533.         }
  534.     }

  535.     /* get broadcast address */
  536.     opt_data = dhcp_get_option(&data, dhcp_broadcast);
  537.     if (opt_data)
  538.     {
  539.         ip_addr = *(uint32_t*)opt_data;
  540.         if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  541.             printf("-->> broadcast:%s\n", ip_str);

  542.     }
  543.     /* get netbios name servers */
  544.     opt_data = dhcp_get_option(&data, dhcp_netbios_name_srv);
  545.     if (opt_data)
  546.     {
  547.         int num = *(opt_data - 1) >> 2; /* get number of servers */
  548.         for (i = 0; i < num; i)
  549.         {
  550.             ip_addr = *((uint32_t*)opt_data i);
  551.             if (inet_ntop(af_inet, &ip_addr, ip_str, sizeof(ip_str)))
  552.                 printf("-->> netbios%d:%s\n", i 1, ip_str);
  553.             else
  554.                 break;
  555.         }
  556.     }
  557.     return 0;
  558. }

  559. /**
  560.  * signal handler
  561.  * @param signal value.
  562.  *
  563.  * @return void.
  564.  */
  565. static void handler(int sig)
  566. {
  567.     if (sig == sigalrm)
  568.         got_alarm = 1;
  569. }


  570. /**
  571.  * search dhcp server.
  572.  *
  573.  * @param ifname network interface name.
  574.  * @param time wait time.
  575.  *
  576.  * @return 1 on success, 0 on time is out, -2 on invalid json object for result,
  577.  * -1 on other errors.
  578.  */
  579. int scan_dhcp(const char* ifname, unsigned int time)
  580. {
  581.     int ifindex;
  582.     uint8_t hwaddr[eth_alen];
  583.     struct sigaction sa;
  584.     uid_t euid;
  585.     uint32_t id;
  586.     int fd = -1;
  587.     int ret = -1;


  588.     /* check superuser priveleges */
  589.     if ((euid = geteuid()) != 0)
  590.     {
  591.         printf( "you must be root\n");
  592.         goto err_exit;
  593.     }

  594.     /* check input data */
  595.     /* check wait time */
  596.     if (time == 0)
  597.         time = 1;

  598.     if (time > max_wait_time)
  599.     {
  600.         printf("max wait time is %d\n", max_wait_time);
  601.         goto err_exit;
  602.     }

  603.     /* check interface name */
  604.     if (!ifname || *ifname == '\0')
  605.     {
  606.         printf("empty interface name\n");
  607.         goto err_exit;
  608.     }

  609.     /* check interface name length */
  610.     if (strlen(ifname) > ifnamsiz)
  611.     {
  612.         printf("interface name is too long\n");
  613.         goto err_exit;
  614.     }

  615.     /* get interface index */
  616.     if ((ifindex = get_if_index(ifname)) == 0)
  617.     {
  618.         printf("no interface found\n");
  619.         goto err_exit;
  620.     }

  621.     /* get mac address */
  622.     if ((get_if_mac(ifname, hwaddr)) < 0)
  623.     {
  624.         printf( "can't get mac address\n");
  625.         goto err_exit;
  626.     }

  627.     /* create socket */
  628.     fd = socket(pf_packet, sock_dgram, htons(eth_p_ip));

  629.     if (fd < 0)
  630.     {
  631.         printf("can't create socket\n");
  632.         goto err_exit;
  633.     }

  634.     /* establish handler for notification signal */
  635.     memset(&sa, 0, sizeof(struct sigaction));
  636.     sa.sa_flags = 0;
  637.     sigemptyset(&sa.sa_mask);
  638.     sa.sa_handler = handler;
  639.     if ((sigaction(sigalrm, &sa, null)) == -1)
  640.     {
  641.         printf("can't set handler for timer\n");
  642.         goto err_exit2;
  643.     }

  644.     /* send request */
  645.     id = random_id();
  646.     ret = dhcp_send_discover(fd, ifindex, hwaddr, id);
  647.     if (ret < 0)
  648.     {
  649.         printf("can't send request\n");
  650.         goto err_exit2;
  651.     }

  652.     /* start timer */
  653.     alarm(time);

  654.     /* loop, recv packets && search answer for us */
  655.     while(1)
  656.     {
  657.         ret = dhcp_recv_offer(fd, id, hwaddr);

  658.         /* answer received */
  659.         if (ret == 0)
  660.         {
  661.             ret = 1;
  662.             break;
  663.         }
  664.         /* read error */
  665.         if (ret == -1)
  666.         {
  667.             printf("read socket error\n");
  668.             break;
  669.         }

  670.         /* check timer */
  671.         if (got_alarm == 1)
  672.         {
  673.             ret = 0;
  674.             break;
  675.         }
  676.     }
  677.     /* cancel timer */
  678.     alarm(0);
  679. err_exit2:
  680.     close(fd);
  681. err_exit:
  682.     return ret;
  683. }


  684. int main(int argc, char** argv)
  685. {
  686.     if(argc < 2)
  687.     {
  688.         printf("must appoint a interface\n");
  689.         return 127;
  690.     }
  691.     return scan_dhcp(argv[1], 3);
  692. }

demo测试:


注意,需要root权限运行
阅读(1890) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图