This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RedBoot - more DHCP twiddling


It seems some DHCP servers are truly stubborn, whilst 
others are more forgiving...

-- 
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.136
diff -u -5 -p -r1.136 ChangeLog
--- redboot/current/ChangeLog	24 Sep 2003 15:30:14 -0000	1.136
+++ redboot/current/ChangeLog	25 Sep 2003 23:49:36 -0000
@@ -1,5 +1,10 @@
+2003-09-25  Gary Thomas  <gary@mlbassoc.com>
+
+	* src/net/bootp.c: Rework DHCP process to handle really stubborn
+	servers.
+
 2003-09-24  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/net/bootp.c (__bootp_find_local_ip): Forgot to unregister
 	UDP handler - could cause serious problems later!  Also, fix
 	problem with retries after DHCP discovery phase.
Index: redboot/current/src/net/bootp.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/net/bootp.c,v
retrieving revision 1.16
diff -u -5 -p -r1.16 bootp.c
--- redboot/current/src/net/bootp.c	24 Sep 2003 15:30:15 -0000	1.16
+++ redboot/current/src/net/bootp.c	25 Sep 2003 23:48:43 -0000
@@ -58,12 +58,12 @@
 #include <net/bootp.h>
 
 #define SHOULD_BE_RANDOM  0x12345555
 
 /* How many milliseconds to wait before retrying the request */
-#define RETRY_TIME   500
-#define MAX_RETRIES   30
+#define RETRY_TIME  2000
+#define MAX_RETRIES    8
 
 static bootp_header_t *bp_info;
   
 #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP
 static const unsigned char dhcpCookie[] = {99,130,83,99};
