在一些网络环境中,需要用到DHCP服务探测技术,动态调整本地dhcp服务的。本文提供一个探测的demo实现。
原理:
发送DHCP discover 报文,如果能够接受到 DHCP offer回应,则可以获取到服务信息。
代码如下:
-
#include <errno.h>
-
#include <unistd.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <stddef.h>
-
#include <time.h>
-
#include <string.h>
-
#include <signal.h>
-
#include <sys/ioctl.h>
-
#include <arpa/inet.h>
-
#include <netpacket/packet.h>
-
#include <netinet/if_ether.h>
-
#include <netinet/ip.h>
-
#include <netinet/udp.h>
-
#include <linux/if.h>
-
-
#define MAX_WAIT_TIME 15
-
#define MAX_ERROR_LENGTH 1500
-
-
/* Endianness check */
-
#define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100)
-
-
-
/* DHCP protocol. RFC 2131, RFC 2132 */
-
#define DHCP_MAGIC 0x63825363
-
#define DHCP_FIXED_LEN 240 /* with DHCP magic */
-
#define DHCP_UDP_OVERHEAD 28 /* IP + UDP headers */
-
#define DHCP_MTU_MAX 1500
-
#define DHCP_MTU_MIN 576
-
#define DHCP_OPTIONS_BUF_MIN (DHCP_MTU_MIN - DHCP_FIXED_LEN - DHCP_UDP_OVERHEAD)
-
#define DHCP_OPTIONS_BUF_MAX (DHCP_MTU_MAX - DHCP_FIXED_LEN - DHCP_UDP_OVERHEAD)
-
-
#define BOOTREQUEST 1
-
#define BOOTREPLY 2
-
-
/* DHCP Ports and Addresses */
-
#define CLIENT_PORT 68
-
#define SERVER_PORT 67
-
-
/* DHCP packet */
-
struct dhcp_packet
-
{
-
uint8_t op; /* BOOTREQUEST or BOOTREPLY */
-
uint8_t htype; /* hardware address type. 1 = 10Mb ethernet */
-
uint8_t hlen; /* hardware address length */
-
uint8_t hops; /* used by relay agents only */
-
uint32_t xid; /* unuque id */
-
uint16_t secs; /* seconds since client started looking */
-
uint16_t flags; /* only one flag */
-
uint32_t ciaddr; /* clients IP address (if already in use) */
-
uint32_t yiaddr; /* client IP address */
-
uint32_t siaddr_nip; /* next server used in bootstrap */
-
uint32_t gateway_nip; /* relay agent IP address */
-
uint8_t chaddr[16]; /* MAC address of client */
-
uint8_t sname[64]; /* server host name (ASCIZ) */
-
uint8_t file[128]; /* boot file name (ASCIIZ) */
-
uint32_t cookie; /* fixed first four option bytes (99, 130, 83, 99 dec) */
-
uint8_t options[DHCP_OPTIONS_BUF_MAX];
-
};
-
-
/* IP packet with DHCP */
-
struct ip_udp_dhcp_packet
-
{
-
struct iphdr ip; /* IP header */
-
struct udphdr udp; /* UDP header */
-
struct dhcp_packet data; /* UDP payload */
-
};
-
-
/* UDP packet with DHCP */
-
struct udp_dhcp_packet
-
{
-
struct udphdr udp; /* UDP header */
-
struct dhcp_packet data; /* UDP payload */
-
};
-
-
/* Packets size */
-
enum
-
{
-
IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet),
-
UDP_DHCP_SIZE = sizeof(struct udp_dhcp_packet),
-
DHCP_SIZE = sizeof(struct dhcp_packet),
-
};
-
-
/* DHCP options codes */
-
#define DHCP_PADDING 0x00
-
#define DHCP_SUBNET 0x01
-
#define DHCP_ROUTER 0x03
-
#define DHCP_DNS 0x06
-
#define DHCP_BROADCAST 0x1c
-
#define DHCP_STATIC 0x21
-
#define DHCP_NTP 0x2a
-
#define DHCP_VENDOR 0x2b
-
#define DHCP_NETBIOS_NAME_SRV 0x2c
-
#define DHCP_LEASE_TIME 0x33
-
#define DHCP_OVERLOAD 0x34
-
#define DHCP_MESSAGE_TYPE 0x35
-
#define DHCP_SERVER_ID 0x36 /* DHCP server IP */
-
#define DHCP_PARAM_REQ 0x37 /* list of options client wants */
-
#define DHCP_MAX_SIZE 0x39
-
#define DHCP_RENEWAL_TIME 0x3a
-
#define DHCP_REBINDING_TIME 0x3b
-
#define DHCP_VENDOR_CLASS_ID 0x3c
-
#define DHCP_CLIENT_ID 0x3d /* client's MAC addr*/
-
#define DHCP_SIP 0x78
-
#define DHCP_CLASSLESS_STATIC 0x79
-
#define DHCP_END 0xff
-
-
/* DHCP_MESSAGE_TYPE values */
-
#define DHCPDISCOVER 1 /* client -> server */
-
#define DHCPOFFER 2 /* client <- server */
-
-
/* Offsets in option byte sequence */
-
#define OPT_CODE 0
-
#define OPT_LEN 1
-
#define OPT_DATA 2
-
-
/* Bits in "overload" option */
-
#define OPTION_FIELD 0
-
#define FILE_FIELD 1
-
#define SNAME_FIELD 2
-
-
-
static volatile sig_atomic_t got_alarm = 0;
-
-
/**
-
* Get MAC address of interface.
-
*
-
* @param ifname Interface name.
-
* @param addr Array for MAC address.
-
*
-
* @return -1 on failure, 0 on success.
-
*/
-
int get_if_mac(const char* ifname, uint8_t addr[ETH_ALEN])
-
{
-
/* Copy interface name into ifreq */
-
struct ifreq ifr;
-
memset(&ifr, 0, sizeof(struct ifreq));
-
-
size_t if_name_len = strlen(ifname);
-
-
if (if_name_len < sizeof(ifr.ifr_name))
-
{
-
memcpy(ifr.ifr_name, ifname, if_name_len);
-
ifr.ifr_name[if_name_len] = 0;
-
}
-
else
-
{
-
return -1;
-
}
-
-
/* Create socket */
-
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
-
-
if (fd < 0)
-
{
-
return -1;
-
}
-
-
/* Get hw address */
-
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
-
{
-
close (fd);
-
return -1;
-
}
-
-
close(fd);
-
memcpy (addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
-
return 0;
-
}
-
-
-
/**
-
* Get Interface index.
-
*
-
* @param ifname Interface name.
-
*
-
* @return Interface index on success, zero on failure.
-
*/
-
unsigned int get_if_index(const char* ifname)
-
{
-
/* Copy interface name into ifreq */
-
struct ifreq ifr;
-
memset(&ifr, 0, sizeof(struct ifreq));
-
-
size_t if_name_len = strlen(ifname);
-
-
if (if_name_len < sizeof(ifr.ifr_name))
-
{
-
memcpy(ifr.ifr_name, ifname, if_name_len);
-
ifr.ifr_name[if_name_len] = 0;
-
}
-
else
-
{
-
return -1;
-
}
-
-
/* Create socket */
-
int fd = socket(AF_UNIX, SOCK_DGRAM, 0);
-
-
if (fd < 0)
-
{
-
return 0;
-
}
-
-
/* Get interface index */
-
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
-
{
-
close (fd);
-
return 0;
-
}
-
-
close(fd);
-
return ifr.ifr_ifindex;
-
}
-
-
/**
-
* Calculate internet checksum.
-
*
-
* @param addr Start address.
-
* @param nleft Length in bytes.
-
*
-
* @return Checksum.
-
*/
-
uint16_t inet_chksum(uint16_t* addr, int nleft)
-
{
-
/*
-
* Algorithm is simple, using a 32 bit accumulator,
-
* we add sequential 16 bit words to it, and at the end, fold
-
* back all the carry bits from the top 16 bits into the lower
-
* 16 bits.
-
*/
-
unsigned sum = 0;
-
while (nleft > 1)
-
{
-
sum += *addr++;
-
nleft -= 2;
-
}
-
/* Mop up an odd byte, if necessary */
-
if (nleft == 1)
-
{
-
if (IS_BIG_ENDIAN)
-
sum += *(uint8_t*)addr << 8;
-
else
-
sum += *(uint8_t*)addr;
-
}
-
-
/* Add back carry outs from top 16 bits to low 16 bits */
-
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
-
sum += (sum >> 16); /* add carry */
-
-
return (uint16_t)~sum;
-
}
-
-
/**
-
* Calculate random id (unsigned 32-bit value).
-
*
-
* @param Void.
-
* @return id
-
*/
-
uint32_t random_id(void)
-
{
-
srand(time(NULL));
-
return rand();
-
}
-
-
-
/**
-
* Fill DHCP Packet.
-
*
-
* @param packet DHCP packet.
-
* @param hwaddr MAC address of interface.
-
* @return Void.
-
*/
-
static void dhcp_init_packet(struct dhcp_packet* packet, uint8_t* hwaddr)
-
{
-
unsigned index = 0;
-
-
/* DHCP header */
-
memset(packet, 0, sizeof(*packet));
-
packet->op = BOOTREQUEST;
-
packet->htype = 1; /* ethernet */
-
packet->hlen = ETH_ALEN;
-
packet->cookie = htonl(DHCP_MAGIC);
-
packet->secs = 0;
-
memcpy(packet->chaddr, hwaddr, ETH_ALEN);
-
-
/* DHCP options */
-
/* Message type */
-
packet->options[index++] = DHCP_MESSAGE_TYPE;
-
packet->options[index++] = 1; //length of option data
-
packet->options[index++] = DHCPDISCOVER;
-
-
/* Requested parameters */
-
packet->options[index++] = DHCP_PARAM_REQ;
-
packet->options[index++] = 9; // number of options
-
packet->options[index++] = DHCP_SUBNET;
-
packet->options[index++] = DHCP_ROUTER;
-
packet->options[index++] = DHCP_DNS;
-
packet->options[index++] = DHCP_BROADCAST;
-
packet->options[index++] = DHCP_STATIC;
-
packet->options[index++] = DHCP_NTP;
-
packet->options[index++] = DHCP_VENDOR;
-
packet->options[index++] = DHCP_SIP;
-
packet->options[index++] = DHCP_CLASSLESS_STATIC;
-
-
/* client id */
-
packet->options[index++] = DHCP_CLIENT_ID;
-
packet->options[index++] = ETH_ALEN + 1;
-
packet->options[index++] = 1; //ethernet
-
memcpy(&packet->options[index], hwaddr, ETH_ALEN);
-
index += ETH_ALEN;
-
-
/* end option */
-
packet->options[index] = DHCP_END;
-
}
-
-
/**
-
* Calculate position of the END option.
-
*
-
* @param optionptr Beginning of dhcp options.
-
* @return Position of 'end' option.
-
*/
-
static int dhcp_end_option(uint8_t* optionptr)
-
{
-
int i = 0;
-
while (optionptr[i] != DHCP_END)
-
{
-
if (optionptr[i] != DHCP_PADDING)
-
i += optionptr[i + OPT_LEN] + OPT_DATA - 1;
-
i++;
-
}
-
return i;
-
}
-
-
/**
-
* Get an option with bounds checking
-
*
-
* @param packet DHCP packet.
-
* @param code Option code.
-
*
-
* @return NULL or pointer to beginning of the option data.
-
*/
-
static uint8_t* dhcp_get_option(struct dhcp_packet* packet, int code)
-
{
-
uint8_t* optionptr;
-
int len;
-
int rem;
-
int overload = 0;
-
enum
-
{
-
FILE_FIELD101 = FILE_FIELD * 0x101,
-
SNAME_FIELD101 = SNAME_FIELD * 0x101,
-
};
-
-
/* option bytes: [code][len][data1][data2]...[dataLEN] */
-
optionptr = packet->options;
-
rem = sizeof(packet->options);
-
while (1)
-
{
-
if (rem <= 0)
-
{
-
return NULL;
-
}
-
if (optionptr[OPT_CODE] == DHCP_PADDING)
-
{
-
rem--;
-
optionptr++;
-
continue;
-
}
-
if (optionptr[OPT_CODE] == DHCP_END)
-
{
-
if ((overload & FILE_FIELD101) == FILE_FIELD)
-
{
-
/* we can use packet->file */
-
overload |= FILE_FIELD101;
-
optionptr = packet->file;
-
rem = sizeof(packet->file);
-
continue;
-
}
-
if ((overload & SNAME_FIELD101) == SNAME_FIELD)
-
{
-
/* we can use packet->sname */
-
overload |= SNAME_FIELD101;
-
optionptr = packet->sname;
-
rem = sizeof(packet->sname);
-
continue;
-
}
-
break;
-
}
-
len = OPT_DATA + optionptr[OPT_LEN];
-
rem -= len;
-
if (rem < 0)
-
continue;
-
-
if (optionptr[OPT_CODE] == code)
-
return optionptr + OPT_DATA;
-
-
if (optionptr[OPT_CODE] == DHCP_OVERLOAD)
-
overload |= optionptr[OPT_DATA];
-
-
optionptr += len;
-
}
-
-
return NULL;
-
}
-
-
/**
-
* Send DHCP DISCOVER
-
*
-
* @param fd Socket descriptor.
-
* @param ifindex Interface index.
-
* @param hwaddr MAC address of interface.
-
* @param id Unique ID.
-
*
-
* @return Number of bytes sent on success, -1 on error.
-
*/
-
static int dhcp_send_discover(int fd, int ifindex, uint8_t* hwaddr, uint32_t id)
-
{
-
struct sockaddr_ll sa;
-
struct ip_udp_dhcp_packet packet;
-
unsigned padding;
-
int result = -1;
-
-
/* Bind */
-
memset(&sa, 0, sizeof(sa));
-
sa.sll_family = AF_PACKET;
-
sa.sll_protocol = htons(ETH_P_IP);
-
sa.sll_ifindex = ifindex;
-
sa.sll_halen = ETH_ALEN;
-
memset(&sa.sll_addr, 0xff, ETH_ALEN);
-
-
if (bind(fd, (struct sockaddr*)&sa, sizeof(sa)) < 0)
-
{
-
return result;
-
}
-
-
/* Craft packet */
-
memset(&packet, 0, sizeof(packet));
-
dhcp_init_packet(&packet.data, hwaddr);
-
packet.data.xid = id;
-
-
/* For badly configured servers (they drop DHCP packets > 576 octets (with ethernet header),
-
* but they may only drop packets > 576 octets without ethernet header (590 with ethernet header).
-
* RFC 1542: minimal BOOTP header 300 octets.
-
*/
-
padding = DHCP_OPTIONS_BUF_MAX - 1 - dhcp_end_option(packet.data.options);
-
if (padding > DHCP_SIZE - 300)
-
padding = DHCP_SIZE - 300;
-
-
/* IP and UDP headers */
-
packet.ip.protocol = IPPROTO_UDP;
-
packet.ip.saddr = htonl(INADDR_ANY);
-
packet.ip.daddr = htonl(INADDR_BROADCAST);
-
packet.udp.source = htons(CLIENT_PORT);
-
packet.udp.dest = htons(SERVER_PORT);
-
/* size, excluding IP header */
-
packet.udp.len = htons(UDP_DHCP_SIZE - padding);
-
/* for UDP checksumming, ip.len is set to UDP packet len */
-
packet.ip.tot_len = packet.udp.len;
-
-
packet.udp.check = inet_chksum((uint16_t*)&packet,
-
IP_UDP_DHCP_SIZE - padding);
-
/* for sending, it is set to IP packet len */
-
packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
-
packet.ip.version = IPVERSION;
-
packet.ip.ihl = sizeof(packet.ip) >> 2;
-
packet.ip.ttl = IPDEFTTL;
-
packet.ip.check = inet_chksum((uint16_t*)&packet.ip, sizeof(packet.ip));
-
-
/* Send packet */
-
result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, 0,
-
(struct sockaddr*)&sa, sizeof(sa));
-
-
return result;
-
}
-
-
-
/**
-
* Receive OFFER
-
*
-
* @param fd Socket descriptor.
-
* @param id Unique ID.
-
* @param hwaddr MAC address of interface.
-
*
-
* @return 0 on success, -1 on read error,
-
* -2 packet is not correct, -3 on EINTR (time is out).
-
*/
-
static int dhcp_recv_offer(int fd, uint32_t id, uint8_t* hwaddr)
-
{
-
int bytes;
-
struct ip_udp_dhcp_packet packet;
-
struct dhcp_packet data;
-
-
uint8_t* opt_data;
-
uint16_t check;
-
char ip_str[INET_ADDRSTRLEN];
-
uint32_t ip_addr;
-
int i;
-
-
memset(&packet, 0, sizeof(packet));
-
memset(&data, 0, sizeof(data));
-
-
/* Read packet */
-
bytes = read(fd, &packet, sizeof(packet));
-
-
if (bytes < 0)
-
{
-
if (errno == EINTR)
-
{
-
return -3;
-
}
-
else
-
{
-
return -1;
-
}
-
}
-
/* Packet is too short */
-
if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp)))
-
return -2;
-
/* Oversized packet */
-
if (bytes < (int) ntohs(packet.ip.tot_len))
-
return -2;
-
-
/* Ignore any extra garbage bytes */
-
bytes = ntohs(packet.ip.tot_len);
-
-
/* Unrelated/bogus packet */
-
if (packet.ip.protocol != IPPROTO_UDP
-
|| packet.ip.version != IPVERSION
-
|| packet.ip.ihl != (sizeof(packet.ip) >> 2)
-
|| packet.udp.dest != htons(CLIENT_PORT)
-
|| ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) )
-
return -2;
-
-
/* Verify IP checksum */
-
check = packet.ip.check;
-
packet.ip.check = 0;
-
if (check != inet_chksum((uint16_t*)&packet.ip, sizeof(packet.ip)))
-
return -2;
-
-
/* Verify UDP checksum, IP header has to be modified for this */
-
memset(&packet.ip, 0, offsetof(struct iphdr, protocol));
-
/* ip.xx fields which are not memset: protocol, check, saddr, daddr */
-
packet.ip.tot_len = packet.udp.len;
-
check = packet.udp.check;
-
packet.udp.check = 0;
-
if (check && check != inet_chksum((uint16_t*)&packet, bytes))
-
return -2;
-
-
memcpy(&data, &packet.data, sizeof(data));
-
-
/* Check DHCP magic */
-
if (bytes < (int)offsetof(struct dhcp_packet, options)
-
|| data.cookie != htonl(DHCP_MAGIC))
-
return -2;
-
-
/* Check xid */
-
if (data.xid != id)
-
return -2;
-
-
/* Ignore packets that aren't for us */
-
if (data.hlen != ETH_ALEN || memcmp(&data.chaddr, hwaddr, ETH_ALEN))
-
return -2;
-
-
/* Check message type */
-
opt_data = dhcp_get_option(&data, DHCP_MESSAGE_TYPE);
-
if (!opt_data || *opt_data != DHCPOFFER)
-
return -2;
-
-
/* print output */
-
/* Get DHCP server ID */
-
opt_data = dhcp_get_option(&data, DHCP_SERVER_ID);
-
if (opt_data)
-
{
-
ip_addr = *(uint32_t*)opt_data;
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> server:%s\n", ip_str);
-
}
-
-
/* Get netmask */
-
opt_data = dhcp_get_option(&data, DHCP_SUBNET);
-
if (opt_data)
-
{
-
ip_addr = *(uint32_t*)opt_data;
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> mask:%s\n", ip_str);
-
}
-
-
/* Get router */
-
opt_data = dhcp_get_option(&data, DHCP_ROUTER);
-
if (opt_data)
-
{
-
ip_addr = *(uint32_t*)opt_data;
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> router:%s\n", ip_str);
-
-
}
-
-
/* Get DNS servers */
-
opt_data = dhcp_get_option(&data, DHCP_DNS);
-
if (opt_data)
-
{
-
-
int num = *(opt_data - 1) >> 2; /* get number of servers */
-
for (i = 0; i < num; i++)
-
{
-
ip_addr = (*((uint32_t*)opt_data + i));
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> dns%d:%s\n", i + 1, ip_str);
-
else
-
break;
-
}
-
}
-
-
/* Get Broadcast address */
-
opt_data = dhcp_get_option(&data, DHCP_BROADCAST);
-
if (opt_data)
-
{
-
ip_addr = *(uint32_t*)opt_data;
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> broadcast:%s\n", ip_str);
-
-
}
-
/* Get NETBIOS Name servers */
-
opt_data = dhcp_get_option(&data, DHCP_NETBIOS_NAME_SRV);
-
if (opt_data)
-
{
-
int num = *(opt_data - 1) >> 2; /* get number of servers */
-
for (i = 0; i < num; i++)
-
{
-
ip_addr = *((uint32_t*)opt_data + i);
-
if (inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))
-
printf("-->> netbios%d:%s\n", i + 1, ip_str);
-
else
-
break;
-
}
-
}
-
return 0;
-
}
-
-
/**
-
* Signal handler
-
* @param Signal value.
-
*
-
* @return Void.
-
*/
-
static void handler(int sig)
-
{
-
if (sig == SIGALRM)
-
got_alarm = 1;
-
}
-
-
-
/**
-
* Search DHCP server.
-
*
-
* @param ifname Network interface name.
-
* @param time Wait time.
-
*
-
* @return 1 on success, 0 on time is out, -2 on invalid json object for result,
-
* -1 on other errors.
-
*/
-
int scan_dhcp(const char* ifname, unsigned int time)
-
{
-
int ifindex;
-
uint8_t hwaddr[ETH_ALEN];
-
struct sigaction sa;
-
uid_t euid;
-
uint32_t id;
-
int fd = -1;
-
int ret = -1;
-
-
-
/* Check superuser priveleges */
-
if ((euid = geteuid()) != 0)
-
{
-
printf( "You must be root\n");
-
goto err_exit;
-
}
-
-
/* Check input data */
-
/* Check wait time */
-
if (time == 0)
-
time = 1;
-
-
if (time > MAX_WAIT_TIME)
-
{
-
printf("Max wait time is %d\n", MAX_WAIT_TIME);
-
goto err_exit;
-
}
-
-
/* Check interface name */
-
if (!ifname || *ifname == '\0')
-
{
-
printf("Empty interface name\n");
-
goto err_exit;
-
}
-
-
/* Check interface name length */
-
if (strlen(ifname) > IFNAMSIZ)
-
{
-
printf("Interface name is too long\n");
-
goto err_exit;
-
}
-
-
/* Get interface index */
-
if ((ifindex = get_if_index(ifname)) == 0)
-
{
-
printf("No interface found\n");
-
goto err_exit;
-
}
-
-
/* Get MAC address */
-
if ((get_if_mac(ifname, hwaddr)) < 0)
-
{
-
printf( "Can't get MAC address\n");
-
goto err_exit;
-
}
-
-
/* Create socket */
-
fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
-
-
if (fd < 0)
-
{
-
printf("Can't create socket\n");
-
goto err_exit;
-
}
-
-
/* Establish handler for notification signal */
-
memset(&sa, 0, sizeof(struct sigaction));
-
sa.sa_flags = 0;
-
sigemptyset(&sa.sa_mask);
-
sa.sa_handler = handler;
-
if ((sigaction(SIGALRM, &sa, NULL)) == -1)
-
{
-
printf("Can't set handler for timer\n");
-
goto err_exit2;
-
}
-
-
/* Send Request */
-
id = random_id();
-
ret = dhcp_send_discover(fd, ifindex, hwaddr, id);
-
if (ret < 0)
-
{
-
printf("Can't send request\n");
-
goto err_exit2;
-
}
-
-
/* Start timer */
-
alarm(time);
-
-
/* Loop, recv packets && search answer for us */
-
while(1)
-
{
-
ret = dhcp_recv_offer(fd, id, hwaddr);
-
-
/* Answer received */
-
if (ret == 0)
-
{
-
ret = 1;
-
break;
-
}
-
/* Read error */
-
if (ret == -1)
-
{
-
printf("Read socket error\n");
-
break;
-
}
-
-
/* Check timer */
-
if (got_alarm == 1)
-
{
-
ret = 0;
-
break;
-
}
-
}
-
/* Cancel timer */
-
alarm(0);
-
err_exit2:
-
close(fd);
-
err_exit:
-
return ret;
-
}
-
-
-
int main(int argc, char** argv)
-
{
-
if(argc < 2)
-
{
-
printf("must appoint a interface\n");
-
return 127;
-
}
-
return scan_dhcp(argv[1], 3);
-
}
demo测试:
注意,需要root权限运行
阅读(1909) | 评论(0) | 转发(0) |