changeset 216:da643977bd0a

Improve DHCP reply handling
author gthomas
date Wed, 05 Jun 2002 13:16:26 +0000
parents 9091c290be62
children 3ef90475a347
files packages/net/common/current/ChangeLog packages/net/common/current/src/dhcp_prot.c
diffstat 2 files changed, 64 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/packages/net/common/current/ChangeLog
+++ b/packages/net/common/current/ChangeLog
@@ -1,3 +1,15 @@
+2002-06-05  Gary Thomas  <gary@chez-thomas.org>
+
+	* src/dhcp_prot.c (_dhcp_copy): New function used to better handle
+	replies that can be variable length.
+
+2002-05-30  Gary Thomas  <gthomas@redhat.com>
+
+	* tests/tcp_echo.c: Build with either stack (no libkern.h).
+
+	* tests/bridge.c: Don't do anything (should not even be built,
+	but that's a CDL complication) if no BRIDGE support in system.
+
 2002-05-30  Jesper Skov  <jskov@redhat.com>
 
 	* tests/flood.c (floodsend): Fixed warning.
--- a/packages/net/common/current/src/dhcp_prot.c
+++ b/packages/net/common/current/src/dhcp_prot.c
@@ -512,6 +512,26 @@ static void set_default_dhcp_tags( struc
     set_fixed_tag( xmit, TAG_DHCP_MAX_MSGSZ, BP_MINPKTSZ, 2 );
 }
 
+//
+// Make a copy of a BOOTP/DHCP record.  Note that this can
+// be [somewhat] arbitrarily long, thus it needs to be allocated
+// dynamically.  Reset certain fields within the record that are
+// supposed to only be returned by the server.
+//
+static struct bootp *
+_dhcp_copy(struct bootp *xmit, int xlen)
+{
+    struct bootp *xmit2;
+    xmit2 = (struct bootp *)cyg_net_malloc(xlen, 0, 0);
+    if (xmit2) {
+        bcopy(xmit, xmit2, xlen);
+        xmit2->bp_yiaddr.s_addr = 0;
+        xmit2->bp_siaddr.s_addr = 0;
+        xmit2->bp_hops = 0;
+    }
+    return xmit2;
+}
+
 // ------------------------------------------------------------------------
 // the DHCP state machine - this does all the work
 
@@ -546,7 +566,8 @@ do_dhcp(const char *intf, struct bootp *
     struct bootp rx_local;
     struct bootp *received = &rx_local;
     struct bootp *xmit = res;
-    struct bootp xmit2;
+    struct bootp *xmit2 = (struct bootp *)NULL;
+    int xlen;
 
     // First, get a socket on the interface in question.  But Zeroth, if
     // needs be, bring it to the half-up broadcast only state if needs be.
@@ -786,11 +807,13 @@ do_dhcp(const char *intf, struct bootp *
 #endif            
             // Send back a [modified] copy.  Note that some fields are explicitly
             // cleared, as per the RFC.  We need the copy because these fields are
-            // still useful to us (and currently stored in the 'result' structure)
-            bcopy(xmit, &xmit2, dhcp_size_for_send(xmit));
-            xmit2.bp_yiaddr.s_addr = 0;
-            xmit2.bp_siaddr.s_addr = 0;
-            if(sendto(s, &xmit2, dhcp_size_for_send(xmit), 0, 
+            // still useful to us (and currently stored in the 'result' structure)            
+            xlen = dhcp_size_for_send(xmit);
+            if ((xmit2 = _dhcp_copy(xmit, xlen)) == (struct bootp *)NULL) {
+                *pstate = DHCPSTATE_FAILED;
+                break;
+            }
+            if(sendto(s, xmit2, xlen, 0, 
                       (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
@@ -923,10 +946,12 @@ do_dhcp(const char *intf, struct bootp *
             // Send back a [modified] copy.  Note that some fields are explicitly
             // cleared, as per the RFC.  We need the copy because these fields are
             // still useful to us (and currently stored in the 'result' structure)
-            bcopy(xmit, &xmit2, dhcp_size_for_send(xmit));
-            xmit2.bp_yiaddr.s_addr = 0;
-            xmit2.bp_siaddr.s_addr = 0;
-            if(sendto(s, &xmit2, dhcp_size_for_send(xmit), 0, 
+            xlen = dhcp_size_for_send(xmit);
+            if ((xmit2 = _dhcp_copy(xmit, xlen)) == (struct bootp *)NULL) {
+                *pstate = DHCPSTATE_FAILED;
+                break;
+            }
+            if(sendto(s, xmit2, xlen, 0, 
                        // UNICAST address of the server:
                       (struct sockaddr *)&server_addr,
                       sizeof(server_addr)) < 0) {
@@ -1027,10 +1052,12 @@ do_dhcp(const char *intf, struct bootp *
             // Send back a [modified] copy.  Note that some fields are explicitly
             // cleared, as per the RFC.  We need the copy because these fields are
             // still useful to us (and currently stored in the 'result' structure)
-            bcopy(xmit, &xmit2, dhcp_size_for_send(xmit));
-            xmit2.bp_yiaddr.s_addr = 0;
-            xmit2.bp_siaddr.s_addr = 0;
-            if(sendto(s, &xmit2, dhcp_size_for_send(xmit), 0, 
+            xlen = dhcp_size_for_send(xmit);
+            if ((xmit2 = _dhcp_copy(xmit, xlen)) == (struct bootp *)NULL) {
+                *pstate = DHCPSTATE_FAILED;
+                break;
+            }
+            if(sendto(s, xmit2, xlen, 0, 
                       (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
@@ -1174,10 +1201,12 @@ do_dhcp(const char *intf, struct bootp *
             // Send back a [modified] copy.  Note that some fields are explicitly
             // cleared, as per the RFC.  We need the copy because these fields are
             // still useful to us (and currently stored in the 'result' structure)
-            bcopy(xmit, &xmit2, dhcp_size_for_send(xmit));
-            xmit2.bp_yiaddr.s_addr = 0;
-            xmit2.bp_siaddr.s_addr = 0;
-            if(sendto(s, &xmit2, dhcp_size_for_send(xmit), 0, 
+            xlen = dhcp_size_for_send(xmit);
+            if ((xmit2 = _dhcp_copy(xmit, xlen)) == (struct bootp *)NULL) {
+                *pstate = DHCPSTATE_FAILED;
+                break;
+            }
+            if(sendto(s, xmit2, xlen, 0, 
                        // UNICAST address of the server:
                       (struct sockaddr *)&server_addr,
                       sizeof(server_addr)) < 0) {
@@ -1193,6 +1222,11 @@ do_dhcp(const char *intf, struct bootp *
             close(s);
             return false;
         }
+        // Clean up temporary buffer(s)
+        if (xmit2) {
+            cyg_net_free(xmit2, 0);
+            xmit2 = (struct bootp *)NULL;
+        }
     }
     /* NOTREACHED */
     return false;