aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-11-28 19:23:12 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-11-28 19:23:12 +0000
commit35ff74676b54b1cae5a6324d2517568393fedbc8 (patch)
treeb913eda3005954aec3543cc07d3f86baeeb6429a
parent41f5add965163607b5921aa224b9ba6fa3debc05 (diff)
downloadbusybox-w32-35ff74676b54b1cae5a6324d2517568393fedbc8.tar.gz
busybox-w32-35ff74676b54b1cae5a6324d2517568393fedbc8.tar.bz2
busybox-w32-35ff74676b54b1cae5a6324d2517568393fedbc8.zip
dhcpc: let server know we don't like oversized packets.
add TODO comment
-rw-r--r--networking/udhcp/Config.in1
-rw-r--r--networking/udhcp/clientpacket.c3
-rw-r--r--networking/udhcp/files.c6
-rw-r--r--networking/udhcp/options.c68
-rw-r--r--networking/udhcp/options.h4
-rw-r--r--networking/udhcp/script.c23
6 files changed, 58 insertions, 47 deletions
diff --git a/networking/udhcp/Config.in b/networking/udhcp/Config.in
index 1aef69ba7..242a9f3b8 100644
--- a/networking/udhcp/Config.in
+++ b/networking/udhcp/Config.in
@@ -104,3 +104,4 @@ config UDHCPC_SLACK_FOR_BUGGY_SERVERS
104 seems to confuse maximum allowed UDP packet size with 104 seems to confuse maximum allowed UDP packet size with
105 maximum size of entire IP packet, and sends packets which are 105 maximum size of entire IP packet, and sends packets which are
106 28 bytes too large. 106 28 bytes too large.
107 Seednet (ISP) VDSL: sends packets 2 bytes too big.
diff --git a/networking/udhcp/clientpacket.c b/networking/udhcp/clientpacket.c
index 4a5c627f4..406fe340a 100644
--- a/networking/udhcp/clientpacket.c
+++ b/networking/udhcp/clientpacket.c
@@ -96,6 +96,9 @@ int send_discover(uint32_t xid, uint32_t requested)
96 if (requested) 96 if (requested)
97 add_simple_option(packet.options, DHCP_REQUESTED_IP, requested); 97 add_simple_option(packet.options, DHCP_REQUESTED_IP, requested);
98 98
99 /* Explicitly saying that we want RFC-compliant packets helps
100 * some buggy DHCP servers to NOT send bigger packets */
101 add_simple_option(packet.options, DHCP_MAX_SIZE, htons(576));
99 add_requests(&packet); 102 add_requests(&packet);
100 bb_info_msg("Sending discover..."); 103 bb_info_msg("Sending discover...");
101 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, 104 return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,
diff --git a/networking/udhcp/files.c b/networking/udhcp/files.c
index 59a5e4ab2..5026598d7 100644
--- a/networking/udhcp/files.c
+++ b/networking/udhcp/files.c
@@ -90,7 +90,7 @@ static void attach_option(struct option_set **opt_list,
90 90
91 existing = find_option(*opt_list, option->code); 91 existing = find_option(*opt_list, option->code);
92 if (!existing) { 92 if (!existing) {
93 DEBUG("Attaching option %s to list", option->name); 93 DEBUG("Attaching option %02x to list", option->code);
94 94
95#if ENABLE_FEATURE_RFC3397 95#if ENABLE_FEATURE_RFC3397
96 if ((option->flags & TYPE_MASK) == OPTION_STR1035) 96 if ((option->flags & TYPE_MASK) == OPTION_STR1035)
@@ -119,7 +119,7 @@ static void attach_option(struct option_set **opt_list,
119 } 119 }
120 120
121 /* add it to an existing option */ 121 /* add it to an existing option */
122 DEBUG("Attaching option %s to existing member of list", option->name); 122 DEBUG("Attaching option %02x to existing member of list", option->code);
123 if (option->flags & OPTION_LIST) { 123 if (option->flags & OPTION_LIST) {
124#if ENABLE_FEATURE_RFC3397 124#if ENABLE_FEATURE_RFC3397
125 if ((option->flags & TYPE_MASK) == OPTION_STR1035) 125 if ((option->flags & TYPE_MASK) == OPTION_STR1035)
@@ -170,7 +170,7 @@ static int read_opt(const char *const_line, void *arg)
170 while (1) { 170 while (1) {
171 if (!option->code) 171 if (!option->code)
172 return 0; 172 return 0;
173 if (!strcasecmp(option->name, opt)) 173 if (!strcasecmp(option->opt_name, opt))
174 break; 174 break;
175 option++; 175 option++;
176 } 176 }
diff --git a/networking/udhcp/options.c b/networking/udhcp/options.c
index 6744e2ad0..ffc0ed127 100644
--- a/networking/udhcp/options.c
+++ b/networking/udhcp/options.c
@@ -9,37 +9,42 @@
9#include "options.h" 9#include "options.h"
10 10
11 11
12/* supported options are easily added here */ 12/* Supported options are easily added here */
13const struct dhcp_option dhcp_options[] = { 13const struct dhcp_option dhcp_options[] = {
14 /* name[12] flags code */ 14 /* opt_name[12] flags code */
15 {"subnet", OPTION_IP | OPTION_REQ, 0x01}, 15 {"subnet", OPTION_IP | OPTION_REQ, 0x01}, /* DHCP_SUBNET */
16 {"timezone", OPTION_S32, 0x02}, 16 {"timezone", OPTION_S32, 0x02}, /* DHCP_TIME_OFFSET */
17 {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, 17 {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, /* DHCP_ROUTER */
18 {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, 18 {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, /* DHCP_TIME_SERVER */
19 {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, 19 {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, /* DHCP_NAME_SERVER */
20 {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, 20 {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, /* DHCP_DNS_SERVER */
21 {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, 21 {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, /* DHCP_LOG_SERVER */
22 {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, 22 {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, /* DHCP_COOKIE_SERVER */
23 {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, 23 {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, /* DHCP_LPR_SERVER */
24 {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, 24 {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, /* DHCP_HOST_NAME */
25 {"bootsize", OPTION_U16, 0x0d}, 25 {"bootsize", OPTION_U16, 0x0d}, /* DHCP_BOOT_SIZE */
26 {"domain", OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, 26 {"domain", OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, /* DHCP_DOMAIN_NAME */
27 {"swapsvr", OPTION_IP, 0x10}, 27 {"swapsvr", OPTION_IP, 0x10}, /* DHCP_SWAP_SERVER */
28 {"rootpath", OPTION_STRING, 0x11}, 28 {"rootpath", OPTION_STRING, 0x11}, /* DHCP_ROOT_PATH */
29 {"ipttl", OPTION_U8, 0x17}, 29 {"ipttl", OPTION_U8, 0x17}, /* DHCP_IP_TTL */
30 {"mtu", OPTION_U16, 0x1a}, 30 {"mtu", OPTION_U16, 0x1a}, /* DHCP_MTU */
31 {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, 31 {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, /* DHCP_BROADCAST */
32 {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, 32 {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, /* DHCP_NTP_SERVER */
33 {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, 33 {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, /* DHCP_WINS_SERVER */
34 {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, 34 {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, /* DHCP_REQUESTED_IP */
35 {"wins", OPTION_IP | OPTION_LIST, 0x2c}, 35 {"wins", OPTION_IP | OPTION_LIST, 0x2c}, /* DHCP_LEASE_TIME */
36 {"requestip", OPTION_IP, 0x32}, 36 {"requestip", OPTION_IP, 0x32}, /* DHCP_OPTION_OVER */
37 {"lease", OPTION_U32, 0x33}, 37 {"lease", OPTION_U32, 0x33}, /* DHCP_MESSAGE_TYPE */
38 {"dhcptype", OPTION_U8, 0x35}, 38 {"dhcptype", OPTION_U8, 0x35}, /* DHCP_SERVER_ID */
39 {"serverid", OPTION_IP, 0x36}, 39 {"serverid", OPTION_IP, 0x36}, /* DHCP_PARAM_REQ */
40 {"message", OPTION_STRING, 0x38}, 40 {"message", OPTION_STRING, 0x38}, /* DHCP_MESSAGE */
41 {"vendorclass", OPTION_STRING, 0x3C}, 41// TODO: 1) some options should not be parsed & passed to script -
42 {"clientid", OPTION_STRING, 0x3D}, 42// maxsize sure should not, since it cannot appear in server responses!
43// grep for opt_name is fix the mess.
44// 2) Using fixed-sized char[] vector wastes space.
45 {"maxsize", OPTION_U16, 0x39}, /* DHCP_MAX_SIZE */
46 {"vendorclass", OPTION_STRING, 0x3C}, /* DHCP_VENDOR */
47 {"clientid", OPTION_STRING, 0x3D}, /* DHCP_CLIENT_ID */
43 {"tftp", OPTION_STRING, 0x42}, 48 {"tftp", OPTION_STRING, 0x42},
44 {"bootfile", OPTION_STRING, 0x43}, 49 {"bootfile", OPTION_STRING, 0x43},
45 {"userclass", OPTION_STRING, 0x4D}, 50 {"userclass", OPTION_STRING, 0x4D},
@@ -48,9 +53,10 @@ const struct dhcp_option dhcp_options[] = {
48#endif 53#endif
49 /* MSIE's "Web Proxy Autodiscovery Protocol" support */ 54 /* MSIE's "Web Proxy Autodiscovery Protocol" support */
50 {"wpad", OPTION_STRING, 0xfc}, 55 {"wpad", OPTION_STRING, 0xfc},
51 {"", 0x00, 0x00} 56 {} /* zero-padded terminating entry */
52}; 57};
53 58
59
54/* Lengths of the different option types */ 60/* Lengths of the different option types */
55const unsigned char option_lengths[] ALIGN1 = { 61const unsigned char option_lengths[] ALIGN1 = {
56 [OPTION_IP] = 4, 62 [OPTION_IP] = 4,
diff --git a/networking/udhcp/options.h b/networking/udhcp/options.h
index 33a968ce9..4bf73a17e 100644
--- a/networking/udhcp/options.h
+++ b/networking/udhcp/options.h
@@ -33,6 +33,7 @@ enum {
33 33
34#define DHCP_MAGIC 0x63825363 34#define DHCP_MAGIC 0x63825363
35 35
36
36/* DHCP option codes (partial list) */ 37/* DHCP option codes (partial list) */
37#define DHCP_PADDING 0x00 38#define DHCP_PADDING 0x00
38#define DHCP_SUBNET 0x01 39#define DHCP_SUBNET 0x01
@@ -67,7 +68,6 @@ enum {
67#define DHCP_VENDOR 0x3c 68#define DHCP_VENDOR 0x3c
68#define DHCP_CLIENT_ID 0x3d 69#define DHCP_CLIENT_ID 0x3d
69#define DHCP_FQDN 0x51 70#define DHCP_FQDN 0x51
70
71#define DHCP_END 0xFF 71#define DHCP_END 0xFF
72 72
73 73
@@ -98,7 +98,7 @@ enum {
98#define OPT_DATA 2 98#define OPT_DATA 2
99 99
100struct dhcp_option { 100struct dhcp_option {
101 char name[12]; 101 char opt_name[12];
102 char flags; 102 char flags;
103 uint8_t code; 103 uint8_t code;
104}; 104};
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c
index 68de358e5..33d96e687 100644
--- a/networking/udhcp/script.c
+++ b/networking/udhcp/script.c
@@ -44,14 +44,15 @@ static int sprintip(char *dest, const char *pre, const uint8_t *ip)
44 44
45 45
46/* really simple implementation, just count the bits */ 46/* really simple implementation, just count the bits */
47static int mton(struct in_addr *mask) 47static int mton(uint32_t mask)
48{ 48{
49 int i; 49 int i = 0;
50 unsigned long bits = ntohl(mask->s_addr); 50 mask = ntohl(mask); /* 111110000-like bit pattern */
51 /* too bad one can't check the carry bit, etc in c bit 51 while (mask) {
52 * shifting */ 52 i++;
53 for (i = 0; i < 32 && !((bits >> i) & 1); i++); 53 mask <<= 1;
54 return 32 - i; 54 }
55 return i;
55} 56}
56 57
57 58
@@ -69,8 +70,8 @@ static char *alloc_fill_opts(uint8_t *option, const struct dhcp_option *type_p)
69 type = type_p->flags & TYPE_MASK; 70 type = type_p->flags & TYPE_MASK;
70 optlen = option_lengths[type]; 71 optlen = option_lengths[type];
71 72
72 dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->name) + 2); 73 dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->opt_name) + 2);
73 dest += sprintf(ret, "%s=", type_p->name); 74 dest += sprintf(ret, "%s=", type_p->opt_name);
74 75
75 for (;;) { 76 for (;;) {
76 switch (type) { 77 switch (type) {
@@ -133,7 +134,6 @@ static char **fill_envp(struct dhcpMessage *packet)
133 char **envp; 134 char **envp;
134 char *var; 135 char *var;
135 uint8_t *temp; 136 uint8_t *temp;
136 struct in_addr subnet;
137 char over = 0; 137 char over = 0;
138 138
139 if (packet) { 139 if (packet) {
@@ -179,8 +179,9 @@ static char **fill_envp(struct dhcpMessage *packet)
179 179
180 /* Fill in a subnet bits option for things like /24 */ 180 /* Fill in a subnet bits option for things like /24 */
181 if (dhcp_options[i].code == DHCP_SUBNET) { 181 if (dhcp_options[i].code == DHCP_SUBNET) {
182 uint32_t subnet;
182 memcpy(&subnet, temp, 4); 183 memcpy(&subnet, temp, 4);
183 envp[j++] = xasprintf("mask=%d", mton(&subnet)); 184 envp[j++] = xasprintf("mask=%d", mton(subnet));
184 } 185 }
185 } 186 }
186 if (packet->siaddr) { 187 if (packet->siaddr) {