From: Roy Marples Date: Tue, 17 Jul 2007 08:34:59 +0000 (+0000) Subject: Suport DHCP option (52) overload. X-Git-Tag: v3.2.3~237 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ff711cf766f3efd9dc8f79776e688a3a28f52d9a;p=thirdparty%2Fdhcpcd.git Suport DHCP option (52) overload. --- diff --git a/ChangeLog b/ChangeLog index 2b273bfa..40a20b3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +Suport DHCP option (52) overload. Added -T test option. This just sends a DHCP_DISCOVER message and then prints the configuration data to stdout - we don't request a lease, configure the interface or write the info file. diff --git a/dhcp.c b/dhcp.c index d6dde73a..b095d2f2 100644 --- a/dhcp.c +++ b/dhcp.c @@ -474,18 +474,22 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) route_t *static_routes = NULL; route_t *static_routesp = NULL; route_t *csr = NULL; - - end += sizeof (message->options); + bool in_overload = false; + bool parse_sname = false; + bool parse_file = false; + + end += sizeof (message->options); if (gettimeofday (&tv, NULL) == -1) { logger (LOG_ERR, "gettimeofday: %s", strerror (errno)); return (-1); } + + dhcp->address.s_addr = message->yiaddr; dhcp->leasedfrom = tv.tv_sec; dhcp->frominfo = false; - dhcp->address.s_addr = message->yiaddr; - strlcpy (dhcp->servername, message->servername, + strlcpy (dhcp->servername, (char *) message->servername, sizeof (dhcp->servername)); #define LEN_ERR \ @@ -495,11 +499,15 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) continue; \ } +parse_start: while (p < end) { option = *p++; if (! option) continue; + if (option == DHCP_END) + goto eexit; + length = *p++; if (p + length >= end) { @@ -509,9 +517,6 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) } switch (option) { - case DHCP_END: - goto eexit; - case DHCP_MESSAGETYPE: retval = (int) *p; p += length; @@ -674,6 +679,18 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) } break; + case DHCP_OPTIONSOVERLOADED: + LENGTH (1); + /* The overloaded option in an overloaded option + * should be ignored, overwise we may get an infinite loop */ + if (! in_overload) { + if (*p & 1) + parse_file = true; + if (*p & 2) + parse_sname = true; + } + break; + #undef LENGTH #undef MIN_LENGTH #undef MULT_LENGTH @@ -687,6 +704,22 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) } eexit: + /* We may have options overloaded, so go back and grab them */ + if (parse_file) { + parse_file = false; + p = message->bootfile; + end = p + sizeof (message->bootfile); + in_overload = true; + goto parse_start; + } else if (parse_sname) { + parse_sname = false; + p = message->servername; + end = p + sizeof (message->servername); + memset (dhcp->servername, 0, sizeof (dhcp->servername)); + in_overload = true; + goto parse_start; + } + /* Fill in any missing fields */ if (! dhcp->netmask.s_addr) dhcp->netmask.s_addr = get_netmask (dhcp->address.s_addr); diff --git a/dhcp.h b/dhcp.h index 9b88dc34..3f5b9cda 100644 --- a/dhcp.h +++ b/dhcp.h @@ -83,6 +83,7 @@ enum DHCP_OPTIONS DHCP_NTPSERVER = 42, DHCP_ADDRESS = 50, DHCP_LEASETIME = 51, + DHCP_OPTIONSOVERLOADED = 52, DHCP_MESSAGETYPE = 53, DHCP_SERVERIDENTIFIER = 54, DHCP_PARAMETERREQUESTLIST = 55, @@ -187,8 +188,8 @@ typedef struct dhcpmessage_t int32_t siaddr; /* should be zero in client's messages */ int32_t giaddr; /* should be zero in client's messages */ unsigned char chaddr[DHCP_CHADDR_LEN]; /* client's hardware address */ - char servername[SERVERNAME_LEN]; /* server host name */ - char bootfile[BOOTFILE_LEN]; /* boot file name */ + unsigned char servername[SERVERNAME_LEN]; /* server host name */ + unsigned char bootfile[BOOTFILE_LEN]; /* boot file name */ uint32_t cookie; unsigned char options[DHCP_OPTION_LEN]; /* message options - cookie */ } dhcpmessage_t;