From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hugo Tyson To: Subject: Re: [ECOS] DHCP w/ Win2K server? Date: Fri, 30 Nov 2001 07:08:00 -0000 Message-ID: References: X-SW-Source: 2001-11/msg00436.html Message-ID: <20011130070800.hBV9T6gVP866-lpPxHhVt2hjMid4pI-kV8j5MYagCXE@z> Hugo Tyson writes: > "Dan Conti" 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 + + * 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 * 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" );