Mercurial > ecos
changeset 3097:a75d37e86790
Create new package for DHCP/BOOTP support so that it can be disable
(not built). Moved options specific to DHCP/BOOTP into the new
package.
Rewrite DHCP/BOOTP implementation to fix several problems: race
condition when receiving responses from multiple servers; broken retry
mechanism; XID is hard-wired constant; XID not verified properly.
[ Bugzilla 1001177 ]
| author | grante |
|---|---|
| date | Tue, 06 Mar 2012 16:45:24 +0000 |
| parents | 73ce0d6424ec |
| children | 64c563c52ef5 |
| files | packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/include/redboot.h packages/redboot/current/src/net/bootp.c packages/redboot/current/src/net/net_io.c |
| diffstat | 5 files changed, 383 insertions(+), 277 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,20 @@ +2012-03-06 Grant Edwards <grant.b.edwards@gmail.com> + + * src/net/net_io.c: + * cdl/redboot.cdl: Added new CDL option + CYGPKG_REDBOOT_NETWORKING_BOOTP to control whether BOOTP/DHCP + support is built into Redboot. Moved "DEFAULT_NO_BOOTP" option + into the new package. + [ Bugzilla 1001177 ] + + * src/net/bootp.c: + * cdl/redboot.cdl: Re-wrote BOOTP/DHCP client code to fix retry + mechanism and to fix race conditions that were corrupting the + received IP configuration data. Added verbose BOOTP/DHCP output + CDL option. + [ Bugzilla 1001177 ] + + 2011-12-02 John Dallaway <john@dallaway.org.uk> * cdl/redboot.cdl: Fix typographical error. Issue reported by
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -251,6 +251,7 @@ cdl_package CYGPKG_REDBOOT { display "Include POSIX checksum command" doc ref/cksum-command.html default_value 1 + requires CYGPKG_CRC compile -library=libextras.a cksum.c } @@ -339,7 +340,7 @@ cdl_package CYGPKG_REDBOOT { active_if CYGPKG_IO_ETH_DRIVERS default_value 1 implements CYGINT_REDBOOT_LOAD_METHOD - compile net/bootp.c net/udp.c net/ip.c net/pktbuf.c net/cksum.c + compile net/udp.c net/ip.c net/pktbuf.c net/cksum.c compile net/enet.c net/icmp.c net/tcp.c net/timers.c net/arp.c compile net/inet_addr.c compile -library=libextras.a net/ping.c net/net_io.c @@ -389,17 +390,6 @@ cdl_package CYGPKG_REDBOOT { an IP address is configured into the Flash configuration, that will be used in preference." - cdl_option CYGSEM_REDBOOT_DEFAULT_NO_BOOTP { - display "Do not try to use BOOTP" - flavor bool - default_value 0 - description " - By default Redboot tries to use BOOTP to get an IP - address. If there's no BOOTP server on your network - use this option to avoid the wait until the - timeout. This option is overriden by the - configuration stored in flash." - } cdl_option CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR { display "Default bootp server" flavor booldata @@ -415,21 +405,54 @@ cdl_package CYGPKG_REDBOOT { preference." } } - - cdl_component CYGSEM_REDBOOT_NETWORKING_DHCP { - display "Use DHCP to get IP information" + + cdl_component CYGPKG_REDBOOT_NETWORKING_BOOTP { + display "Enable BOOTP/DHCP support" flavor bool default_value 1 + compile net/bootp.c description " - Use DHCP protocol to obtain pertinent IP addresses, such - as the client, server, gateway, etc." + Use BOOTP/DHCP protocol to obtain pertinent IP + addresses, such as the client, server, gateway, + etc." + + cdl_component CYGSEM_REDBOOT_NETWORKING_DHCP { + display "Enable DHCP in addition to BOOTP support" + flavor bool + default_value 1 + description " + Enables DHCP protocol in addition to BOOTP. If not enabled, + only BOOTP will be suported." + } + + cdl_component CYGSEM_REDBOOT_NETWORKING_BOOTP_VERBOSE { + display "Enable verbose output from BOOTP/DHCP code" + flavor bool + default_value 0 + description " + Enable more verbose output from BOOTP/DHCP that logs rx/tx + packet types and state-machine transitions." + } + + cdl_option CYGSEM_REDBOOT_DEFAULT_NO_BOOTP { + display "Do not try to use BOOTP/DHCP" + flavor bool + default_value 0 + description " + By default Redboot tries to use BOOTP/DHCP to + get an IP address when BOOTP/DHCP support is + present in Redboot. If there's no BOOTP/DHCP + server on your network use this option to + avoid waiting for the BOOTP/DHCP timeouts and + retries. This option is overriden by the + configuration stored in flash." + } } - + cdl_component CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY { display "Use a gateway for non-local IP traffic" flavor bool default_value 1 - requires CYGSEM_REDBOOT_NETWORKING_DHCP description " Enabling this option will allow the RedBoot networking stack to use a \[single\] gateway to reach a non-local @@ -932,6 +955,7 @@ cdl_package CYGPKG_REDBOOT { display "Use CRC checksums on FIS images." flavor bool default_value 1 + requires CYGPKG_CRC description " When this option is enabled, RedBoot will use CRC checksums when reading and writing flash images."
--- a/packages/redboot/current/include/redboot.h +++ b/packages/redboot/current/include/redboot.h @@ -67,8 +67,10 @@ #include <net/net.h> #include <net/bootp.h> // Determine an IP address for this node, using BOOTP +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP extern int __bootp_find_local_ip(bootp_header_t *info); #endif +#endif #ifdef DEFINE_VARS #define EXTERN
--- a/packages/redboot/current/src/net/bootp.c +++ b/packages/redboot/current/src/net/bootp.c @@ -40,11 +40,13 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): gthomas +// grant edwards // Contributors: gthomas -// Date: 2000-07-14 -// Purpose: -// Description: -// +// grant edwards +// Date: 2011-03-18 +// Purpose: +// Description: +// // This code is part of RedBoot (tm). // //####DESCRIPTIONEND#### @@ -55,299 +57,341 @@ #include <net/net.h> #include <net/bootp.h> -#define SHOULD_BE_RANDOM 0x12345555 +#define RETRY_TIME_MS 2000 +#define MAX_RETRIES 4 -/* How many milliseconds to wait before retrying the request */ -#define RETRY_TIME 2000 -#define MAX_RETRIES 8 - +static unsigned xid; // transaction ID, should be random/unique +static const ip_route_t broadcast = { {255, 255, 255, 255}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff} }; static bootp_header_t *bp_info; - + #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP -static const unsigned char dhcpCookie[] = {99,130,83,99}; -static const unsigned char dhcpEnd[] = {255}; -static const unsigned char dhcpDiscover[] = {53,1,1}; -static const unsigned char dhcpRequest[] = {53,1,3}; -static const unsigned char dhcpRequestIP[] = {50,4}; -static const unsigned char dhcpParamRequestList[] = {55,3,1,3,6}; +static const unsigned char dhcpCookie[] = { 99, 130, 83, 99 }; +static const unsigned char dhcpDiscover[] = { 53, 1, 1 }; +static const unsigned char dhcpRequest[] = { 53, 1, 3 }; +static const unsigned char dhcpRequestIP[] = { 50, 4 }; +static const unsigned char dhcpParamRequestList[] = { 55, 3, 1, 3, 6 }; +static const unsigned char dhcpEnd[] = { 255 }; +#endif + +// FSM states -- only NONE and DONE are used in BOOTP mode static enum { DHCP_NONE = 0, - DHCP_DISCOVER, - DHCP_OFFER, - DHCP_REQUEST, - DHCP_ACK + DHCP_WAITING_FOR_OFFER, + DHCP_WAITING_FOR_ACK, + DHCP_DONE, + DHCP_FAILED } dhcpState; + +#if !defined(CYGSEM_REDBOOT_NETWORKING_BOOTP_VERBOSE) +# define debug_printf(format, ...) /* noop */ +#else +# define debug_printf(format, ...) diag_printf(format, ##__VA_ARGS__) +static const char *dhcpStateString[] = { "NONE", "WAITING_FOR_OFFER", "WAITING_FOR_ACK", "DONE", "FAILED" }; +# ifdef CYGSEM_REDBOOT_NETWORKING_DHCP +static const char *dhcpTypeString[] = { "0x00", "DISCOVER", "OFFER", "REQUEST", "0x04", "ACK", "NAK", "0x07" }; +# endif +#endif + +// parse network configuration from a DHCP ACK packet or BOOTP REPLY +static void +parseConfig(bootp_header_t *bp, int len) +{ +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + unsigned char *end, + *p; + int optlen; +#endif + memcpy(__local_ip_addr, &bp->bp_yiaddr, sizeof __local_ip_addr); +#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY + memcpy(__local_ip_gate, &bp->bp_giaddr, sizeof __local_ip_gate); #endif +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + + // are there option fields to parse? + if (memcmp(bp->bp_vend, dhcpCookie, sizeof dhcpCookie)) + return; + + p = bp->bp_vend + 4; + end = (unsigned char *)bp + len; + 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) { +# ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY + case TAG_SUBNET_MASK: + memcpy(__local_ip_mask, p, sizeof __local_ip_mask); + break; + case TAG_GATEWAY: + memcpy(__local_ip_gate, p, sizeof __local_ip_gate); + break; +# endif +# ifdef CYGPKG_REDBOOT_NETWORKING_DNS + case TAG_DOMAIN_SERVER: + memcpy(&__bootp_dns_addr, p, sizeof __bootp_dns_addr); + __bootp_dns_set = 1; + break; +# endif + default: + break; + } + } + p += optlen; + } +#endif +} + +// functions used to prepare BOOTP/DHCP tx packets + +// basic BOOTP request static void -bootp_handler(udp_socket_t *skt, char *buf, int len, - ip_route_t *src_route, word src_port) +prep_bootp_request(bootp_header_t *b) +{ + memset(b, 0, sizeof *b); + b->bp_op = BOOTREQUEST; + b->bp_htype = HTYPE_ETHERNET; + b->bp_hlen = sizeof __local_enet_addr; + b->bp_xid = xid; + memcpy(b->bp_chaddr, __local_enet_addr, sizeof b->bp_chaddr); +} + +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + +# define AddOption(p,d) do {memcpy(p,d,sizeof d); p += sizeof d;} while (0) + +// add DHCP DISCOVER fields to a basic BOOTP request +static int +prep_dhcp_discover(bootp_header_t *b) +{ + unsigned char *p = b->bp_vend; + AddOption(p, dhcpCookie); + AddOption(p, dhcpDiscover); + AddOption(p, dhcpParamRequestList); + AddOption(p, dhcpEnd); + if (p < &b->bp_vend[BP_MIN_VEND_SIZE]) + p = &b->bp_vend[BP_MIN_VEND_SIZE]; + return p - (unsigned char *)b; +} + +// add DHCP REQUEST fields to a basic BOOTP request using data from supplied DHCP OFFER +static int +prep_dhcp_request(bootp_header_t *b, bootp_header_t *offer) +{ + unsigned char *p = b->bp_vend; + AddOption(p, dhcpCookie); + AddOption(p, dhcpRequest); + AddOption(p, dhcpRequestIP); + memcpy(p, &offer->bp_yiaddr, dhcpRequestIP[1]); + p += dhcpRequestIP[1]; // Ask for the address just given + AddOption(p, dhcpParamRequestList); + AddOption(p, dhcpEnd); + if (p < &b->bp_vend[BP_MIN_VEND_SIZE]) + p = &b->bp_vend[BP_MIN_VEND_SIZE]; + return p - (unsigned char *)b; +} +#endif + +// Macro used to change state of BOOTP/DHCP state machine +#define NewDhcpState(state) do {dhcpState = state; debug_printf("DHCP state: %s\n",dhcpStateString[state]);}while(0) + +// send BOOTP REQUEST or DHCP DISCOVER +static void +bootp_start(void) +{ + int txSize; + bootp_header_t b; + // send out a BOOTP request or DHCP DISCOVER + prep_bootp_request(&b); // basic BOOTP request +#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP + debug_printf("DHCP send: DISCOVER\n"); + NewDhcpState(DHCP_WAITING_FOR_OFFER); + txSize = prep_dhcp_discover(&b); // make it into DHCP DISCOVER +#else + debug_printf("BOOTP send: REQUEST\n"); + txSize = sizeof(b); +#endif + __udp_send((char *)&b, txSize, (ip_route_t*)&broadcast, IPPORT_BOOTPS, IPPORT_BOOTPC); +} + +// save packet for use by other commands +static void +save_packet(void *b, int len) +{ + memset(bp_info, 0, sizeof *bp_info); + if ((unsigned)len > sizeof *bp_info) + len = sizeof *bp_info; + memcpy(bp_info, b, len); +} + +// Handler for received BOOTP/DHCP packets +static void +bootp_handler(udp_socket_t *skt, char *buf, int len, ip_route_t *src_route, + word src_port) { bootp_header_t *b; #ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - unsigned char *p, expected = 0; + int txSize; + int type; + bootp_header_t txpkt; + unsigned expected = 0; #endif - b = (bootp_header_t *)buf; - if (bp_info) { - memset(bp_info,0,sizeof *bp_info); - if (len > sizeof *bp_info) - len = sizeof *bp_info; - memcpy(bp_info, b, len); + b = (bootp_header_t *) buf; + + // only accept BOOTP REPLY responses + if (b->bp_op != BOOTREPLY) + return; + + // must be sent to me + if (memcmp(b->bp_chaddr, __local_enet_addr, b->bp_hlen)) + return; + + // verify XID + if (b->bp_xid != xid) + return; + +#if !defined(CYGSEM_REDBOOT_NETWORKING_DHCP) + // simple BOOTP - this is all there is! + debug_printf("BOOTP recv: REPLY\n"); + if (dhcpState != DHCP_DONE) { + save_packet(b, len); + parseConfig(b, len); + NewDhcpState(DHCP_DONE); + } +#else + // DHCP support is enabled... + + // Check to see that it's a DHCP packet with a DHCP type field + + type = -1; + if (!memcmp(b->bp_vend, dhcpCookie, sizeof dhcpCookie)) { + unsigned char *p = b->bp_vend + 4; + while (p < (unsigned char *)b + len) { + if (*p == TAG_DHCP_MESS_TYPE) { + type = p[2]; + break; + } + p += p[1] + 2; + } } - // Only accept pure REPLY responses - if (b->bp_op != BOOTREPLY) - return; - - // Must be sent to me, as well! - if (memcmp(b->bp_chaddr, __local_enet_addr, 6)) - return; + if (type == -1) { + // apparently we have a BOOTP (but not not DHCP) server + debug_printf("DHCP recv: BOOTP-REPLY -- falling back to BOOTP mode\n"); + if (dhcpState != DHCP_DONE) { + save_packet(b, len); + parseConfig(b, len); + NewDhcpState(DHCP_DONE); + } + return; + } -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - p = b->bp_vend; - if (memcmp(p, dhcpCookie, sizeof(dhcpCookie))) - return; - p += 4; - - // Find the DHCP Message Type tag - while (*p != TAG_DHCP_MESS_TYPE) { - p += p[1] + 2; - if (p >= (unsigned char*)b + sizeof(*bp_info)) - return; - } - - p += 2; + // it's a real DHCP packet + debug_printf("DHCP recv: %s [%d]\n", dhcpTypeString[type], type); switch (dhcpState) { - case DHCP_DISCOVER: - // The discover message has been sent, only accept an offer reply - if (*p == DHCP_MESS_TYPE_OFFER) { - dhcpState = DHCP_OFFER; + case DHCP_WAITING_FOR_OFFER: + if (type == (expected = DHCP_MESS_TYPE_OFFER)) { + prep_bootp_request(&txpkt); + txSize = prep_dhcp_request(&txpkt, b); + debug_printf("DHCP send: REQUEST\n"); + NewDhcpState(DHCP_WAITING_FOR_ACK); + __udp_send((char *)&txpkt, txSize, (ip_route_t *)&broadcast, IPPORT_BOOTPS, IPPORT_BOOTPC); return; - } else { - expected = DHCP_MESS_TYPE_OFFER; } break; - case DHCP_REQUEST: - // The request message has been sent, only accept an ack reply - if (*p == DHCP_MESS_TYPE_ACK) { - dhcpState = DHCP_ACK; + + case DHCP_WAITING_FOR_ACK: + if (type == (expected = DHCP_MESS_TYPE_ACK)) { + save_packet(b, len); + parseConfig(b, len); + NewDhcpState(DHCP_DONE); return; - } else { - expected = DHCP_MESS_TYPE_ACK; } break; - case DHCP_NONE: - case DHCP_OFFER: - case DHCP_ACK: - // Quitely ignore these - they indicate repeated message from server + + default: + debug_printf("DHCP packet ignored\n"); return; } - // See if we've been NAK'd - if so, give up and try again - if (*p == DHCP_MESS_TYPE_NAK) { - dhcpState = DHCP_NONE; + + if (type == DHCP_MESS_TYPE_NAK && dhcpState != DHCP_DONE) { + NewDhcpState(DHCP_FAILED); return; } - diag_printf("DHCP reply: %d, not %d\n", (int)*p, (int)expected); - return; -#else - // Simple BOOTP - this is all there is! - memcpy(__local_ip_addr, &b->bp_yiaddr, 4); + + debug_printf("DHCP packet ignored -- expected %d[%s]\n", expected, dhcpTypeString[expected]); #endif } -#define AddOption(p,d) do {memcpy(p,d,sizeof d); p += sizeof d;} while (0) -/* - * Find our IP address and copy to __local_ip_addr. - * Return zero if successful, -1 if not. - */ +// Request IP configuration via BOOTP/DHCP. +// Return zero if successful, -1 if not. + int __bootp_find_local_ip(bootp_header_t *info) { - udp_socket_t udp_skt; - bootp_header_t b; - ip_route_t r; - 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; + udp_socket_t udp_skt; + int retry; + unsigned long start; + ip_addr_t saved_ip_addr; -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - dhcpState = DHCP_NONE; -#endif + bp_info = info; + + diag_printf("\nRequesting IP conf via BOOTP/DHCP...\n"); - // Where we want the results saved - bp_info = info; - // Preserve any IP address we currently have, just in case - memcpy(saved_ip_addr, __local_ip_addr, sizeof(__local_ip_addr)); + memcpy(&xid, __local_enet_addr, sizeof xid); + xid ^= (__local_enet_addr[4]<<16) + __local_enet_addr[5]; + xid ^= (unsigned)&retry + (unsigned)&__bootp_find_local_ip; - // fill out route for a broadcast - r.ip_addr[0] = 255; - r.ip_addr[1] = 255; - r.ip_addr[2] = 255; - r.ip_addr[3] = 255; - r.enet_addr[0] = 255; - r.enet_addr[1] = 255; - r.enet_addr[2] = 255; - r.enet_addr[3] = 255; - r.enet_addr[4] = 255; - r.enet_addr[5] = 255; + debug_printf("XID: %08x\n",xid); - // setup a socket listener for bootp replies + memcpy(saved_ip_addr, __local_ip_addr, sizeof __local_ip_addr); // save our IP in case of failure + + NewDhcpState(DHCP_NONE); + __udp_install_listener(&udp_skt, IPPORT_BOOTPC, bootp_handler); - retry = MAX_RETRIES; - do { - start = MS_TICKS(); + retry = MAX_RETRIES; - // Build up the BOOTP/DHCP request - memset(&b, 0, sizeof(b)); - b.bp_op = BOOTREQUEST; - b.bp_htype = HTYPE_ETHERNET; - b.bp_hlen = 6; - b.bp_xid = xid++; - memcpy(b.bp_chaddr, __local_enet_addr, 6); + while (retry > 0) { + start = MS_TICKS(); memset(__local_ip_addr, 0, sizeof(__local_ip_addr)); - -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - p = b.bp_vend; - switch (dhcpState) { - case DHCP_NONE: - case DHCP_DISCOVER: - AddOption(p,dhcpCookie); - AddOption(p,dhcpDiscover); - AddOption(p,dhcpParamRequestList); - AddOption(p,dhcpEnd); - 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: - // Ignore these states (they won't happen) - break; - } - - // 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); - - // If we're retrying, inform the user - if (retry == (MAX_RETRIES-1)) - diag_printf("... waiting for BOOTP information\n"); + // send bootp REQUEST or dhcp DISCOVER + bootp_start(); - do { - __enet_poll(); -#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP - 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); -#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) { -#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY - case TAG_SUBNET_MASK: // subnet mask - memcpy(__local_ip_mask,p,4); - break; - case TAG_GATEWAY: // router - memcpy(__local_ip_gate,p,4); - break; -#endif -#ifdef CYGPKG_REDBOOT_NETWORKING_DNS - case TAG_DOMAIN_SERVER: -// diag_printf(" DNS server found!\n"); - memcpy(&__bootp_dns_addr, p, 4); - __bootp_dns_set = 1; - break; -#ifdef CYGPKG_REDBOOT_NETWORKING_DNS_DHCP_DOMAIN - case TAG_DOMAIN_NAME: - if(optlen < sizeof(__bootp_dns_domain)) { - memcpy(__bootp_dns_domain, p, optlen); - __bootp_dns_domain[optlen] = '\0'; - __bootp_dns_domain_set = 1; - } else { - diag_printf("DNS domain name too long\n"); - } - break; -#endif //CYGPKG_REDBOOT_NETWORKING_DNS_DHCP_DOMAIN -#endif //CYGPKG_REDBOOT_NETWORKING_DNS - default: - break; - } - } - p += optlen; - } - __udp_remove_listener(IPPORT_BOOTPC); - return 0; - } else { - break; // State changed, handle it - } - } -#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]) { - /* success */ - __udp_remove_listener(IPPORT_BOOTPC); - return 0; - } -#endif - if (_rb_break(1)) { - // The user typed ^C on the console - abort = true; + // wait for timeout, user-abort, or for receive packet handler to fail/succeed + while ((MS_TICKS_DELAY() - start) < RETRY_TIME_MS) { + __enet_poll(); + if (dhcpState == DHCP_FAILED) break; - } - MS_TICKS_DELAY(); // Count for ^C test - } while ((MS_TICKS_DELAY() - start) < RETRY_TIME); - } while (!abort && (retry-- > 0)); + if (dhcpState == DHCP_DONE) + goto done; + if (_rb_break(1)) // did user hit ^C? + goto failed; + MS_TICKS_DELAY(); + } + --retry; + ++xid; + diag_printf("TIMEOUT%s\n", retry ? ", retrying..." : ""); + } - // timed out +failed: + diag_printf("FAIL\n"); __udp_remove_listener(IPPORT_BOOTPC); - // Restore any previous IP address - memcpy(__local_ip_addr, saved_ip_addr, sizeof(__local_ip_addr)); + memcpy(__local_ip_addr, saved_ip_addr, sizeof __local_ip_addr); // restore prev IP return -1; + +done: + diag_printf("OK\n"); + __udp_remove_listener(IPPORT_BOOTPC); + return 0; } - -
--- a/packages/redboot/current/src/net/net_io.c +++ b/packages/redboot/current/src/net/net_io.c @@ -59,6 +59,10 @@ #include <cyg/hal/hal_intr.h> #include <cyg/infra/cyg_ass.h> // assertion macros +#ifndef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP +#define CYGSEM_REDBOOT_DEFAULT_NO_BOOTP 0 +#endif + #ifdef CYGSEM_REDBOOT_FLASH_CONFIG #include <flash_config.h> @@ -90,15 +94,14 @@ RedBoot_config_option("Default network d // negated (if false, the others apply) which makes the names even more // confusing. -#ifndef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP -#define CYGSEM_REDBOOT_DEFAULT_NO_BOOTP 0 -#endif +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP RedBoot_config_option("Use BOOTP for network configuration", bootp, ALWAYS_ENABLED, true, CONFIG_BOOL, !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP ); +#endif RedBoot_config_option("Local IP address", bootp_my_ip, "bootp", false, @@ -689,10 +692,10 @@ net_init(void) #endif // Set defaults as appropriate -#ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP +#if defined(CYGPKG_REDBOOT_NETWORKING_BOOTP) && !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP + use_bootp = true; +#else use_bootp = false; -#else - use_bootp = true; #endif #ifdef CYGDBG_REDBOOT_NET_DEBUG net_debug = true; @@ -707,7 +710,9 @@ net_init(void) #endif flash_get_config("net_debug", &net_debug, CONFIG_BOOL); flash_get_config("gdb_port", &gdb_port, CONFIG_INT); +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP flash_get_config("bootp", &use_bootp, CONFIG_BOOL); +#endif if (!use_bootp) { flash_get_IP("bootp_my_ip", &__local_ip_addr); #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY @@ -767,6 +772,7 @@ net_init(void) return; } // Initialize the network [if present] +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP if (use_bootp) { if (__bootp_find_local_ip(&my_bootp_info) == 0) { have_net = true; @@ -781,7 +787,9 @@ net_init(void) have_net = true; } } - } else { + } +#endif + if (!use_bootp) { if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 && __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) { show_eth_info(); @@ -813,7 +821,11 @@ net_init(void) } } -static char usage[] = "[-b] [-l <local_ip_address>[/<mask_len>]] [-h <server_address>]" +static char usage[] = "" +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP + " [-b]" +#endif + " [-l <local_ip_address>[/<mask_len>]] [-h <server_address>]" #ifdef CYGPKG_REDBOOT_NETWORKING_DNS " [-d <dns_server_address>]" #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN @@ -836,7 +848,9 @@ do_ip_addr(int argc, char *argv[]) struct option_info opts[5]; char *ip_addr, *host_addr; bool ip_addr_set, host_addr_set; +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP bool do_bootp = false; +#endif struct sockaddr_in host; #ifdef CYGPKG_REDBOOT_NETWORKING_DNS char *dns_addr; @@ -857,9 +871,12 @@ do_ip_addr(int argc, char *argv[]) (void *)&ip_addr, (bool *)&ip_addr_set, "local IP address"); init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR, (void *)&host_addr, (bool *)&host_addr_set, "default server address"); + num_opts = 2; +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP init_opts(&opts[2], 'b', false, OPTION_ARG_TYPE_FLG, &do_bootp, 0, "use BOOTP"); - num_opts = 3; + num_opts++; +#endif #ifdef CYGPKG_REDBOOT_NETWORKING_DNS init_opts(&opts[num_opts], 'd', true, OPTION_ARG_TYPE_STR, (void *)&dns_addr, (bool *)&dns_addr_set, "DNS server address"); @@ -875,11 +892,13 @@ do_ip_addr(int argc, char *argv[]) if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) { return; } +#ifdef CYGPKG_REDBOOT_NETWORKING_BOOTP if (do_bootp) { if (__bootp_find_local_ip(&my_bootp_info) != 0) { diag_printf("Failed to get BOOTP address\n"); } } +#endif if (ip_addr_set) { #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY char *slash_pos;
