dhcpc: let server know we don't like oversized packets.

add TODO comment
This commit is contained in:
Denis Vlasenko 2007-11-28 19:23:12 +00:00
parent 41f5add965
commit 35ff74676b
6 changed files with 58 additions and 47 deletions

View File

@ -104,3 +104,4 @@ config UDHCPC_SLACK_FOR_BUGGY_SERVERS
seems to confuse maximum allowed UDP packet size with seems to confuse maximum allowed UDP packet size with
maximum size of entire IP packet, and sends packets which are maximum size of entire IP packet, and sends packets which are
28 bytes too large. 28 bytes too large.
Seednet (ISP) VDSL: sends packets 2 bytes too big.

View File

@ -96,6 +96,9 @@ int send_discover(uint32_t xid, uint32_t requested)
if (requested) if (requested)
add_simple_option(packet.options, DHCP_REQUESTED_IP, 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); add_requests(&packet);
bb_info_msg("Sending discover..."); bb_info_msg("Sending discover...");
return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST, return udhcp_raw_packet(&packet, INADDR_ANY, CLIENT_PORT, INADDR_BROADCAST,

View File

@ -90,7 +90,7 @@ static void attach_option(struct option_set **opt_list,
existing = find_option(*opt_list, option->code); existing = find_option(*opt_list, option->code);
if (!existing) { if (!existing) {
DEBUG("Attaching option %s to list", option->name); DEBUG("Attaching option %02x to list", option->code);
#if ENABLE_FEATURE_RFC3397 #if ENABLE_FEATURE_RFC3397
if ((option->flags & TYPE_MASK) == OPTION_STR1035) 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 */ /* 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 (option->flags & OPTION_LIST) {
#if ENABLE_FEATURE_RFC3397 #if ENABLE_FEATURE_RFC3397
if ((option->flags & TYPE_MASK) == OPTION_STR1035) if ((option->flags & TYPE_MASK) == OPTION_STR1035)
@ -170,7 +170,7 @@ static int read_opt(const char *const_line, void *arg)
while (1) { while (1) {
if (!option->code) if (!option->code)
return 0; return 0;
if (!strcasecmp(option->name, opt)) if (!strcasecmp(option->opt_name, opt))
break; break;
option++; option++;
} }

View File

@ -9,37 +9,42 @@
#include "options.h" #include "options.h"
/* supported options are easily added here */ /* Supported options are easily added here */
const struct dhcp_option dhcp_options[] = { const struct dhcp_option dhcp_options[] = {
/* name[12] flags code */ /* opt_name[12] flags code */
{"subnet", OPTION_IP | OPTION_REQ, 0x01}, {"subnet", OPTION_IP | OPTION_REQ, 0x01}, /* DHCP_SUBNET */
{"timezone", OPTION_S32, 0x02}, {"timezone", OPTION_S32, 0x02}, /* DHCP_TIME_OFFSET */
{"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, {"router", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x03}, /* DHCP_ROUTER */
{"timesvr", OPTION_IP | OPTION_LIST, 0x04}, {"timesvr", OPTION_IP | OPTION_LIST, 0x04}, /* DHCP_TIME_SERVER */
{"namesvr", OPTION_IP | OPTION_LIST, 0x05}, {"namesvr", OPTION_IP | OPTION_LIST, 0x05}, /* DHCP_NAME_SERVER */
{"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, {"dns", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x06}, /* DHCP_DNS_SERVER */
{"logsvr", OPTION_IP | OPTION_LIST, 0x07}, {"logsvr", OPTION_IP | OPTION_LIST, 0x07}, /* DHCP_LOG_SERVER */
{"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, {"cookiesvr", OPTION_IP | OPTION_LIST, 0x08}, /* DHCP_COOKIE_SERVER */
{"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, {"lprsvr", OPTION_IP | OPTION_LIST, 0x09}, /* DHCP_LPR_SERVER */
{"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, {"hostname", OPTION_STRING | OPTION_REQ, 0x0c}, /* DHCP_HOST_NAME */
{"bootsize", OPTION_U16, 0x0d}, {"bootsize", OPTION_U16, 0x0d}, /* DHCP_BOOT_SIZE */
{"domain", OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, {"domain", OPTION_STRING | OPTION_LIST | OPTION_REQ, 0x0f}, /* DHCP_DOMAIN_NAME */
{"swapsvr", OPTION_IP, 0x10}, {"swapsvr", OPTION_IP, 0x10}, /* DHCP_SWAP_SERVER */
{"rootpath", OPTION_STRING, 0x11}, {"rootpath", OPTION_STRING, 0x11}, /* DHCP_ROOT_PATH */
{"ipttl", OPTION_U8, 0x17}, {"ipttl", OPTION_U8, 0x17}, /* DHCP_IP_TTL */
{"mtu", OPTION_U16, 0x1a}, {"mtu", OPTION_U16, 0x1a}, /* DHCP_MTU */
{"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, {"broadcast", OPTION_IP | OPTION_REQ, 0x1c}, /* DHCP_BROADCAST */
{"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, {"nisdomain", OPTION_STRING | OPTION_REQ, 0x28}, /* DHCP_NTP_SERVER */
{"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, {"nissrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x29}, /* DHCP_WINS_SERVER */
{"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, {"ntpsrv", OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a}, /* DHCP_REQUESTED_IP */
{"wins", OPTION_IP | OPTION_LIST, 0x2c}, {"wins", OPTION_IP | OPTION_LIST, 0x2c}, /* DHCP_LEASE_TIME */
{"requestip", OPTION_IP, 0x32}, {"requestip", OPTION_IP, 0x32}, /* DHCP_OPTION_OVER */
{"lease", OPTION_U32, 0x33}, {"lease", OPTION_U32, 0x33}, /* DHCP_MESSAGE_TYPE */
{"dhcptype", OPTION_U8, 0x35}, {"dhcptype", OPTION_U8, 0x35}, /* DHCP_SERVER_ID */
{"serverid", OPTION_IP, 0x36}, {"serverid", OPTION_IP, 0x36}, /* DHCP_PARAM_REQ */
{"message", OPTION_STRING, 0x38}, {"message", OPTION_STRING, 0x38}, /* DHCP_MESSAGE */
{"vendorclass", OPTION_STRING, 0x3C}, // TODO: 1) some options should not be parsed & passed to script -
{"clientid", OPTION_STRING, 0x3D}, // 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}, {"tftp", OPTION_STRING, 0x42},
{"bootfile", OPTION_STRING, 0x43}, {"bootfile", OPTION_STRING, 0x43},
{"userclass", OPTION_STRING, 0x4D}, {"userclass", OPTION_STRING, 0x4D},
@ -48,9 +53,10 @@ const struct dhcp_option dhcp_options[] = {
#endif #endif
/* MSIE's "Web Proxy Autodiscovery Protocol" support */ /* MSIE's "Web Proxy Autodiscovery Protocol" support */
{"wpad", OPTION_STRING, 0xfc}, {"wpad", OPTION_STRING, 0xfc},
{"", 0x00, 0x00} {} /* zero-padded terminating entry */
}; };
/* Lengths of the different option types */ /* Lengths of the different option types */
const unsigned char option_lengths[] ALIGN1 = { const unsigned char option_lengths[] ALIGN1 = {
[OPTION_IP] = 4, [OPTION_IP] = 4,

View File

@ -33,6 +33,7 @@ enum {
#define DHCP_MAGIC 0x63825363 #define DHCP_MAGIC 0x63825363
/* DHCP option codes (partial list) */ /* DHCP option codes (partial list) */
#define DHCP_PADDING 0x00 #define DHCP_PADDING 0x00
#define DHCP_SUBNET 0x01 #define DHCP_SUBNET 0x01
@ -67,7 +68,6 @@ enum {
#define DHCP_VENDOR 0x3c #define DHCP_VENDOR 0x3c
#define DHCP_CLIENT_ID 0x3d #define DHCP_CLIENT_ID 0x3d
#define DHCP_FQDN 0x51 #define DHCP_FQDN 0x51
#define DHCP_END 0xFF #define DHCP_END 0xFF
@ -98,7 +98,7 @@ enum {
#define OPT_DATA 2 #define OPT_DATA 2
struct dhcp_option { struct dhcp_option {
char name[12]; char opt_name[12];
char flags; char flags;
uint8_t code; uint8_t code;
}; };

View File

@ -44,14 +44,15 @@ static int sprintip(char *dest, const char *pre, const uint8_t *ip)
/* really simple implementation, just count the bits */ /* really simple implementation, just count the bits */
static int mton(struct in_addr *mask) static int mton(uint32_t mask)
{ {
int i; int i = 0;
unsigned long bits = ntohl(mask->s_addr); mask = ntohl(mask); /* 111110000-like bit pattern */
/* too bad one can't check the carry bit, etc in c bit while (mask) {
* shifting */ i++;
for (i = 0; i < 32 && !((bits >> i) & 1); i++); mask <<= 1;
return 32 - i; }
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; type = type_p->flags & TYPE_MASK;
optlen = option_lengths[type]; optlen = option_lengths[type];
dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->name) + 2); dest = ret = xmalloc(upper_length(len, type) + strlen(type_p->opt_name) + 2);
dest += sprintf(ret, "%s=", type_p->name); dest += sprintf(ret, "%s=", type_p->opt_name);
for (;;) { for (;;) {
switch (type) { switch (type) {
@ -133,7 +134,6 @@ static char **fill_envp(struct dhcpMessage *packet)
char **envp; char **envp;
char *var; char *var;
uint8_t *temp; uint8_t *temp;
struct in_addr subnet;
char over = 0; char over = 0;
if (packet) { if (packet) {
@ -179,8 +179,9 @@ static char **fill_envp(struct dhcpMessage *packet)
/* Fill in a subnet bits option for things like /24 */ /* Fill in a subnet bits option for things like /24 */
if (dhcp_options[i].code == DHCP_SUBNET) { if (dhcp_options[i].code == DHCP_SUBNET) {
uint32_t subnet;
memcpy(&subnet, temp, 4); memcpy(&subnet, temp, 4);
envp[j++] = xasprintf("mask=%d", mton(&subnet)); envp[j++] = xasprintf("mask=%d", mton(subnet));
} }
} }
if (packet->siaddr) { if (packet->siaddr) {