Mercurial > ecos
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;
