]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Suport DHCP option (52) overload.
authorRoy Marples <roy@marples.name>
Tue, 17 Jul 2007 08:34:59 +0000 (08:34 +0000)
committerRoy Marples <roy@marples.name>
Tue, 17 Jul 2007 08:34:59 +0000 (08:34 +0000)
ChangeLog
dhcp.c
dhcp.h

index 2b273bfa5589f7416802c5f9cecfa7ccfad2aa24..40a20b3cf8726989932490408c95ed15cbd3d37f 100644 (file)
--- 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 d6dde73a3100fea518e25375a545a6a7fcd8284c..b095d2f26c4e46cd00c12f0c42f95769314bb488 100644 (file)
--- 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 9b88dc340d0310e5139514cc5fae87b23a887720..3f5b9cda23553154d98c99af0968bccabf2c94ca 100644 (file)
--- 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;