[ECOS] DHCP w/ Win2K server?

Hugo Tyson hmt@redhat.com
Fri Nov 30 07:08:00 GMT 2001


Hugo Tyson <hmt@redhat.com> writes:
> "Dan Conti" <danc@iobjects.com> writes:
> > Unfortunately my eCos version is a bit outdated at this point, so if i
> > gave you a patch it almost certainly wouldn't apply properly.
> 
> OK, I'll get something together for the trunk.
> 
> I believe it will be good to add that tag to all *FOUR* places DHCP sends a
> packet, DHCPSTATE_REQUESTING, RENEWING, REBINDING and the initial broadcast
> one in INIT.  'Course I'll test it, but only with LINUX dhcpd.  Comments?
> 
> I'll place a patch which should be good for anoncvs here.

And here it is; rather more than the four-times-one-liner we expected...
Please followup here if anyone sees any problems with this tag set, and
requests to add or elide specifics, or if you need real configury of this.

	- Huge


Index: net/tcpip/current/ChangeLog
===================================================================
RCS file: /home/cvs/ecc/ecc/net/tcpip/current/ChangeLog,v
retrieving revision 1.147
diff -u -5 -p -r1.147 ChangeLog
--- net/tcpip/current/ChangeLog	2001/11/29 19:10:37	1.147
+++ net/tcpip/current/ChangeLog	2001/11/30 14:16:25
@@ -1,5 +1,21 @@
+2001-11-30  Hugo Tyson  <hmt@redhat.com>
+
+	* src/lib/dhcp_prot.c (set_default_dhcp_tags): New routine to
+	insert all the extra woffle we need neatly each time, keeping the
+	state machine's case arms to the real work.  The new thing this
+	sets is TAG_DHCP_PARM_REQ_LIST, with a list that matches the
+	default set we get from a LINUX dhcpd.  This is because M$ servers
+	need explicit requests for eg. TAG_GATEWAY.  Note that I have
+	included configuration to override the set of tags requested here
+	in the source, but not yet backed up by CDL - we'll see whether
+	anyone needs this.
+	(set_variable_tag): New routine to insert a variable pointed-to
+	data item rather than an int of 1,2 or 4 bytes.
+	(do_dhcp): Call set_default_dhcp_tags() every time we send a
+	packet, rather than ad hoc additions in each state.
+
 2001-11-29  Jonathan Larmour  <jlarmour@redhat.com>
 
 	* include/machine/ansi.h: No longer require BSD string function
 	compatibility macros (in fact they confuse things).
 
Index: net/tcpip/current/src/lib/dhcp_prot.c
===================================================================
RCS file: /home/cvs/ecc/ecc/net/tcpip/current/src/lib/dhcp_prot.c,v
retrieving revision 1.10
diff -u -5 -p -r1.10 dhcp_prot.c
--- net/tcpip/current/src/lib/dhcp_prot.c	2001/11/19 18:37:51	1.10
+++ net/tcpip/current/src/lib/dhcp_prot.c	2001/11/30 14:16:25
@@ -167,10 +167,54 @@ set_fixed_tag( struct bootp *ppkt,
         value >>= 8;
     }
     return true;
 }
 
+// Note that this does not permit changing the size of an extant tag.
+static int
+set_variable_tag( struct bootp *ppkt,
+               unsigned char tag,
+               cyg_uint8 *pvalue,
+               int len)
+{
+    unsigned char *op;
+
+    // Initially this will only scan the options field.
+    op = &ppkt->bp_vend[4];
+    while (*op != TAG_END) {
+        if ( op > &ppkt->bp_vend[BP_VEND_LEN-1] ) {
+            CYG_FAIL( "Oversize DHCP packet in set_variable_tag" );
+            return false;
+        }
+        if (*op == tag)                 // Found it...
+            break;
+        op += *(op+1)+2;
+    }
+    
+    if (*op == tag) { // Found it...
+        if ( *(op+1) != len ) {
+            CYG_FAIL( "Wrong size in set_variable_tag" );
+            return false;           // wrong size
+        }
+    }
+    else { // overwrite the end tag and install a new one
+        if ( op + len + 2 > &ppkt->bp_vend[BP_VEND_LEN-1] ) {
+            CYG_FAIL( "Oversize DHCP packet in set_variable_tag append" );
+            return false;
+        }
+        *op = tag;
+        *(op+1) = len;
+        *(op + len + 2) = TAG_END;
+    }
+    // and insert the value.  No order is implied.
+    op += 2;               // point to start of value
+    while ( len-- > 0 ) {
+        *op++ = *pvalue++;
+    }
+    return true;
+}
+
 // ------------------------------------------------------------------------
 // Bring up an interface enough to broadcast, before we know who we are
 
 static int
 bring_half_up(const char *intf, struct ifreq *ifrp )
