Mercurial > flash_v2
changeset 229:ff3465255c3a
* 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.
| author | jlarmour |
|---|---|
| date | Thu, 04 Jul 2002 18:03:05 +0000 |
| parents | e1b642d73533 |
| children | 20314171555b |
| files | packages/net/common/current/ChangeLog packages/net/common/current/src/dhcp_prot.c |
| diffstat | 2 files changed, 52 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/net/common/current/ChangeLog +++ b/packages/net/common/current/ChangeLog @@ -1,3 +1,10 @@ +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.
--- a/packages/net/common/current/src/dhcp_prot.c +++ b/packages/net/common/current/src/dhcp_prot.c @@ -512,26 +512,6 @@ 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 @@ -566,7 +546,7 @@ 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 *)NULL; + struct bootp xmit2; int xlen; // First, get a socket on the interface in question. But Zeroth, if @@ -743,15 +723,20 @@ do_dhcp(const char *intf, struct bootp * *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... @@ -807,13 +792,12 @@ 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) - 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; @@ -840,15 +824,20 @@ do_dhcp(const char *intf, struct bootp * *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... @@ -947,11 +936,10 @@ do_dhcp(const char *intf, struct bootp * // 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) { @@ -985,15 +973,20 @@ do_dhcp(const char *intf, struct bootp * *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... @@ -1052,12 +1045,11 @@ 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, + 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; @@ -1089,15 +1081,20 @@ do_dhcp(const char *intf, struct bootp * *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... @@ -1201,12 +1198,11 @@ 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, + 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) { @@ -1222,11 +1218,6 @@ 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;
