dhclient(8) vs Nortel NetID vs DHO_DHCP_MESSAGE_TYPE

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

dhclient(8) vs Nortel NetID vs DHO_DHCP_MESSAGE_TYPE

Kenneth R Westerback
PR#6543 reports a failure to obtain a DHCP lease. Further investigation
with the submitter has shown that the DHCP server in question (Nortel
NetID v4.5.0) is sensitive to the position of the DHO_DHCP_MESSAGE_TYPE
option.

We currently simply write out the options in numerical order, which
results in several DHCP-only (i.e. not bootp) options being written
before the DHO_DHCP_MESSAGE_TYPE option identifies the packet as
being a DHCP packet rather than a bootp packet.

The diff below ensures that the DHO_DHCP_MESSAGE_TYPE option, if
present, will be written as the very first option. This appears
to fix the problem reported in the PR, although further testing
is still pending.

The diff includes a bit of code refactoring to make clear there is
always enough room in the options area for the cookie and the
DHO_DHCP_MESSAGE_TYPE option.

Of course where there is one sensitive server there may be others.

Tests on various DHCP servers would be appreciated.

As would ok's. :-).

.... Ken

Index: dhclient.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
retrieving revision 1.140
diff -u -p -r1.140 dhclient.c
--- dhclient.c 17 Apr 2011 20:06:08 -0000 1.140
+++ dhclient.c 10 May 2011 18:41:22 -0000
@@ -1195,8 +1195,7 @@ make_discover(struct client_lease *lease
  }
 
  /* Set up the option buffer to fit in a minimal UDP packet. */
- i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
-    options);
+ i = cons_options(options);
  if (i == -1 || client->packet.options[i] != DHO_END)
  error("options do not fit in DHCPDISCOVER packet.");
  client->packet_length = DHCP_FIXED_NON_UDP+i+1;
@@ -1264,8 +1263,7 @@ make_request(struct client_lease * lease
  }
 
  /* Set up the option buffer to fit in a minimal UDP packet. */
- i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
-    options);
+ i = cons_options(options);
  if (i == -1 || client->packet.options[i] != DHO_END)
  error("options do not fit in DHCPREQUEST packet.");
  client->packet_length = DHCP_FIXED_NON_UDP+i+1;
@@ -1332,8 +1330,7 @@ make_decline(struct client_lease *lease)
  }
 
  /* Set up the option buffer to fit in a minimal UDP packet. */
- i = cons_options(client->packet.options, 576 - DHCP_FIXED_LEN,
-    options);
+ i = cons_options(options);
  if (i == -1 || client->packet.options[i] != DHO_END)
  error("options do not fit in DHCPDECLINE packet.");
  client->packet_length = DHCP_FIXED_NON_UDP+i+1;
Index: dhcp.h
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhcp.h,v
retrieving revision 1.8
diff -u -p -r1.8 dhcp.h
--- dhcp.h 15 Oct 2010 09:51:15 -0000 1.8
+++ dhcp.h 10 May 2011 18:41:22 -0000
@@ -86,7 +86,8 @@ struct dhcp_packet {
 
 /* Magic cookie validating dhcp options field (and bootp vendor
    extensions field). */
-#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+#define DHCP_OPTIONS_MESSAGE_TYPE "\065\001\000"
 
 /* DHCP Option codes: */
 
Index: dhcpd.h
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhcpd.h,v
retrieving revision 1.72
diff -u -p -r1.72 dhcpd.h
--- dhcpd.h 4 Apr 2011 11:14:52 -0000 1.72
+++ dhcpd.h 10 May 2011 18:41:22 -0000
@@ -207,7 +207,7 @@ extern struct client_state *client;
 extern struct client_config *config;
 
 /* options.c */
-int cons_options(unsigned char *, const int, struct option_data *);
+int cons_options(struct option_data *);
 char *pretty_print_option(unsigned int, unsigned char *, int, int, int);
 void do_packet(int, unsigned int, struct iaddr, struct hardware *);
 
Index: options.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/options.c,v
retrieving revision 1.38
diff -u -p -r1.38 options.c
--- options.c 17 Apr 2011 19:57:23 -0000 1.38
+++ options.c 10 May 2011 18:41:22 -0000
@@ -131,18 +131,24 @@ parse_option_buffer(struct option_data *
  * to see if it's DHO_END to decide if all the options were copied.
  */
 int
-cons_options(unsigned char *buf, const int buflen, struct option_data *options)
+cons_options(struct option_data *options)
 {
+ unsigned char *buf = client->packet.options;
+ int buflen = 576 - DHCP_FIXED_LEN;
  int ix, incr, length, bufix, code, lastopt = -1;
 
  bzero(buf, buflen);
 
- if (buflen > 3)
- memcpy(buf, DHCP_OPTIONS_COOKIE, 4);
- bufix = 4;
+ memcpy(buf, DHCP_OPTIONS_COOKIE, 4);
+ if (options[DHO_DHCP_MESSAGE_TYPE].data) {
+ memcpy(&buf[4], DHCP_OPTIONS_MESSAGE_TYPE, 3);
+ buf[6] = options[DHO_DHCP_MESSAGE_TYPE].data[0];
+ bufix = 7;
+ } else
+ bufix = 4;
 
  for (code = DHO_SUBNET_MASK; code < DHO_END; code++) {
- if (!options[code].data)
+ if (!options[code].data || code == DHO_DHCP_MESSAGE_TYPE)
  continue;
 
  length = options[code].len;