dhcpc: let server know we don't like oversized packets.
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 28 Nov 2007 19:23:12 +0000 (19:23 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 28 Nov 2007 19:23:12 +0000 (19:23 -0000)
add TODO comment

networking/udhcp/Config.in
networking/udhcp/clientpacket.c
networking/udhcp/files.c
networking/udhcp/options.c
networking/udhcp/options.h
networking/udhcp/script.c

index 1aef69ba70f4a1d7aa3aabe3509a27405883442a..242a9f3b8f2408d94cff8dc9594724996a09dcd9 100644 (file)
@@ -104,3 +104,4 @@ config UDHCPC_SLACK_FOR_BUGGY_SERVERS
            seems to confuse maximum allowed UDP packet size with
            maximum size of entire IP packet, and sends packets which are
            28 bytes too large.
+          Seednet (ISP) VDSL: sends packets 2 bytes too big.
index 4a5c627f4c4d95a79843e2dfddf33ff2a31b3aa2..406fe340a9e6df52db6379a684b3b2833dade708 100644 (file)
@@ -96,6 +96,9 @@ int send_discover(uint32_t xid, uint32_t requested)
        if (requested)
                add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
 
+       /* Explicitly saying that we want RFC-compliant packets helps
+        * some buggy DHCP servers to NOT send bigger packets */
+       add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576));
        add_requests(&packet);
        bb_info_msg("Sending discover...");
        return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
