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/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!! */
/*****************************************************************/
@ -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,

View File

@ -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;
}
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) {
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) {
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;
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;
rem = sizeof packet->file;
continue;
}
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;
}
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)
{

View File

@ -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);