@@ -404,10 +448,49 @@ static inline void new_lease( struct boo
 
     cyg_alarm_initialize( lease->alarm, lease->t1, 0 );
     cyg_alarm_enable( lease->alarm );
 }
 
+// ------------------------------------------------------------------------
+// Set all the tags we want to use when sending a packet.
+// This has expanded to a large, explicit set to interwork better
+// with a variety of DHCP servers.
+
+static void set_default_dhcp_tags( struct bootp *xmit )
+{
+    // Explicitly request full set of params that are default for LINUX
+    // dhcp servers, but not default for others.  This is rather arbitrary,
+    // but it preserves behaviour for people using those servers.
+    // Perhaps configury of this set will be needed in future?
+    //
+    // Here's the set:
+    static cyg_uint8 req_list[]  = {
+#ifdef CYGOPT_NET_DHCP_PARM_REQ_LIST_REPLACE
+        CYGOPT_NET_DHCP_PARM_REQ_LIST_REPLACE ,
+#else
+        TAG_DHCP_SERVER_ID    ,     //     DHCP server id: 10.16.19.66
+        TAG_DHCP_LEASE_TIME   ,     //     DHCP time 51: 60
+        TAG_DHCP_RENEWAL_TIME ,     //     DHCP time 58: 30
+        TAG_DHCP_REBIND_TIME  ,     //     DHCP time 59: 52
+        TAG_SUBNET_MASK       ,     //     subnet mask: 255.255.255.0
+        TAG_GATEWAY           ,     //     gateway: 10.16.19.66
+        TAG_DOMAIN_SERVER     ,     //     domain server: 10.16.19.66
+        TAG_DOMAIN_NAME       ,     //     domain name: hmt10.cambridge.redhat.com
+        TAG_IP_BROADCAST      ,     //     IP broadcast: 10.16.19.255
+#endif
+#ifdef CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL
+        CYGOPT_NET_DHCP_PARM_REQ_LIST_ADDITIONAL ,
+#endif
+    };
+
+    if ( req_list[0] ) // So that one may easily turn it all off by configury
+        set_variable_tag( xmit, TAG_DHCP_PARM_REQ_LIST,
+                          &req_list[0], sizeof( req_list ) );
+
+    // Explicitly specify our max message size.
+    set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
+}
 
 // ------------------------------------------------------------------------
 // the DHCP state machine - this does all the work
 
 int
@@ -557,12 +640,12 @@ do_dhcp(const char *intf, struct bootp *
             bcopy(ifr.ifr_hwaddr.sa_data, &xmit->bp_chaddr, xmit->bp_hlen);
             bcopy(mincookie, xmit->bp_vend, sizeof(mincookie));
 
             // remove the next line to test ability to handle bootp packets.
             set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPDISCOVER, 1 );
-
-            set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
+            // Set all the tags we want to use when sending a packet
+            set_default_dhcp_tags( xmit );
 
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_INIT sending:\n" );
             show_bootp( intf, xmit );
 #endif            
@@ -648,12 +731,12 @@ do_dhcp(const char *intf, struct bootp *
             // Fill in the BOOTP request - DHCPREQUEST packet
             xmit->bp_op = BOOTREQUEST;
             xmit->bp_flags = htons(0x8000); // BROADCAST FLAG
 
             set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 );
-            set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
-
+            // Set all the tags we want to use when sending a packet
+            set_default_dhcp_tags( xmit );
             // And this will be a new one:
             set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 );
             
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_REQUESTING sending:\n" );
@@ -765,12 +848,12 @@ do_dhcp(const char *intf, struct bootp *
             xmit->bp_flags = htons(0); // No BROADCAST FLAG
             // Use the *client* address here:
             xmit->bp_ciaddr.s_addr = xmit->bp_yiaddr.s_addr;
 
             set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 );
-            set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
-
+            // Set all the tags we want to use when sending a packet
+            set_default_dhcp_tags( xmit );
             // And this will be a new one:
             set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 );
             
             // Set unicast address to *server*
             server_addr.sin_addr.s_addr = res->bp_siaddr.s_addr;
@@ -864,12 +947,12 @@ do_dhcp(const char *intf, struct bootp *
             xmit->bp_flags = htons(0); // no BROADCAST FLAG
             // Use the *client* address here:
             xmit->bp_ciaddr.s_addr = xmit->bp_yiaddr.s_addr;
 
             set_fixed_tag( xmit, TAG_DHCP_MESS_TYPE, DHCPREQUEST, 1 );
-            set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
-
+            // Set all the tags we want to use when sending a packet
+            set_default_dhcp_tags( xmit );
             // And this will be a new one:
             set_fixed_tag( xmit, TAG_DHCP_REQ_IP, ntohl(xmit->bp_yiaddr.s_addr), 4 );
             
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_REBINDING sending:\n" );



More information about the Ecos-discuss mailing list