index 59a5e4ab2bd45d9cf9ce0dad7f2f4a681b54d0df..5026598d743b15e9c8fdadec09103985b65d1f77 100644 (file)
@@ -90,7 +90,7 @@ static void attach_option(struct option_set **opt_list,
 
        existing = find_option(*opt_list, option->code);
        if (!existing) {
-               DEBUG("Attaching option %s to list", option->name);
+               DEBUG("Attaching option %02x to list", option->code);
 
 #if ENABLE_FEATURE_RFC3397
                if ((option->flags & TYPE_MASK) == OPTION_STR1035)
@@ -119,7 +119,7 @@ static void attach_option(struct option_set **opt_list,
        }
 
        /* add it to an existing option */
-       DEBUG("Attaching option %s to existing member of list", option->name);
+       DEBUG("Attaching option %02x to existing member of list", option->code);
        if (option->flags & OPTION_LIST) {
 #if ENABLE_FEATURE_RFC3397
                if ((option->flags & TYPE_MASK) == OPTION_STR1035)
@@ -170,7 +170,7 @@ static int read_opt(const char *const_line, void *arg)
        while (1) {
                if (!option->code)
                        return 0;
-               if (!strcasecmp(option->name, opt))
+               if (!strcasecmp(option->opt_name, opt))
                        break;
                option++;
        }
index 6744e2ad0e1924b0ded286455c29ea05af0b6a6b..ffc0ed127a216b8c2ba55ab4ded44b8eb39b5a7d 100644 (file)
@@ -9,37 +9,42 @@
 #include "options.h"
 
 
-/* supported options are easily added here */
+/* Supported options are easily added here */
 const struct dhcp_option dhcp_options[] = {
-       /* name[12]     flags                                   code */
-       {"subnet",      OPTION_IP | OPTION_REQ,                 0x01},
-       {"timezone",    OPTION_S32,                             0x02},
-       {"router",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x03},
-       {"timesvr",     OPTION_IP | OPTION_LIST,                0x04},
-       {"namesvr",     OPTION_IP | OPTION_LIST,                0x05},
-       {"dns",         OPTION_IP | OPTION_LIST | OPTION_REQ,   0x06},
-       {"logsvr",      OPTION_IP | OPTION_LIST,                0x07},
-       {"cookiesvr",   OPTION_IP | OPTION_LIST,                0x08},
-       {"lprsvr",      OPTION_IP | OPTION_LIST,                0x09},
-       {"hostname",    OPTION_STRING | OPTION_REQ,             0x0c},
-       {"bootsize",    OPTION_U16,                             0x0d},
-       {"domain",      OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f},
-       {"swapsvr",     OPTION_IP,                              0x10},
-       {"rootpath",    OPTION_STRING,                          0x11},
-       {"ipttl",       OPTION_U8,                              0x17},
-       {"mtu",         OPTION_U16,                             0x1a},
-       {"broadcast",   OPTION_IP | OPTION_REQ,                 0x1c},
-       {"nisdomain",   OPTION_STRING | OPTION_REQ,             0x28},
-       {"nissrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x29},
-       {"ntpsrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x2a},
-       {"wins",        OPTION_IP | OPTION_LIST,                0x2c},
-       {"requestip",   OPTION_IP,                              0x32},
-       {"lease",       OPTION_U32,                             0x33},
-       {"dhcptype",    OPTION_U8,                              0x35},
-       {"serverid",    OPTION_IP,                              0x36},
-       {"message",     OPTION_STRING,                          0x38},
-       {"vendorclass", OPTION_STRING,                          0x3C},
-       {"clientid",    OPTION_STRING,                          0x3D},
+       /* opt_name[12] flags                                   code */
+       {"subnet",      OPTION_IP | OPTION_REQ,                 0x01},   /* DHCP_SUBNET         */
+       {"timezone",    OPTION_S32,                             0x02},   /* DHCP_TIME_OFFSET    */
+       {"router",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x03},   /* DHCP_ROUTER         */
+       {"timesvr",     OPTION_IP | OPTION_LIST,                0x04},   /* DHCP_TIME_SERVER    */
+       {"namesvr",     OPTION_IP | OPTION_LIST,                0x05},   /* DHCP_NAME_SERVER    */
+       {"dns",         OPTION_IP | OPTION_LIST | OPTION_REQ,   0x06},   /* DHCP_DNS_SERVER     */
+       {"logsvr",      OPTION_IP | OPTION_LIST,                0x07},   /* DHCP_LOG_SERVER     */
+       {"cookiesvr",   OPTION_IP | OPTION_LIST,                0x08},   /* DHCP_COOKIE_SERVER  */
+       {"lprsvr",      OPTION_IP | OPTION_LIST,                0x09},   /* DHCP_LPR_SERVER     */
+       {"hostname",    OPTION_STRING | OPTION_REQ,             0x0c},   /* DHCP_HOST_NAME      */
+       {"bootsize",    OPTION_U16,                             0x0d},   /* DHCP_BOOT_SIZE      */
+       {"domain",      OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, /* DHCP_DOMAIN_NAME    */
+       {"swapsvr",     OPTION_IP,                              0x10},   /* DHCP_SWAP_SERVER    */
+       {"rootpath",    OPTION_STRING,                          0x11},   /* DHCP_ROOT_PATH      */
+       {"ipttl",       OPTION_U8,                              0x17},   /* DHCP_IP_TTL         */
+       {"mtu",         OPTION_U16,                             0x1a},   /* DHCP_MTU            */
+       {"broadcast",   OPTION_IP | OPTION_REQ,                 0x1c},   /* DHCP_BROADCAST      */
+       {"nisdomain",   OPTION_STRING | OPTION_REQ,             0x28},   /* DHCP_NTP_SERVER     */
+       {"nissrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x29},   /* DHCP_WINS_SERVER    */
+       {"ntpsrv",      OPTION_IP | OPTION_LIST | OPTION_REQ,   0x2a},   /* DHCP_REQUESTED_IP   */
+       {"wins",        OPTION_IP | OPTION_LIST,                0x2c},   /* DHCP_LEASE_TIME     */
+       {"requestip",   OPTION_IP,                              0x32},   /* DHCP_OPTION_OVER    */
+       {"lease",       OPTION_U32,                             0x33},   /* DHCP_MESSAGE_TYPE   */
+       {"dhcptype",    OPTION_U8,                              0x35},   /* DHCP_SERVER_ID      */
+       {"serverid",    OPTION_IP,                              0x36},   /* DHCP_PARAM_REQ      */
+       {"message",     OPTION_STRING,                          0x38},   /* DHCP_MESSAGE        */
+// TODO: 1) some options should not be parsed & passed to script -
+// maxsize sure should not, since it cannot appear in server responses!
+// grep for opt_name is fix the mess.
+// 2) Using fixed-sized char[] vector wastes space.
+       {"maxsize",     OPTION_U16,                             0x39},   /* DHCP_MAX_SIZE       */
+       {"vendorclass", OPTION_STRING,                          0x3C},   /* DHCP_VENDOR         */
+       {"clientid",    OPTION_STRING,                          0x3D},   /* DHCP_CLIENT_ID      */
        {"tftp",        OPTION_STRING,                          0x42},
        {"bootfile",    OPTION_STRING,                          0x43},
        {"userclass",   OPTION_STRING,                          0x4D},
@@ -48,9 +53,10 @@ const struct dhcp_option dhcp_options[] = {
 #endif
        /* MSIE's "Web Proxy Autodiscovery Protocol" support */
        {"wpad",        OPTION_STRING,                          0xfc},
-       {"",            0x00,                                   0x00}
+       {} /* zero-padded terminating entry */
 };
 
+
 /* Lengths of the different option types */
 const unsigned char option_lengths[] ALIGN1 = {
        [OPTION_IP] =      4,
index 33a968ce977bf56881b087c164720e87a34bd060..4bf73a17e3ecbf00965dfd49f364f0d92a03b5d4 100644 (file)
@@ -33,6 +33,7 @@ enum {
 
 #define DHCP_MAGIC             0x63825363
 
+
 /* DHCP option codes (partial list) */
 #define DHCP_PADDING           0x00
 #define DHCP_SUBNET            0x01
@@ -67,7 +68,6 @@ enum {
 #define DHCP_VENDOR            0x3c
 #define DHCP_CLIENT_ID         0x3d
 #define DHCP_FQDN              0x51
-
 #define DHCP_END               0xFF
 
 
@@ -98,7 +98,7 @@ enum {
 #define OPT_DATA 2
 
 struct dhcp_option {
-       char name[12];
+       char opt_name[12];
        char flags;
        uint8_t code;
 };
index 68de358e5ac8e559c148829c04d655b226a8f651..33d96e687c7e7e16051e4c9fd63679f26e256aef 100644 (file)
@@ -44,14 +44,15 @@ static int sprintip(char *dest, const char *pre, const uint8_t *ip)
 
 
 /* really simple implementation, just count the bits */
-static int mton(struct in_addr *mask)
+static int mton(uint32_t mask)
 {
-       int i;
-       unsigned long bits = ntohl(mask->s_addr);
-       /* too bad one can't check the carry bit, etc in c bit
-        * shifting */
-       for (i = 0; i < 32 && !((bits >> i) & 1); i++);
-       return 32 - i;
+       int i = 0;
+       mask = ntohl(mask); /* 111110000-like bit pattern */
+       while (mask) {
+               i++;
+               mask <<= 1;
+       }
+       return i;
 }
 
 
@@ -69,8 +70,8 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p)
        type = type_p->flags & TYPE_MASK;
        optlen = option_lengths[type];
 
-       dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->name) + 2);
-       dest += sprintf(ret, "%s=", type_p->name);
+       dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->opt_name) + 2);
+       dest += sprintf(ret, "%s=", type_p->opt_name);
 
        for (;;) {
                switch (type) {
@@ -133,7 +134,6 @@ static char **fill_envp(struct dhcpMessage *packet)
        char **envp;
        char *var;
        uint8_t *temp;
-       struct in_addr subnet;
        char over = 0;
 
        if (packet) {
@@ -179,8 +179,9 @@ static char **fill_envp(struct dhcpMessage *packet)
 
                /* Fill in a subnet bits option for things like /24 */
                if (dhcp_options[i].code == DHCP_SUBNET) {
+                       uint32_t subnet;
                        memcpy(&subnet, temp, 4);
-                       envp[j++] = xasprintf("mask=%d", mton(&subnet));
+                       envp[j++] = xasprintf("mask=%d", mton(subnet));
                }
        }
        if (packet->siaddr) {