@@ -71,10 +71,11 @@ static const unsigned char dhcpEnd[] = {
 static const unsigned char dhcpDiscover[] = {53,1,1};
 static const unsigned char dhcpOffer[] = {53,1,2};
 static const unsigned char dhcpRequest[] = {53,1,3};
 static const unsigned char dhcpRequestIP[] = {50,4};
 static const unsigned char dhcpAck[] = {53,1,5};
+static const unsigned char dhcpNak[] = {53,1,6};
 static const unsigned char dhcpParamRequestList[] = {55,3,1,3,6};
 static enum {
     DHCP_NONE = 0,
     DHCP_DISCOVER,
     DHCP_OFFER,
@@ -134,17 +135,20 @@ bootp_handler(udp_socket_t *skt, char *b
         }
         break;
     case DHCP_NONE:
     case DHCP_OFFER:
     case DHCP_ACK:
-        diag_printf("Invalid DHCP reply state: %d\n", dhcpState);
-        dhcpState = DHCP_NONE;  // Reset state machine
+        // Quitely ignore these - they indicate repeated message from server
+        return;
+    }
+    // See if we've been NAK'd - if so, give up and try again
+    if (memcmp(p, dhcpNak, sizeof(dhcpNak)) == 0) {
+        dhcpState = DHCP_NONE;
         return;
     }
     diag_printf("DHCP reply: %d/%d/%d, not %d/%d/%d\n",
                 p[0], p[1], p[2], expected[0], expected[1], expected[2]);
-    dhcpState = DHCP_NONE;  // Reset state machine
     return;
 #else
     // Simple BOOTP - this is all there is!
     memcpy(__local_ip_addr, &b->bp_yiaddr, 4);
 #endif
@@ -165,10 +169,11 @@ __bootp_find_local_ip(bootp_header_t *in
     int            retry;
     unsigned long  start;
     ip_addr_t saved_ip_addr;
 #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP
     unsigned char *p;
+    int oldState;
 #endif
     int txSize;
     bool abort = false;
     static int xid = SHOULD_BE_RANDOM;
 
@@ -221,75 +226,78 @@ __bootp_find_local_ip(bootp_header_t *in
             dhcpState = DHCP_DISCOVER;
             break;
         case DHCP_OFFER:
             retry = MAX_RETRIES;
         case DHCP_REQUEST:
+            b.bp_xid = bp_info->bp_xid;  // Match what server sent
             AddOption(p,dhcpCookie);
             AddOption(p,dhcpRequest);
             AddOption(p,dhcpRequestIP);
             memcpy(p, &bp_info->bp_yiaddr, 4);  p += 4;  // Ask for the address just given
             AddOption(p,dhcpParamRequestList);
             AddOption(p,dhcpEnd);
             dhcpState = DHCP_REQUEST;
             memset(&b.bp_yiaddr, 0xFF, 4);
             memset(&b.bp_siaddr, 0xFF, 4);
+            memset(&b.bp_yiaddr, 0x00, 4);
+            memset(&b.bp_siaddr, 0x00, 4);
             break;
-        case DHCP_ACK:
-            // These states should never occur here!
-            diag_printf("Invalid DHCP state: %d\n", dhcpState);
-            abort = true;
         }
-        if (abort) break;  // From while loop
      
         // Some servers insist on a minimum amount of "vendor" data
         if (p < &b.bp_vend[BP_MIN_VEND_SIZE]) p = &b.bp_vend[BP_MIN_VEND_SIZE];
         txSize = p - (unsigned char*)&b;
+        oldState = dhcpState;
 #else
         txSize = sizeof(b);
 #endif
 
 	__udp_send((char *)&b, txSize, &r, IPPORT_BOOTPS, IPPORT_BOOTPC);
 
 	do {
 	    __enet_poll();
 #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP
-            if (dhcpState == DHCP_ACK) {
-                unsigned char *end;
-                int optlen;
-                // Address information has now arrived!
-                memcpy(__local_ip_addr, &bp_info->bp_yiaddr, 4);
+            if (dhcpState != oldState) {
+                if (dhcpState == DHCP_ACK) {
+                    unsigned char *end;
+                    int optlen;
+                    // Address information has now arrived!
+                    memcpy(__local_ip_addr, &bp_info->bp_yiaddr, 4);
 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
-                memcpy(__local_ip_gate, &bp_info->bp_giaddr, 4);
+                    memcpy(__local_ip_gate, &bp_info->bp_giaddr, 4);
 #endif
-                p = bp_info->bp_vend+4;
-                end = (unsigned char *)bp_info+sizeof(*bp_info);
-                while (p < end) {
-                    unsigned char tag = *p;
-                    if (tag == TAG_END)
-                        break;
-                    if (tag == TAG_PAD)
-                        optlen = 1;
-                    else {
-                        optlen = p[1];
-                        p += 2;
-                        switch (tag) {
-                        case TAG_SUBNET_MASK:  // subnet mask
-                            memcpy(__local_ip_mask,p,4); 
+                    p = bp_info->bp_vend+4;
+                    end = (unsigned char *)bp_info+sizeof(*bp_info);
+                    while (p < end) {
+                        unsigned char tag = *p;
+                        if (tag == TAG_END)
                             break;
+                        if (tag == TAG_PAD)
+                            optlen = 1;
+                        else {
+                            optlen = p[1];
+                            p += 2;
+                            switch (tag) {
+                            case TAG_SUBNET_MASK:  // subnet mask
+                                memcpy(__local_ip_mask,p,4); 
+                                break;
 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
-                        case TAG_GATEWAY:  // router
-                            memcpy(__local_ip_gate,p,4); 
-                            break;
-#endif
-                        default:
-                            break;
+                            case TAG_GATEWAY:  // router
+                                memcpy(__local_ip_gate,p,4); 
+                                break;
+#endif
+                            default:
+                                break;
+                            }
                         }
+                        p += optlen;
                     }
-                    p += optlen;
+                    __udp_remove_listener(IPPORT_BOOTPC);
+                    return 0;
+                } else {
+                    break;  // State changed, handle it
                 }
-		__udp_remove_listener(IPPORT_BOOTPC);
-                return 0;
             }
 #else
             // All done, if address response has arrived
 	    if (__local_ip_addr[0] || __local_ip_addr[1] ||
 		__local_ip_addr[2] || __local_ip_addr[3]) {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]