From 5a38e49a81d035b8e39f35b6f39964b448964e29 Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Sun, 14 Nov 2010 03:41:36 -0500 Subject: [PATCH] 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. --- ndhc/dhcpd.h | 21 ++++++------ ndhc/options.c | 86 ++++++++++++++++++++++++++------------------------ ndhc/options.h | 2 +- 3 files changed, 58 insertions(+), 51 deletions(-) diff --git a/ndhc/dhcpd.h b/ndhc/dhcpd.h index 864a223..8e4fd05 100644 --- a/ndhc/dhcpd.h +++ b/ndhc/dhcpd.h @@ -5,13 +5,6 @@ #include #include -/************************************/ -/* 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!! */ /*****************************************************************/ @@ -42,11 +35,13 @@ #define DHCP_IP_TTL 0x17 #define DHCP_MTU 0x1a #define DHCP_BROADCAST 0x1c +#define DHCP_NIS_DOMAIN 0x28 +#define DHCP_NIS_SERVER 0x29 #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_OPTION_OVERLOAD 0x34 #define DHCP_MESSAGE_TYPE 0x35 #define DHCP_SERVER_ID 0x36 #define DHCP_PARAM_REQ 0x37 @@ -56,7 +51,15 @@ #define DHCP_T2 0x3b #define DHCP_VENDOR 0x3c #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 { BOOTREQUEST = 1, diff --git a/ndhc/options.c b/ndhc/options.c index b5c3b2b..7b61480 100644 --- a/ndhc/options.c +++ b/ndhc/options.c @@ -58,59 +58,63 @@ int option_lengths[] = { }; -/* get an option with bounds checking (warning, not aligned). */ -unsigned char *get_option(struct dhcpMessage *packet, int code) +/* Get an option with bounds checking (warning, result is not aligned) */ +uint8_t* get_option(struct dhcpMessage *packet, int code) { - int i = 0, length = DHCP_OPTIONS_BUFSIZE; - unsigned char *optionptr; - int over = 0, done = 0, curr = OPTION_FIELD; + uint8_t *optionptr; + int len, rem, overload = 0; + enum { + FILE_FIELD101 = FILE_FIELD * 0x101, + SNAME_FIELD101 = SNAME_FIELD * 0x101, + }; + /* option bytes: [code][len][data1][data2]..[dataLEN] */ optionptr = packet->options; - while (!done) { - if (i >= length) { - log_warning("bogus packet, option fields too long."); + rem = sizeof packet->options; + while (1) { + if (rem <= 0) { + log_warning("Bad packet, malformed option field."); return NULL; } - if (optionptr[i + OPT_CODE] == code) { - if (i + 1 + optionptr[i + OPT_LEN] >= length) { - log_warning("bogus packet, option fields too long."); - return NULL; + if (optionptr[OPT_CODE] == DHCP_PADDING) { + rem--; + optionptr++; + 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]) { - case DHCP_PADDING: - i++; - break; - case DHCP_OPTION_OVER: - if (i + 1 + optionptr[i + OPT_LEN] >= length) { - log_warning("bogus packet, option fields too long."); - 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; + len = 2 + optionptr[OPT_LEN]; + rem -= len; + if (rem < 0) + continue; /* complain and return NULL */ + + if (optionptr[OPT_CODE] == code) + return optionptr + OPT_DATA; + + if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD) { + overload |= optionptr[OPT_DATA]; + /* fall through */ } + optionptr += len; } return NULL; } - /* return the position of the 'end' option */ int end_option(unsigned char *optionptr) { diff --git a/ndhc/options.h b/ndhc/options.h index 9def838..9347b0a 100644 --- a/ndhc/options.h +++ b/ndhc/options.h @@ -30,7 +30,7 @@ struct dhcp_option { extern struct dhcp_option options[]; 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 add_option_string(unsigned char *optionptr, unsigned char *string); int add_simple_option(unsigned char *optionptr, unsigned char code, uint32_t data);