Browse Source
git-svn-id: file:///svn/pmon-all/pmon-all@98 214b0138-1524-0410-9122-e5cb4b5bc56cmaster
root
17 years ago
12 changed files with 1326 additions and 2 deletions
@ -0,0 +1,18 @@ |
|||
|
|||
all: lwdhcp |
|||
|
|||
lwdhcp: lwdhcp.o packet.o options.o |
|||
cc -o lwdhcp packet.o options.o lwdhcp.o |
|||
|
|||
lwdhcp.o: lwdhcp.c lwdhcp.h |
|||
cc -c lwdhcp.c |
|||
|
|||
packet.o: packet.c lwdhcp.h packet.h |
|||
cc -c packet.c |
|||
|
|||
options.o: options.c options.h |
|||
cc -c options.c |
|||
|
|||
clean: |
|||
-rm -f lwdhcp *.o |
|||
|
@ -0,0 +1,362 @@ |
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// //
|
|||
// Light weight DHCP client //
|
|||
// //
|
|||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
|
|||
#include <sys/param.h> |
|||
#include <sys/file.h> |
|||
#include <sys/syslog.h> |
|||
#include <sys/endian.h> |
|||
|
|||
#ifdef PMON |
|||
#ifdef KERNEL |
|||
#undef KERNEL |
|||
#include <sys/socket.h> |
|||
#include <sys/ioctl.h> |
|||
#include <netinet/in.h> |
|||
#else |
|||
#include <sys/socket.h> |
|||
#include <sys/ioctl.h> |
|||
#include <netinet/in.h> |
|||
#endif |
|||
|
|||
#define KERNEL |
|||
#include <pmon/netio/bootp.h> |
|||
#include <sys/types.h> |
|||
#include <sys/net/if.h> |
|||
#else |
|||
#include <linux/if_packet.h> |
|||
#include <linux/if_ether.h> |
|||
#include <net/if.h> |
|||
#include <sys/ioctl.h> |
|||
#include <netinet/in.h> |
|||
#endif |
|||
|
|||
#include <pmon.h> |
|||
#include <setjmp.h> |
|||
#include <signal.h> |
|||
|
|||
#include "lwdhcp.h" |
|||
#include "packet.h" |
|||
#include "options.h" |
|||
|
|||
struct client_config_t client_config; |
|||
int dhcp_request; |
|||
int fd = 0; |
|||
sig_t pre_handler = 0; |
|||
|
|||
static jmp_buf jmpb; |
|||
|
|||
static void terminate() |
|||
{ |
|||
DbgPrint("Program terminated by user.\n"); |
|||
dhcp_request = 0; |
|||
|
|||
if(fd > 0) |
|||
close(fd); |
|||
|
|||
longjmp(jmpb, 1); |
|||
} |
|||
|
|||
static void init() |
|||
{ |
|||
memset((void *)&client_config, 0, sizeof(struct client_config_t)); |
|||
|
|||
strcpy(client_config.interface, "rtl0"); |
|||
|
|||
pre_handler = signal(SIGINT, (sig_t)terminate); |
|||
} |
|||
|
|||
int listen_socket() |
|||
{ |
|||
int sock, n; |
|||
int flag; |
|||
int dwValue; |
|||
struct ifreq ifr; |
|||
struct sockaddr_in clnt; |
|||
|
|||
sock = socket(AF_INET, SOCK_DGRAM, 0); |
|||
if(sock < 0) |
|||
{ |
|||
PERROR("socket create error"); |
|||
return sock; |
|||
} |
|||
|
|||
bzero((char*)&clnt, sizeof(clnt)); |
|||
clnt.sin_family = AF_INET; |
|||
clnt.sin_port = htons(CLIENT_PORT); |
|||
clnt.sin_addr.s_addr = INADDR_ANY; |
|||
|
|||
if (bind (sock, (struct sockaddr *)&clnt, sizeof(struct sockaddr_in)) < 0) { |
|||
PERROR ("bind failed"); |
|||
close (sock); |
|||
return -1; |
|||
} |
|||
|
|||
flag = 1; |
|||
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)); |
|||
|
|||
n = 1; |
|||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&n, sizeof(n)); |
|||
|
|||
return sock; |
|||
} |
|||
|
|||
|
|||
int read_interface(char *interface, int *ifindex, uint32_t *addr, uint8_t *arp) |
|||
{ |
|||
int fd; |
|||
struct ifreq ifr; |
|||
struct sockaddr_in *our_ip; |
|||
|
|||
memset(&ifr, 0, sizeof(struct ifreq)); |
|||
if((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) >= 0) |
|||
{ |
|||
ifr.ifr_addr.sa_family = AF_INET; |
|||
|
|||
strncpy(ifr.ifr_name, interface, IFNAMSIZ-1); |
|||
|
|||
if (addr) |
|||
{ |
|||
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) |
|||
{ |
|||
our_ip = (struct sockaddr_in *) &ifr.ifr_addr; |
|||
*addr = our_ip->sin_addr.s_addr; |
|||
DbgPrint("%s (our ip) = %s\n", ifr.ifr_name, inet_ntoa(our_ip->sin_addr)); |
|||
} else |
|||
{ |
|||
PERROR("SIOCGIFADDR failed, is the interface up and configured?\n"); |
|||
close(fd); |
|||
return -1; |
|||
} |
|||
} |
|||
|
|||
//the following code needs to change the PMON source code pmon/pmon/netio/bootp.c line 101
|
|||
//int
|
|||
//getethaddr (unsigned char *eaddr, char *ifc)
|
|||
//{
|
|||
// struct ifnet *ifp;
|
|||
// struct ifaddr *ifa;
|
|||
// ......
|
|||
#ifndef PMON |
|||
if(ioctl(fd, SIOCGIFINDEX, &ifr) == 0) |
|||
{ |
|||
DbgPrint("adapter index %d\n", ifr.ifr_ifindex); |
|||
*ifindex = ifr.ifr_ifindex; |
|||
} else |
|||
{ |
|||
PERROR("SIOCGIFINDEX failed!\n"); |
|||
close(fd); |
|||
return -1; |
|||
} |
|||
#endif |
|||
|
|||
#ifndef PMON |
|||
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) |
|||
{ |
|||
memcpy(arp, ifr.ifr_hwaddr.sa_data, 6); |
|||
#else |
|||
if(getethaddr(arp, client_config.interface) >= 0) |
|||
{ |
|||
#endif |
|||
DbgPrint("adapter hardware address %02x:%02x:%02x:%02x:%02x:%02x\n", |
|||
arp[0], arp[1], arp[2], arp[3], arp[4], arp[5]); |
|||
} |
|||
else{ |
|||
PERROR("SIOCGIFHWADDR failed!\n"); |
|||
close(fd); |
|||
return -1; |
|||
} |
|||
} |
|||
else { |
|||
PERROR("socket failed!\n"); |
|||
return -1; |
|||
} |
|||
close(fd); |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int lwdhcp(int argc, char* argv[]) |
|||
{ |
|||
int xid; |
|||
fd_set fs; |
|||
int ret, totimes; |
|||
char buf[1500]; |
|||
struct sockaddr_in from; |
|||
int size = sizeof(from); |
|||
struct dhcp_packet* p; |
|||
uint8_t* dhcp_message_type; |
|||
struct timeval tv; |
|||
|
|||
if(getuid()) |
|||
{ |
|||
DbgPrint("Only root can run this program!\n"); |
|||
return 0; |
|||
} |
|||
|
|||
DbgPrint("Light weight DHCP client starts...\n"); |
|||
init(); |
|||
|
|||
if(setjmp(jmpb)) |
|||
{ |
|||
signal(SIGINT, pre_handler); |
|||
sigsetmask(0); |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
if(read_interface(client_config.interface, &client_config.ifindex, |
|||
&client_config.addr, client_config.arp) < 0) |
|||
{ |
|||
DbgPrint("read_interface error"); |
|||
return 0; |
|||
} |
|||
|
|||
if((fd = listen_socket()) < 0) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
//srand(time(NULL));
|
|||
//xid = rand();
|
|||
totimes = 3; |
|||
|
|||
tryagain: |
|||
if(send_discover(xid) < 0) |
|||
if(--totimes > 0) |
|||
goto tryagain; |
|||
else |
|||
{ |
|||
DbgPrint("Fail to send DHCPDISCOVER...\n"); |
|||
return 0; |
|||
} |
|||
|
|||
FD_ZERO(&fs); |
|||
FD_SET(fd, &fs); |
|||
tv.tv_sec = 3; |
|||
tv.tv_usec = 0; |
|||
//receiving DHCPOFFER
|
|||
while(1) |
|||
{ |
|||
dhcp_request = 1; |
|||
ret = select(fd + 1, &fs, NULL, NULL, &tv); |
|||
|
|||
if(ret == -1) |
|||
PERROR("select error"); |
|||
else if(ret == 0) |
|||
{ |
|||
if(--totimes > 0) |
|||
goto tryagain; |
|||
else |
|||
{ |
|||
dhcp_request = 0; |
|||
DbgPrint("Fail to get IP from DHCP server, it seems that there is no DHCP server.\n"); |
|||
close(fd); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
size = sizeof(from); |
|||
if(recvfrom(fd, buf, sizeof(struct dhcp_packet), (struct sockaddr *)0, &from, &size) < 0) |
|||
continue; |
|||
|
|||
dhcp_request = 0; |
|||
|
|||
p = (struct dhcp_packet *)buf; |
|||
|
|||
if(p->xid != xid) |
|||
continue; |
|||
|
|||
dhcp_message_type = get_dhcp_option(p, DHCP_MESSAGE_TYPE); |
|||
if(!dhcp_message_type) |
|||
continue; |
|||
else if(*dhcp_message_type != DHCPOFFER) |
|||
continue; |
|||
|
|||
DbgPrint("DHCPOFFER received...\n"); |
|||
break; |
|||
} |
|||
|
|||
//sending DHCPREQUEST
|
|||
send_request(xid, *((uint32_t*)(&(p->siaddr))), *((uint32_t*)(&p->yiaddr))); |
|||
|
|||
tv.tv_sec = 3; |
|||
tv.tv_usec = 0; |
|||
//receiving DHCPACK
|
|||
while(1) |
|||
{ |
|||
dhcp_request = 1; |
|||
ret = select(fd + 1, &fs, NULL, NULL, &tv); |
|||
|
|||
if(ret == -1) |
|||
PERROR("select error"); |
|||
else if(ret == 0) |
|||
{ |
|||
if(--totimes > 0) |
|||
goto tryagain; |
|||
else |
|||
{ |
|||
dhcp_request = 0; |
|||
DbgPrint("Fail to get IP from DHCP server, no ACK from DHCP server.\n"); |
|||
close(fd); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
//get_raw_packet(buf, fd);
|
|||
|
|||
size = sizeof(struct sockaddr); |
|||
recvfrom(fd, buf, sizeof(struct dhcp_packet), 0, (struct sockaddr*)&from, &size); |
|||
|
|||
dhcp_request = 0; |
|||
|
|||
if(p->xid != xid) |
|||
continue; |
|||
|
|||
dhcp_message_type = get_dhcp_option(p, DHCP_MESSAGE_TYPE); |
|||
if(!dhcp_message_type) |
|||
continue; |
|||
else if(*dhcp_message_type != DHCPACK) |
|||
continue; |
|||
|
|||
DbgPrint("DHCPACK received...\n"); |
|||
DbgPrint("IP %s obtained from the DHCP server.\n", inet_ntoa(p->yiaddr)); |
|||
break; |
|||
} |
|||
|
|||
close(fd); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
|
|||
/*
|
|||
* Command table registration |
|||
* ========================== |
|||
*/ |
|||
|
|||
static const Cmd Cmds[] = |
|||
{ |
|||
{"Network"}, |
|||
{"lwdhcp", "", 0, |
|||
"Light weight DHCP client", |
|||
lwdhcp, 1, 99, CMD_REPEAT}, |
|||
{0, 0} |
|||
}; |
|||
|
|||
static void init_cmd __P((void)) __attribute__ ((constructor)); |
|||
|
|||
static void |
|||
init_cmd() |
|||
{ |
|||
cmdlist_expand(Cmds, 1); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,80 @@ |
|||
#ifndef __LWDHCP__ |
|||
#define __LWDHCP__ |
|||
|
|||
/*
|
|||
#include <sys/param.h> |
|||
#include <sys/file.h> |
|||
#include <sys/syslog.h> |
|||
#include <sys/endian.h> |
|||
|
|||
#ifdef KERNEL |
|||
#undef KERNEL |
|||
#include <sys/socket.h> |
|||
#else |
|||
#include <sys/socket.h> |
|||
#endif |
|||
*/ |
|||
|
|||
//#include <sys/types.h>
|
|||
#include <stdio.h> |
|||
//#include <linux/types.h>
|
|||
|
|||
|
|||
#ifndef PMON |
|||
#ifndef __LINUX_TYPES_H_ |
|||
#define __LINUX_TYPES_H_ |
|||
|
|||
typedef unsigned char u8; |
|||
typedef unsigned short u16; |
|||
typedef unsigned int u32; |
|||
|
|||
typedef signed char s8; |
|||
typedef signed short s16; |
|||
typedef signed long s32; |
|||
|
|||
typedef signed int sint; |
|||
|
|||
typedef signed long slong; |
|||
#endif /* __LINUX_TYPES_H_ */ |
|||
#else |
|||
// typedef uint8_t u8;
|
|||
// typedef uint16_t u16;
|
|||
// typedef uint32_t u32;
|
|||
|
|||
#endif |
|||
|
|||
|
|||
|
|||
#define LWDHCP_DEBUG 1 |
|||
|
|||
#ifdef LWDHCP_DEBUG |
|||
#define DbgPrint(str, args...) printf(str, ##args) |
|||
#define PERROR(str) perror(str) |
|||
#else |
|||
#define DbgPrint(str, args...) |
|||
#define PERROR(str) |
|||
#endif |
|||
|
|||
|
|||
#define LWDHCP_MESSAGE 1 |
|||
|
|||
#ifdef LWDHCP_MESSAGE |
|||
#define Message(str, args...) printf(str, ##args) |
|||
#else |
|||
#define Message(str, args...) |
|||
#endif |
|||
|
|||
|
|||
struct client_config_t |
|||
{ |
|||
#define INTERFACE_MAXLEN 20 |
|||
char interface[INTERFACE_MAXLEN]; |
|||
char arp[16]; //store the MAC address
|
|||
|
|||
u_int32_t addr; |
|||
int ifindex; |
|||
}; |
|||
|
|||
extern struct client_config_t client_config; |
|||
|
|||
#endif // __LWDHCP__
|
@ -0,0 +1,233 @@ |
|||
/*
|
|||
* options.c -- DHCP server option packet tools |
|||
* Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001 |
|||
*/ |
|||
|
|||
#include <stdlib.h> |
|||
#include <string.h> |
|||
|
|||
#include "options.h" |
|||
#include "packet.h" |
|||
#include "lwdhcp.h" |
|||
|
|||
|
|||
/* supported options are easily added here */ |
|||
struct dhcp_option dhcp_options[] = { |
|||
/* name[10] flags code */ |
|||
{"subnet", OPTION_IP | OPTION_REQ, 0x01}, |
|||
{"timezone", OPTION_S32, 0x02}, |
|||
{"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, |
|||
{"timesvr", OPTION_IP | OPTION_LIST, 0x04}, |
|||
{"namesvr", OPTION_IP | OPTION_LIST, 0x05}, |
|||
{"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, |
|||
{"logsvr", OPTION_IP | OPTION_LIST, 0x07}, |
|||
{"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, |
|||
{"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, |
|||
{"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, |
|||
{"bootsize", OPTION_U16, 0x0d}, |
|||
{"domain", OPTION_STRING | OPTION_REQ, 0x0f}, |
|||
{"swapsvr", OPTION_IP, 0x10}, |
|||
//We had the possibility for the client to ask for a rootpath
|
|||
//closes http://bugs.debian.org/279110 (ericvb@debian.org)
|
|||
//{"rootpath", OPTION_STRING, 0x11},
|
|||
{"rootpath", OPTION_STRING | OPTION_REQ, 0x11}, |
|||
{"ipttl", OPTION_U8, 0x17}, |
|||
{"mtu", OPTION_U16, 0x1a}, |
|||
{"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, |
|||
{"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, |
|||
{"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, |
|||
{"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, |
|||
{"wins", OPTION_IP | OPTION_LIST, 0x2c}, |
|||
{"requestip", OPTION_IP, 0x32}, |
|||
{"lease", OPTION_U32, 0x33}, |
|||
{"dhcptype", OPTION_U8, 0x35}, |
|||
{"serverid", OPTION_IP, 0x36}, |
|||
{"message", OPTION_STRING, 0x38}, |
|||
{"tftp", OPTION_STRING, 0x42}, |
|||
{"bootfile", OPTION_STRING, 0x43}, |
|||
{"wpad", OPTION_STRING, 0xfc}, |
|||
{"", 0x00, 0x00} |
|||
}; |
|||
|
|||
/* Lengths of the different option types */ |
|||
int option_lengths[] = { |
|||
[OPTION_IP] = 4, |
|||
[OPTION_IP_PAIR] = 8, |
|||
[OPTION_BOOLEAN] = 1, |
|||
[OPTION_STRING] = 1, |
|||
[OPTION_U8] = 1, |
|||
[OPTION_U16] = 2, |
|||
[OPTION_S16] = 2, |
|||
[OPTION_U32] = 4, |
|||
[OPTION_S32] = 4 |
|||
}; |
|||
|
|||
|
|||
/* get an option with bounds checking (warning, not aligned). */ |
|||
uint8_t *get_dhcp_option(struct dhcp_packet *packet, int code) |
|||
{ |
|||
int i, length; |
|||
uint8_t *optionptr; |
|||
int over = 0, done = 0, curr = OPTION_FIELD; |
|||
|
|||
optionptr = packet->options; |
|||
i = 0; |
|||
length = 308; |
|||
while (!done) { |
|||
if (i >= length) { |
|||
DbgPrint("bogus packet, option fields too long.\n"); |
|||
return NULL; |
|||
} |
|||
if (optionptr[i + OPT_CODE] == code) { |
|||
if (i + 1 + optionptr[i + OPT_LEN] >= length) { |
|||
DbgPrint("bogus packet, option fields too long.\n"); |
|||
return NULL; |
|||
} |
|||
return optionptr + i + 2; |
|||
} |
|||
switch (optionptr[i + OPT_CODE]) { |
|||
case DHCP_PADDING: |
|||
i++; |
|||
break; |
|||
case DHCP_OPTION_OVER: |
|||
if (i + 1 + optionptr[i + OPT_LEN] >= length) { |
|||
DbgPrint("bogus packet, option fields too long.\n"); |
|||
return NULL; |
|||
} |
|||
over = optionptr[i + 3]; |
|||
i += optionptr[OPT_LEN] + 2; |
|||
break; |
|||
case DHCP_END: |
|||
if (curr == OPTION_FIELD && over & FILE_FIELD) { |
|||
optionptr = packet->file; |
|||
i = 0; |
|||
length = 128; |
|||
curr = FILE_FIELD; |
|||
} else if (curr == FILE_FIELD && over & SNAME_FIELD) { |
|||
optionptr = packet->sname; |
|||
i = 0; |
|||
length = 64; |
|||
curr = SNAME_FIELD; |
|||
} else done = 1; |
|||
break; |
|||
default: |
|||
i += optionptr[OPT_LEN + i] + 2; |
|||
} |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
|
|||
/* return the position of the 'end' option (no bounds checking) */ |
|||
int end_option(uint8_t *optionptr) |
|||
{ |
|||
int i = 0; |
|||
|
|||
while (optionptr[i] != DHCP_END) { |
|||
if (optionptr[i] == DHCP_PADDING) i++; |
|||
else i += optionptr[i + OPT_LEN] + 2; |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
|
|||
/* add an option string to the options (an option string contains an option code,
|
|||
* length, then data) */ |
|||
int add_option_string(uint8_t *optionptr, uint8_t *string) |
|||
{ |
|||
int end = end_option(optionptr); |
|||
|
|||
/* end position + string length + option code/length + end option */ |
|||
if (end + string[OPT_LEN] + 2 + 1 >= 308) { |
|||
DbgPrint("Option 0x%02x did not fit into the packet!\n", string[OPT_CODE]); |
|||
return 0; |
|||
} |
|||
//DbgPrint("adding option 0x%02x\n", string[OPT_CODE]);
|
|||
memcpy(optionptr + end, string, string[OPT_LEN] + 2); |
|||
optionptr[end + string[OPT_LEN] + 2] = DHCP_END; |
|||
return string[OPT_LEN] + 2; |
|||
} |
|||
|
|||
|
|||
/* add a one to four byte option to a packet */ |
|||
int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data) |
|||
{ |
|||
char length = 0; |
|||
int i; |
|||
uint8_t option[2 + 4]; |
|||
uint8_t *u8; |
|||
uint16_t *u16; |
|||
uint32_t *u32; |
|||
uint32_t aligned; |
|||
u8 = (uint8_t *) &aligned; |
|||
u16 = (uint16_t *) &aligned; |
|||
u32 = &aligned; |
|||
|
|||
for (i = 0; dhcp_options[i].code; i++) |
|||
if (dhcp_options[i].code == code) { |
|||
length = option_lengths[dhcp_options[i].flags & TYPE_MASK]; |
|||
} |
|||
|
|||
if (!length) { |
|||
DbgPrint("Could not add option 0x%02x\n", code); |
|||
return 0; |
|||
} |
|||
|
|||
option[OPT_CODE] = code; |
|||
option[OPT_LEN] = length; |
|||
|
|||
switch (length) { |
|||
case 1: *u8 = data; break; |
|||
case 2: *u16 = data; break; |
|||
case 4: *u32 = data; break; |
|||
} |
|||
memcpy(option + 2, &aligned, length); |
|||
return add_option_string(optionptr, option); |
|||
} |
|||
|
|||
|
|||
/* find option 'code' in opt_list */ |
|||
struct option_set *find_option(struct option_set *opt_list, char code) |
|||
{ |
|||
while (opt_list && opt_list->data[OPT_CODE] < code) |
|||
opt_list = opt_list->next; |
|||
|
|||
if (opt_list && opt_list->data[OPT_CODE] == code) return opt_list; |
|||
else return NULL; |
|||
} |
|||
|
|||
|
|||
/* add an option to the opt_list */ |
|||
void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length) |
|||
{ |
|||
struct option_set *existing, *new, **curr; |
|||
|
|||
/* add it to an existing option */ |
|||
if ((existing = find_option(*opt_list, option->code))) { |
|||
DbgPrint("Attaching option %s to existing member of list\n", option->name); |
|||
if (option->flags & OPTION_LIST) { |
|||
if (existing->data[OPT_LEN] + length <= 255) { |
|||
existing->data = realloc(existing->data, |
|||
existing->data[OPT_LEN] + length + 2); |
|||
memcpy(existing->data + existing->data[OPT_LEN] + 2, buffer, length); |
|||
existing->data[OPT_LEN] += length; |
|||
} /* else, ignore the data, we could put this in a second option in the future */ |
|||
} /* else, ignore the new data */ |
|||
} else { |
|||
DbgPrint("Attaching option %s to list\n", option->name); |
|||
|
|||
/* make a new option */ |
|||
new = malloc(sizeof(struct option_set)); |
|||
new->data = malloc(length + 2); |
|||
new->data[OPT_CODE] = option->code; |
|||
new->data[OPT_LEN] = length; |
|||
memcpy(new->data + 2, buffer, length); |
|||
|
|||
curr = opt_list; |
|||
while (*curr && (*curr)->data[OPT_CODE] < option->code) |
|||
curr = &(*curr)->next; |
|||
|
|||
new->next = *curr; |
|||
*curr = new; |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
/* options.h */ |
|||
#ifndef _OPTIONS_H |
|||
#define _OPTIONS_H |
|||
|
|||
#include "packet.h" |
|||
|
|||
#define TYPE_MASK 0x0F |
|||
|
|||
enum { |
|||
OPTION_IP=1, |
|||
OPTION_IP_PAIR, |
|||
OPTION_STRING, |
|||
OPTION_BOOLEAN, |
|||
OPTION_U8, |
|||
OPTION_U16, |
|||
OPTION_S16, |
|||
OPTION_U32, |
|||
OPTION_S32 |
|||
}; |
|||
|
|||
#define OPTION_REQ 0x10 /* have the client request this option */ |
|||
#define OPTION_LIST 0x20 /* There can be a list of 1 or more of these */ |
|||
|
|||
struct dhcp_option { |
|||
char name[10]; |
|||
char flags; |
|||
uint8_t code; |
|||
}; |
|||
|
|||
|
|||
struct option_set { |
|||
uint8_t *data; |
|||
struct option_set *next; |
|||
}; |
|||
|
|||
struct static_lease { |
|||
uint8_t *mac; |
|||
uint32_t *ip; |
|||
struct static_lease *next; |
|||
}; |
|||
|
|||
|
|||
extern struct dhcp_option dhcp_options[]; |
|||
extern int option_lengths[]; |
|||
|
|||
uint8_t *get_option(struct dhcp_packet *packet, int code); |
|||
int end_option(uint8_t *optionptr); |
|||
int add_option_string(uint8_t *optionptr, uint8_t *string); |
|||
int add_simple_option(uint8_t *optionptr, uint8_t code, uint32_t data); |
|||
struct option_set *find_option(struct option_set *opt_list, char code); |
|||
void attach_option(struct option_set **opt_list, struct dhcp_option *option, char *buffer, int length); |
|||
|
|||
#endif |
@ -0,0 +1,249 @@ |
|||
#include <sys/param.h> |
|||
#include <sys/file.h> |
|||
#include <sys/syslog.h> |
|||
#include <sys/endian.h> |
|||
|
|||
#ifdef KERNEL |
|||
#undef KERNEL |
|||
#include <sys/socket.h> |
|||
#include <sys/ioctl.h> |
|||
#include <netinet/in.h> |
|||
#else |
|||
#include <sys/socket.h> |
|||
#include <sys/ioctl.h> |
|||
#include <netinet/in.h> |
|||
#endif |
|||
|
|||
#include <termio.h> |
|||
#include <stdlib.h> |
|||
#include <time.h> |
|||
#include <unistd.h> |
|||
#include <netinet/in.h> |
|||
#include <arpa/inet.h> |
|||
#include <fcntl.h> |
|||
#include <string.h> |
|||
|
|||
#include "packet.h" |
|||
#include "lwdhcp.h" |
|||
#include "options.h" |
|||
|
|||
void init_header(struct dhcp_packet *packet, char type) |
|||
{ |
|||
memset(packet, 0, sizeof(struct dhcp_packet)); |
|||
switch (type) { |
|||
case DHCPDISCOVER: |
|||
case DHCPREQUEST: |
|||
case DHCPRELEASE: |
|||
case DHCPINFORM: |
|||
packet->op = BOOTREQUEST; |
|||
break; |
|||
case DHCPOFFER: |
|||
case DHCPACK: |
|||
case DHCPNAK: |
|||
packet->op = BOOTREPLY; |
|||
} |
|||
packet->htype = ETH_10MB; |
|||
packet->hlen = ETH_10MB_LEN; |
|||
packet->cookie = htonl(DHCP_MAGIC); |
|||
packet->options[0] = DHCP_END; |
|||
add_simple_option(packet->options, DHCP_MESSAGE_TYPE, type); |
|||
} |
|||
|
|||
|
|||
/* initialize a packet with the proper defaults */ |
|||
static void init_packet(struct dhcp_packet *packet, char type) |
|||
{ |
|||
init_header(packet, type); |
|||
|
|||
memcpy(packet->chaddr, client_config.arp, 6); |
|||
} |
|||
|
|||
|
|||
uint16_t checksum(void *addr, int count) |
|||
{ |
|||
/* Compute Internet Checksum for "count" bytes
|
|||
* beginning at location "addr". |
|||
*/ |
|||
register int32_t sum = 0; |
|||
uint16_t *source = (uint16_t *) addr; |
|||
|
|||
while (count > 1) { |
|||
/* This is the inner loop */ |
|||
sum += *source++; |
|||
count -= 2; |
|||
} |
|||
|
|||
/* Add left-over byte, if any */ |
|||
if (count > 0) { |
|||
/* Make sure that the left-over byte is added correctly both
|
|||
* with little and big endian hosts */ |
|||
uint16_t tmp = 0; |
|||
*(uint8_t *) (&tmp) = * (uint8_t *) source; |
|||
sum += tmp; |
|||
} |
|||
/* Fold 32-bit sum to 16 bits */ |
|||
while (sum >> 16) |
|||
sum = (sum & 0xffff) + (sum >> 16); |
|||
|
|||
return ~sum; |
|||
} |
|||
|
|||
|
|||
|
|||
#ifndef PMON |
|||
int raw_packet(struct dhcp_packet *payload, uint32_t source_ip, int source_port, |
|||
uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex) |
|||
{ |
|||
int fd; |
|||
int result; |
|||
struct sockaddr_ll dest; |
|||
struct udp_dhcp_packet packet; |
|||
|
|||
if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { |
|||
perror("socket call failed"); |
|||
return -1; |
|||
} |
|||
|
|||
memset(&dest, 0, sizeof(dest)); |
|||
memset(&packet, 0, sizeof(packet)); |
|||
|
|||
dest.sll_family = AF_PACKET; |
|||
dest.sll_protocol = htons(ETH_P_IP); |
|||
dest.sll_ifindex = ifindex; |
|||
dest.sll_halen = 6; |
|||
memcpy(dest.sll_addr, dest_arp, 6); |
|||
if (bind(fd, (struct sockaddr *)&dest, sizeof(struct sockaddr_ll)) < 0) |
|||
{ |
|||
perror("bind call failed"); |
|||
close(fd); |
|||
return -1; |
|||
} |
|||
packet.ip.protocol = IPPROTO_UDP; |
|||
packet.ip.saddr = source_ip; |
|||
packet.ip.daddr = dest_ip; |
|||
packet.udp.source = htons(source_port); |
|||
packet.udp.dest = htons(dest_port); |
|||
packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcp_packet)); /* cheat on the psuedo-header */ |
|||
packet.ip.tot_len = packet.udp.len; |
|||
memcpy(&(packet.data), payload, sizeof(struct dhcp_packet)); |
|||
packet.udp.check = checksum(&packet, sizeof(struct udp_dhcp_packet)); |
|||
|
|||
packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); |
|||
packet.ip.ihl = sizeof(packet.ip) >> 2; |
|||
packet.ip.version = IPVERSION; |
|||
packet.ip.ttl = IPDEFTTL; |
|||
packet.ip.check = checksum(&(packet.ip), sizeof(packet.ip)); |
|||
|
|||
result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, (struct sockaddr *) &dest, sizeof(dest)); |
|||
if (result <= 0) { |
|||
perror("write on socket failed"); |
|||
} |
|||
close(fd); |
|||
return result; |
|||
} |
|||
#else |
|||
int raw_packet(struct dhcp_packet *payload, uint32_t source_ip, int source_port, |
|||
uint32_t dest_ip, int dest_port, uint8_t *dest_arp, int ifindex) |
|||
{ |
|||
int n; |
|||
int sock; |
|||
struct sockaddr_in clnt, srvr; |
|||
|
|||
sock = socket(AF_INET, SOCK_DGRAM, 0); |
|||
if (sock < 0) { |
|||
perror ("bootp socket"); |
|||
return -1; |
|||
} |
|||
|
|||
n = 1; |
|||
if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &n, sizeof (n)) < 0) { |
|||
perror ("bootp setsockopt(BROADCAST)"); |
|||
close (sock); |
|||
return -1; |
|||
} |
|||
/*
|
|||
if (setsockopt (sock, SOL_SOCKET, SO_DONTROUTE, &n, sizeof (n)) < 0) { |
|||
perror ("bootp setsockopt(DONTROUTE)"); |
|||
close (sock); |
|||
return -1; |
|||
}*/ |
|||
|
|||
bzero((char *)&clnt, sizeof(clnt)); |
|||
clnt.sin_family = AF_INET; |
|||
clnt.sin_port = htons(CLIENT_PORT+2); |
|||
clnt.sin_addr.s_addr = INADDR_ANY; |
|||
|
|||
if (bind (sock, (struct sockaddr *)&clnt, sizeof(clnt)) < 0) { |
|||
PERROR ("bind failed"); |
|||
close (sock); |
|||
return -1; |
|||
} |
|||
|
|||
//change_promisc(sock, 0);
|
|||
|
|||
bzero ((char *)&srvr, sizeof (srvr)); |
|||
srvr.sin_family = AF_INET; |
|||
srvr.sin_addr.s_addr = INADDR_BROADCAST; |
|||
srvr.sin_port = htons (SERVER_PORT); |
|||
|
|||
n = sendto(sock, payload, sizeof(struct dhcp_packet), 0, (struct sockaddr *)&srvr, sizeof(srvr)); |
|||
if(n < 0) |
|||
{ |
|||
PERROR("sendto failed"); |
|||
close(sock); |
|||
return -1; |
|||
} |
|||
|
|||
close(sock); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
#endif |
|||
|
|||
|
|||
/* Add a parameter request list for stubborn DHCP servers. Pull the data
|
|||
* from the struct in options.c. Don't do bounds checking here because it |
|||
* goes towards the head of the packet. */ |
|||
static void add_requests(struct dhcp_packet *packet) |
|||
{ |
|||
int end = end_option(packet->options); |
|||
int i, len = 0; |
|||
|
|||
packet->options[end + OPT_CODE] = DHCP_PARAM_REQ; |
|||
for (i = 0; dhcp_options[i].code; i++) |
|||
if (dhcp_options[i].flags & OPTION_REQ) |
|||
packet->options[end + OPT_DATA + len++] = dhcp_options[i].code; |
|||
packet->options[end + OPT_LEN] = len; |
|||
packet->options[end + OPT_DATA + len] = DHCP_END; |
|||
|
|||
} |
|||
|
|||
int send_request(unsigned long xid, uint32_t server, uint32_t requested_ip) |
|||
{ |
|||
struct dhcp_packet packet; |
|||
|
|||
init_packet(&packet, DHCPREQUEST); |
|||
packet.xid = xid; |
|||
|
|||
add_simple_option(packet.options, DHCP_SERVER_ID, server); |
|||
add_simple_option(packet.options, DHCP_REQUESTED_IP, requested_ip); |
|||
|
|||
DbgPrint("Sending DHCPREQUEST...\n"); |
|||
|
|||
return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, |
|||
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); |
|||
} |
|||
|
|||
int send_discover(unsigned long xid) |
|||
{ |
|||
struct dhcp_packet packet; |
|||
|
|||
init_packet(&packet, DHCPDISCOVER); |
|||
packet.xid = xid; |
|||
|
|||
DbgPrint("Sending DHCPDISCOVER...\n"); |
|||
return raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, |
|||
SERVER_PORT, MAC_BCAST_ADDR, client_config.ifindex); |
|||
} |
|||
|
@ -0,0 +1,309 @@ |
|||
#ifndef __LWDHCP_PACKET__ |
|||
#define __LWDHCP_PACKET__ |
|||
|
|||
#undef KERNEL |
|||
#include <sys/param.h> |
|||
#include <sys/queue.h> |
|||
#include <sys/time.h> |
|||
#include <netinet/in_systm.h> |
|||
#include <netinet/in.h> |
|||
//#include <netinet/ip.h>
|
|||
//#include <netinet/udp.h>
|
|||
|
|||
|
|||
/* DHCP protocol -- see RFC 2131 */ |
|||
#define SERVER_PORT 67 |
|||
#define CLIENT_PORT 68 |
|||
|
|||
#define DHCP_MAGIC 0x63825363 |
|||
|
|||
/* DHCP option codes (partial list) */ |
|||
#define DHCP_PADDING 0x00 |
|||
#define DHCP_SUBNET 0x01 |
|||
#define DHCP_TIME_OFFSET 0x02 |
|||
#define DHCP_ROUTER 0x03 |
|||
#define DHCP_TIME_SERVER 0x04 |
|||
#define DHCP_NAME_SERVER 0x05 |
|||
#define DHCP_DNS_SERVER 0x06 |
|||
#define DHCP_LOG_SERVER 0x07 |
|||
#define DHCP_COOKIE_SERVER 0x08 |
|||
#define DHCP_LPR_SERVER 0x09 |
|||
#define DHCP_HOST_NAME 0x0c |
|||
#define DHCP_BOOT_SIZE 0x0d |
|||
#define DHCP_DOMAIN_NAME 0x0f |
|||
#define DHCP_SWAP_SERVER 0x10 |
|||
#define DHCP_ROOT_PATH 0x11 |
|||
#define DHCP_IP_TTL 0x17 |
|||
#define DHCP_MTU 0x1a |
|||
#define DHCP_BROADCAST 0x1c |
|||
#define DHCP_NTP_SERVER 0x2a |
|||
#define DHCP_WINS_SERVER 0x2c |
|||
#define DHCP_REQUESTED_IP 0x32 |
|||
#define DHCP_LEASE_TIME 0x33 |
|||
#define DHCP_OPTION_OVER 0x34 |
|||
#define DHCP_MESSAGE_TYPE 0x35 |
|||
#define DHCP_SERVER_ID 0x36 |
|||
#define DHCP_PARAM_REQ 0x37 |
|||
#define DHCP_MESSAGE 0x38 |
|||
#define DHCP_MAX_SIZE 0x39 |
|||
#define DHCP_T1 0x3a |
|||
#define DHCP_T2 0x3b |
|||
#define DHCP_VENDOR 0x3c |
|||
#define DHCP_CLIENT_ID 0x3d |
|||
#define DHCP_FQDN 0x51 |
|||
|
|||
#define DHCP_END 0xFF |
|||
|
|||
|
|||
#define BOOTREQUEST 1 |
|||
#define BOOTREPLY 2 |
|||
|
|||
#define ETH_10MB 1 |
|||
#define ETH_10MB_LEN 6 |
|||
|
|||
#define DHCPDISCOVER 1 |
|||
#define DHCPOFFER 2 |
|||
#define DHCPREQUEST 3 |
|||
#define DHCPDECLINE 4 |
|||
#define DHCPACK 5 |
|||
#define DHCPNAK 6 |
|||
#define DHCPRELEASE 7 |
|||
#define DHCPINFORM 8 |
|||
|
|||
#define BROADCAST_FLAG 0x8000 |
|||
|
|||
#define OPTION_FIELD 0 |
|||
#define FILE_FIELD 1 |
|||
#define SNAME_FIELD 2 |
|||
|
|||
|
|||
#define DHCP_UDP_OVERHEAD (20 + /* IP header */ \ |
|||
8) /* UDP header */ |
|||
#define DHCP_SNAME_LEN 64 |
|||
#define DHCP_FILE_LEN 128 |
|||
#define DHCP_FIXED_NON_UDP 236 |
|||
#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD) |
|||
/* Everything but options. */ |
|||
#define DHCP_MTU_MAX 1500 |
|||
#define DHCP_OPTION_LEN (308) //(DHCP_MTU_MAX - DHCP_FIXED_LEN)
|
|||
|
|||
#define BOOTP_MIN_LEN 300 |
|||
#define DHCP_MIN_LEN 548 |
|||
|
|||
|
|||
|
|||
/* miscellaneous defines */ |
|||
#define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff" |
|||
#define OPT_CODE 0 |
|||
#define OPT_LEN 1 |
|||
#define OPT_DATA 2 |
|||
|
|||
|
|||
|
|||
|
|||
struct dhcp_packet { |
|||
u_int8_t op; /* 0: Message opcode/type */ |
|||
u_int8_t htype; /* 1: Hardware addr type (net/if_types.h) */ |
|||
u_int8_t hlen; /* 2: Hardware addr length */ |
|||
u_int8_t hops; /* 3: Number of relay agent hops from client */ |
|||
u_int32_t xid; /* 4: Transaction ID */ |
|||
u_int16_t secs; /* 8: Seconds since client started looking */ |
|||
u_int16_t flags; /* 10: Flag bits */ |
|||
struct in_addr ciaddr; /* 12: Client IP address (if already in use) */ |
|||
struct in_addr yiaddr; /* 16: Client IP address */ |
|||
struct in_addr siaddr; /* 18: IP address of next server to talk to */ |
|||
struct in_addr giaddr; /* 20: DHCP relay agent IP address */ |
|||
unsigned char chaddr [16]; /* 24: Client hardware address */ |
|||
char sname [DHCP_SNAME_LEN]; /* 40: Server name */ |
|||
char file [DHCP_FILE_LEN]; /* 104: Boot filename */ |
|||
u_int32_t cookie; |
|||
unsigned char options [DHCP_OPTION_LEN - 4]; |
|||
/* 212: Optional parameters
|
|||
(actual length dependent on MTU). */ |
|||
}; |
|||
|
|||
#define IPVERSION 4 |
|||
|
|||
struct iphdr |
|||
{ |
|||
#if __BYTE_ORDER == __LITTLE_ENDIAN |
|||
unsigned int ihl:4; |
|||
unsigned int version:4; |
|||
#elif __BYTE_ORDER == __BIG_ENDIAN |
|||
unsigned int version:4; |
|||
unsigned int ihl:4; |
|||
#else |
|||
# error "Please fix <bits/endian.h>" |
|||
#endif |
|||
u_int8_t tos; |
|||
u_int16_t tot_len; |
|||
u_int16_t id; |
|||
u_int16_t frag_off; |
|||
u_int8_t ttl; |
|||
u_int8_t protocol; |
|||
u_int16_t check; |
|||
u_int32_t saddr; |
|||
u_int32_t daddr; |
|||
/*The options start here. */ |
|||
}; |
|||
|
|||
|
|||
/* UDP header as specified by RFC 768, August 1980. */ |
|||
#ifdef __FAVOR_BSD |
|||
|
|||
struct udphdr |
|||
{ |
|||
u_int16_t uh_sport; /* source port */ |
|||
u_int16_t uh_dport; /* destination port */ |
|||
u_int16_t uh_ulen; /* udp length */ |
|||
u_int16_t uh_sum; /* udp checksum */ |
|||
}; |
|||
|
|||
#else |
|||
|
|||
struct udphdr |
|||
{ |
|||
u_int16_t source; |
|||
u_int16_t dest; |
|||
u_int16_t len; |
|||
u_int16_t check; |
|||
}; |
|||
#endif |
|||
|
|||
|
|||
|
|||
|
|||
struct udp_dhcp_packet { |
|||
struct iphdr ip; |
|||
struct udphdr udp; |
|||
struct dhcp_packet data; |
|||
}; |
|||
|
|||
|
|||
/* BOOTP (rfc951) message types */ |
|||
#define BOOTREQUEST 1 |
|||
#define BOOTREPLY 2 |
|||
|
|||
/* Possible values for flags field... */ |
|||
#define BOOTP_BROADCAST 32768L |
|||
|
|||
/* Possible values for hardware type (htype) field... */ |
|||
#define HTYPE_ETHER 1 /* Ethernet 10Mbps */ |
|||
#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */ |
|||
#define HTYPE_FDDI 8 /* FDDI... */ |
|||
|
|||
/* Magic cookie validating dhcp options field (and bootp vendor
|
|||
extensions field). */ |
|||
#define DHCP_OPTIONS_COOKIE "\143\202\123\143" |
|||
|
|||
/* DHCP Option codes: */ |
|||
|
|||
#define DHO_PAD 0 |
|||
#define DHO_SUBNET_MASK 1 |
|||
#define DHO_TIME_OFFSET 2 |
|||
#define DHO_ROUTERS 3 |
|||
#define DHO_TIME_SERVERS 4 |
|||
#define DHO_NAME_SERVERS 5 |
|||
#define DHO_DOMAIN_NAME_SERVERS 6 |
|||
#define DHO_LOG_SERVERS 7 |
|||
#define DHO_COOKIE_SERVERS 8 |
|||
#define DHO_LPR_SERVERS 9 |
|||
#define DHO_IMPRESS_SERVERS 10 |
|||
#define DHO_RESOURCE_LOCATION_SERVERS 11 |
|||
#define DHO_HOST_NAME 12 |
|||
#define DHO_BOOT_SIZE 13 |
|||
#define DHO_MERIT_DUMP 14 |
|||
#define DHO_DOMAIN_NAME 15 |
|||
#define DHO_SWAP_SERVER 16 |
|||
#define DHO_ROOT_PATH 17 |
|||
#define DHO_EXTENSIONS_PATH 18 |
|||
#define DHO_IP_FORWARDING 19 |
|||
#define DHO_NON_LOCAL_SOURCE_ROUTING 20 |
|||
#define DHO_POLICY_FILTER 21 |
|||
#define DHO_MAX_DGRAM_REASSEMBLY 22 |
|||
#define DHO_DEFAULT_IP_TTL 23 |
|||
#define DHO_PATH_MTU_AGING_TIMEOUT 24 |
|||
#define DHO_PATH_MTU_PLATEAU_TABLE 25 |
|||
#define DHO_INTERFACE_MTU 26 |
|||
#define DHO_ALL_SUBNETS_LOCAL 27 |
|||
#define DHO_BROADCAST_ADDRESS 28 |
|||
#define DHO_PERFORM_MASK_DISCOVERY 29 |
|||
#define DHO_MASK_SUPPLIER 30 |
|||
#define DHO_ROUTER_DISCOVERY 31 |
|||
#define DHO_ROUTER_SOLICITATION_ADDRESS 32 |
|||
#define DHO_STATIC_ROUTES 33 |
|||
#define DHO_TRAILER_ENCAPSULATION 34 |
|||
#define DHO_ARP_CACHE_TIMEOUT 35 |
|||
#define DHO_IEEE802_3_ENCAPSULATION 36 |
|||
#define DHO_DEFAULT_TCP_TTL 37 |
|||
#define DHO_TCP_KEEPALIVE_INTERVAL 38 |
|||
#define DHO_TCP_KEEPALIVE_GARBAGE 39 |
|||
#define DHO_NIS_DOMAIN 40 |
|||
#define DHO_NIS_SERVERS 41 |
|||
#define DHO_NTP_SERVERS 42 |
|||
#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43 |
|||
#define DHO_NETBIOS_NAME_SERVERS 44 |
|||
#define DHO_NETBIOS_DD_SERVER 45 |
|||
#define DHO_NETBIOS_NODE_TYPE 46 |
|||
#define DHO_NETBIOS_SCOPE 47 |
|||
#define DHO_FONT_SERVERS 48 |
|||
#define DHO_X_DISPLAY_MANAGER 49 |
|||
#define DHO_DHCP_REQUESTED_ADDRESS 50 |
|||
#define DHO_DHCP_LEASE_TIME 51 |
|||
#define DHO_DHCP_OPTION_OVERLOAD 52 |
|||
#define DHO_DHCP_MESSAGE_TYPE 53 |
|||
#define DHO_DHCP_SERVER_IDENTIFIER 54 |
|||
#define DHO_DHCP_PARAMETER_REQUEST_LIST 55 |
|||
#define DHO_DHCP_MESSAGE 56 |
|||
#define DHO_DHCP_MAX_MESSAGE_SIZE 57 |
|||
#define DHO_DHCP_RENEWAL_TIME 58 |
|||
#define DHO_DHCP_REBINDING_TIME 59 |
|||
#define DHO_VENDOR_CLASS_IDENTIFIER 60 |
|||
#define DHO_DHCP_CLIENT_IDENTIFIER 61 |
|||
#define DHO_NWIP_DOMAIN_NAME 62 |
|||
#define DHO_NWIP_SUBOPTIONS 63 |
|||
#define DHO_USER_CLASS 77 |
|||
#define DHO_FQDN 81 |
|||
#define DHO_DHCP_AGENT_OPTIONS 82 |
|||
#define DHO_SUBNET_SELECTION 118 /* RFC3011! */ |
|||
/* The DHO_AUTHENTICATE option is not a standard yet, so I've
|
|||
allocated an option out of the "local" option space for it on a |
|||
temporary basis. Once an option code number is assigned, I will |
|||
immediately and shamelessly break this, so don't count on it |
|||
continuing to work. */ |
|||
#define DHO_AUTHENTICATE 210 |
|||
|
|||
#define DHO_END 255 |
|||
|
|||
/* DHCP message types. */ |
|||
#define DHCPDISCOVER 1 |
|||
#define DHCPOFFER 2 |
|||
#define DHCPREQUEST 3 |
|||
#define DHCPDECLINE 4 |
|||
#define DHCPACK 5 |
|||
#define DHCPNAK 6 |
|||
#define DHCPRELEASE 7 |
|||
#define DHCPINFORM 8 |
|||
|
|||
/* Relay Agent Information option subtypes: */ |
|||
#define RAI_CIRCUIT_ID 1 |
|||
#define RAI_REMOTE_ID 2 |
|||
#define RAI_AGENT_ID 3 |
|||
|
|||
/* FQDN suboptions: */ |
|||
#define FQDN_NO_CLIENT_UPDATE 1 |
|||
#define FQDN_SERVER_UPDATE 2 |
|||
#define FQDN_ENCODED 3 |
|||
#define FQDN_RCODE1 4 |
|||
#define FQDN_RCODE2 5 |
|||
#define FQDN_HOSTNAME 6 |
|||
#define FQDN_DOMAINNAME 7 |
|||
#define FQDN_FQDN 8 |
|||
#define FQDN_SUBOPTION_COUNT 8 |
|||
|
|||
|
|||
extern int send_request(unsigned long xid, uint32_t server, uint32_t requested_ip); |
|||
extern int send_discover(unsigned long xid); |
|||
extern int get_raw_packet(struct dhcp_packet *payload, int fd); |
|||
|
|||
#endif // __LWDHCP_PACKET__
|
Loading…
Reference in new issue