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]

Tweak DHCP sends, and remove dhcp_copy


Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/ChangeLog,v
retrieving revision 1.6
diff -u -5 -p -r1.6 ChangeLog
--- ChangeLog	20 Jun 2002 22:05:58 -0000	1.6
+++ ChangeLog	4 Jul 2002 18:02:52 -0000
@@ -1,5 +1,12 @@
+2002-07-04  Jonathan Larmour  <jlarmour@redhat.com>
+
+	* src/dhcp_prot.c (_dhcp_copy): Remove. Unnecessary as we can never
+	receive a packet longer than sizeof(struct bootp)
+	(do_dhcp): Also set giaddr to 0 before sends.
+	Verify length of received packets, especially to check for truncation.
+
 2002-06-20  Gary Thomas  <gary@chez-thomas.org>
 
 	* src/inet_ntop.c: Fix build error when used with newer compilers.
 
 2002-06-05  Gary Thomas  <gary@chez-thomas.org>
Index: src/dhcp_prot.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/src/dhcp_prot.c,v
retrieving revision 1.3
diff -u -5 -p -r1.3 dhcp_prot.c
--- src/dhcp_prot.c	5 Jun 2002 13:16:29 -0000	1.3
+++ src/dhcp_prot.c	4 Jul 2002 18:02:52 -0000
@@ -510,30 +510,10 @@ static void set_default_dhcp_tags( struc
 
     // Explicitly specify our max message size.
     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
 
 int
 do_dhcp(const char *intf, struct bootp *res,
@@ -564,11 +544,11 @@ do_dhcp(const char *intf, struct bootp *
     // when we are happy with them.  So we always transmit from the
     // existing state.
     struct bootp rx_local;
     struct bootp *received = &rx_local;
     struct bootp *xmit = res;
-    struct bootp *xmit2 = (struct bootp *)NULL;
+    struct bootp xmit2;
     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.
     
@@ -741,19 +721,24 @@ do_dhcp(const char *intf, struct bootp *
                     break;
                 }
                 *pstate = DHCPSTATE_INIT; // to retransmit
                 break;
             }
-
+            // Check for well-formed packet with correct termination (not truncated)
+            length = dhcp_size( received );
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_SELECTING received:\n" );
+            if ( length <= 0 )
+                diag_printf( "WARNING! malformed or truncated packet\n" );
             diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",
                          rx_addr.sin_family,
                          rx_addr.sin_addr.s_addr,
                          rx_addr.sin_port );
             show_bootp( intf, received );
 #endif            
+            if ( length <= 0 )
+                break;
             if ( CHECK_XID() )          // XID and ESA matches?
                 break;                  // listen again...
 
             if ( 0 == received->bp_siaddr.s_addr ) {
                 // then fill in from the options...
@@ -805,17 +790,16 @@ do_dhcp(const char *intf, struct bootp *
             diag_printf( "---------DHCPSTATE_REQUESTING sending:\n" );
             show_bootp( intf, xmit );
 #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)            
-            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, 
+            // still useful to us (and currently stored in the 'result' structure)
+            xlen = dhcp_size_for_send( xmit );
+            bcopy( xmit, &xmit2, xlen );
+            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;
+            xmit2.bp_hops = 0;
+            if(sendto(s, &xmit2, xlen, 0, 
                       (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
             }
 
@@ -838,19 +822,24 @@ do_dhcp(const char *intf, struct bootp *
                     break;
                 }
                 *pstate = DHCPSTATE_REQUESTING;
                 break;
             }
-
+            // Check for well-formed packet with correct termination (not truncated)
+            length = dhcp_size( received );
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_REQUEST_RECV received:\n" );
+            if ( length <= 0 )
+                diag_printf( "WARNING! malformed or truncated packet\n" );
             diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",
                          rx_addr.sin_family,
                          rx_addr.sin_addr.s_addr,
                          rx_addr.sin_port );
             show_bootp( intf, received );
 #endif            
+            if ( length <= 0 )
+                break;
             if ( CHECK_XID() )          // not the same transaction;
                 break;                  // listen again...
 
             if ( 0 == received->bp_siaddr.s_addr ) {
                 // then fill in from the options...
@@ -945,15 +934,14 @@ 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)
             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, 
+            bcopy( xmit, &xmit2, xlen );
+            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;
+            xmit2.bp_hops = 0;
+            if(sendto(s, &xmit2, xlen, 0,
                        // UNICAST address of the server:
                       (struct sockaddr *)&server_addr,
                       sizeof(server_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
@@ -983,19 +971,24 @@ do_dhcp(const char *intf, struct bootp *
                     break;
                 }
                 *pstate = DHCPSTATE_RENEWING;
                 break;
             }
-
+            // Check for well-formed packet with correct termination (not truncated)
+            length = dhcp_size( received );
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_RENEW_RECV received:\n" );
+            if ( length <= 0 )
+                diag_printf( "WARNING! malformed or truncated packet\n" );
             diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",
                          rx_addr.sin_family,
                          rx_addr.sin_addr.s_addr,
                          rx_addr.sin_port );
             show_bootp( intf, received );
 #endif            
+            if ( length <= 0 )
+                break;
             if ( CHECK_XID() )          // not the same transaction;
                 break;                  // listen again...
 
             if ( 0 == received->bp_siaddr.s_addr ) {
                 // then fill in from the options...
@@ -1050,16 +1043,15 @@ do_dhcp(const char *intf, struct bootp *
             show_bootp( intf, xmit );
 #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)
-            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, 
+            xlen = dhcp_size_for_send( xmit );
+            bcopy( xmit, &xmit2, xlen );
+            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;
+            xmit2.bp_hops = 0;
+            if(sendto(s, &xmit2, xlen, 0, 
                       (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
             }
 
@@ -1087,19 +1079,24 @@ do_dhcp(const char *intf, struct bootp *
                     break;
                 }
                 *pstate = DHCPSTATE_REBINDING;
                 break;
             }
-
+            // Check for well-formed packet with correct termination (not truncated)
+            length = dhcp_size( received );
 #ifdef CYGDBG_NET_DHCP_CHATTER
             diag_printf( "---------DHCPSTATE_REBIND_RECV received:\n" );
+            if ( length <= 0 )
+                diag_printf( "WARNING! malformed or truncated packet\n" );
             diag_printf( "...rx_addr is family %d, addr %08x, port %d\n",
                          rx_addr.sin_family,
                          rx_addr.sin_addr.s_addr,
                          rx_addr.sin_port );
             show_bootp( intf, received );
 #endif            
+            if ( length <= 0 )
+                break;
             if ( CHECK_XID() )          // not the same transaction;
                 break;                  // listen again...
 
             if ( 0 == received->bp_siaddr.s_addr ) {
                 // then fill in from the options...
@@ -1199,16 +1196,15 @@ do_dhcp(const char *intf, struct bootp *
             show_bootp( intf, xmit );
 #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)
-            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, 
+            xlen = dhcp_size_for_send( xmit );
+            bcopy( xmit, &xmit2, xlen );
+            xmit2.bp_yiaddr.s_addr = xmit2.bp_siaddr.s_addr = xmit2.bp_giaddr.s_addr = 0;
+            xmit2.bp_hops = 0;
+            if(sendto(s, &xmit2, xlen, 0, 
                        // UNICAST address of the server:
                       (struct sockaddr *)&server_addr,
                       sizeof(server_addr)) < 0) {
                 *pstate = DHCPSTATE_FAILED;
                 break;
@@ -1219,15 +1215,10 @@ do_dhcp(const char *intf, struct bootp *
 
         default:
             no_lease( lease );
             close(s);
             return false;
-        }
-        // Clean up temporary buffer(s)
-        if (xmit2) {
-            cyg_net_free(xmit2, 0);
-            xmit2 = (struct bootp *)NULL;
         }
     }
     /* NOTREACHED */
     return false;
 }


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