Update get_option() to use the function from busybox's udhcp variant;

it's much easier to read.  The original one is indecipherable, and thus
it is difficult to verify correctness.
This commit is contained in:
Nicholas J. Kain 2010-11-14 03:41:36 -05:00
parent 1ffd1d9df3
commit 5a38e49a81
3 changed files with 58 additions and 51 deletions

View File

@ -5,13 +5,6 @@
#include <netinet/ip.h> #include <netinet/ip.h>
#include <netinet/udp.h> #include <netinet/udp.h>
/************************************/
/* Defaults _you_ may want to tweak */
/************************************/
/* the period of time the client is allowed to use that address */
#define LEASE_TIME (60*60*24*10) /* 10 days of seconds */
/*****************************************************************/ /*****************************************************************/
/* Do not modify below here unless you know what you are doing!! */ /* Do not modify below here unless you know what you are doing!! */
/*****************************************************************/ /*****************************************************************/
@ -42,11 +35,13 @@
#define DHCP_IP_TTL 0x17 #define DHCP_IP_TTL 0x17
#define DHCP_MTU 0x1a #define DHCP_MTU 0x1a
#define DHCP_BROADCAST 0x1c #define DHCP_BROADCAST 0x1c
#define DHCP_NIS_DOMAIN 0x28
#define DHCP_NIS_SERVER 0x29
#define DHCP_NTP_SERVER 0x2a #define DHCP_NTP_SERVER 0x2a
#define DHCP_WINS_SERVER 0x2c #define DHCP_WINS_SERVER 0x2c
#define DHCP_REQUESTED_IP 0x32 #define DHCP_REQUESTED_IP 0x32
#define DHCP_LEASE_TIME 0x33 #define DHCP_LEASE_TIME 0x33
#define DHCP_OPTION_OVER 0x34 #define DHCP_OPTION_OVERLOAD 0x34
#define DHCP_MESSAGE_TYPE 0x35 #define DHCP_MESSAGE_TYPE 0x35
#define DHCP_SERVER_ID 0x36 #define DHCP_SERVER_ID 0x36
#define DHCP_PARAM_REQ 0x37 #define DHCP_PARAM_REQ 0x37
@ -56,7 +51,15 @@
#define DHCP_T2 0x3b #define DHCP_T2 0x3b
#define DHCP_VENDOR 0x3c #define DHCP_VENDOR 0x3c
#define DHCP_CLIENT_ID 0x3d #define DHCP_CLIENT_ID 0x3d
#define DHCP_END 0xFF #define DHCP_TFTP_SERVER_NAME 0x42
#define DHCP_BOOT_FILE 0x43
#define DHCP_USER_CLASS 0x4d
#define DHCP_FQDN 0x51
#define DHCP_DOMAIN_SEARCH 0x77
#define DHCP_SIP_SERVERS 0x78
#define DHCP_STATIC_ROUTES 0x79
#define DHCP_WPAD 0xfc
#define DHCP_END 0xff
enum { enum {
BOOTREQUEST = 1, BOOTREQUEST = 1,

View File

@ -58,59 +58,63 @@ int option_lengths[] = {
}; };
/* get an option with bounds checking (warning, not aligned). */ /* Get an option with bounds checking (warning, result is not aligned) */
unsigned char *get_option(struct dhcpMessage *packet, int code) uint8_t* get_option(struct dhcpMessage *packet, int code)
{ {
int i = 0, length = DHCP_OPTIONS_BUFSIZE; uint8_t *optionptr;
unsigned char *optionptr; int len, rem, overload = 0;
int over = 0, done = 0, curr = OPTION_FIELD; enum {
FILE_FIELD101 = FILE_FIELD * 0x101,
SNAME_FIELD101 = SNAME_FIELD * 0x101,
};
/* option bytes: [code][len][data1][data2]..[dataLEN] */
optionptr = packet->options; optionptr = packet->options;
while (!done) { rem = sizeof packet->options;
if (i >= length) { while (1) {
log_warning("bogus packet, option fields too long."); if (rem <= 0) {
log_warning("Bad packet, malformed option field.");
return NULL; return NULL;
} }
if (optionptr[i + OPT_CODE] == code) { if (optionptr[OPT_CODE] == DHCP_PADDING) {
if (i + 1 + optionptr[i + OPT_LEN] >= length) { rem--;
log_warning("bogus packet, option fields too long."); optionptr++;
return NULL; continue;
}
if (optionptr[OPT_CODE] == DHCP_END) {
if ((overload & FILE_FIELD101) == FILE_FIELD) {
/* can use packet->file, and didn't look at it yet */
overload |= FILE_FIELD101; /* "we looked at it" */
optionptr = packet->file;
rem = sizeof packet->file;
continue;
} }
return optionptr + i + 2; if ((overload & SNAME_FIELD101) == SNAME_FIELD) {
/* can use packet->sname, and didn't look at it yet */
overload |= SNAME_FIELD101; /* "we looked at it" */
optionptr = packet->sname;
rem = sizeof packet->sname;
continue;
}
break;
} }
switch (optionptr[i + OPT_CODE]) { len = 2 + optionptr[OPT_LEN];
case DHCP_PADDING: rem -= len;
i++; if (rem < 0)
break; continue; /* complain and return NULL */
case DHCP_OPTION_OVER:
if (i + 1 + optionptr[i + OPT_LEN] >= length) { if (optionptr[OPT_CODE] == code)
log_warning("bogus packet, option fields too long."); return optionptr + OPT_DATA;
return NULL;
} if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) {
over = optionptr[i + 3]; overload |= optionptr[OPT_DATA];
i += optionptr[OPT_LEN] + 2; /* fall through */
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;
} }
optionptr += len;
} }
return NULL; return NULL;
} }
/* return the position of the 'end' option */ /* return the position of the 'end' option */
int end_option(unsigned char *optionptr) int end_option(unsigned char *optionptr)
{ {

View File

@ -30,7 +30,7 @@ struct dhcp_option {
extern struct dhcp_option options[]; extern struct dhcp_option options[];
extern int option_lengths[]; extern int option_lengths[];
unsigned char *get_option(struct dhcpMessage *packet, int code); uint8_t *get_option(struct dhcpMessage *packet, int code);
int end_option(unsigned char *optionptr); int end_option(unsigned char *optionptr);
int add_option_string(unsigned char *optionptr, unsigned char *string); int add_option_string(unsigned char *optionptr, unsigned char *string);
int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data); int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data);