This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
RedBoot - more DHCP twiddling
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at sources dot redhat dot com>
- Date: 25 Sep 2003 17:50:57 -0600
- Subject: RedBoot - more DHCP twiddling
- Organization: MLB Associates
It seems some DHCP servers are truly stubborn, whilst
others are more forgiving...
--
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: redboot/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/ChangeLog,v
retrieving revision 1.136
diff -u -5 -p -r1.136 ChangeLog
--- redboot/current/ChangeLog 24 Sep 2003 15:30:14 -0000 1.136
+++ redboot/current/ChangeLog 25 Sep 2003 23:49:36 -0000
@@ -1,5 +1,10 @@
+2003-09-25 Gary Thomas <gary@mlbassoc.com>
+
+ * src/net/bootp.c: Rework DHCP process to handle really stubborn
+ servers.
+
2003-09-24 Gary Thomas <gary@mlbassoc.com>
* src/net/bootp.c (__bootp_find_local_ip): Forgot to unregister
UDP handler - could cause serious problems later! Also, fix
problem with retries after DHCP discovery phase.
Index: redboot/current/src/net/bootp.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/redboot/current/src/net/bootp.c,v
retrieving revision 1.16
diff -u -5 -p -r1.16 bootp.c
--- redboot/current/src/net/bootp.c 24 Sep 2003 15:30:15 -0000 1.16
+++ redboot/current/src/net/bootp.c 25 Sep 2003 23:48:43 -0000
@@ -58,12 +58,12 @@
#include <net/bootp.h>
#define SHOULD_BE_RANDOM 0x12345555
/* How many milliseconds to wait before retrying the request */
-#define RETRY_TIME 500
-#define MAX_RETRIES 30
+#define RETRY_TIME 2000
+#define MAX_RETRIES 8
static bootp_header_t *bp_info;
#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP
static const unsigned char dhcpCookie[] = {99,130,83,99};
@@ -71,10 +71,11 @@ static const unsigned char dhcpEnd[] = {
static const unsigned char dhcpDiscover[] = {53,1,1};
static const unsigned char dhcpOffer[] = {53,1,2};
static const unsigned char dhcpRequest[] = {53,1,3};
static const unsigned char dhcpRequestIP[] = {50,4};
static const unsigned char dhcpAck[] = {53,1,5};
+static const unsigned char dhcpNak[] = {53,1,6};
static const unsigned char dhcpParamRequestList[] = {55,3,1,3,6};
static enum {
DHCP_NONE = 0,
DHCP_DISCOVER,
DHCP_OFFER,
@@ -134,17 +135,20 @@ bootp_handler(udp_socket_t *skt, char *b
}
break;
case DHCP_NONE:
case DHCP_OFFER:
case DHCP_ACK:
- diag_printf("Invalid DHCP reply state: %d\n", dhcpState);
- dhcpState = DHCP_NONE; // Reset state machine
+ // Quitely ignore these - they indicate repeated message from server
+ return;
+ }
+ // See if we've been NAK'd - if so, give up and try again
+ if (memcmp(p, dhcpNak, sizeof(dhcpNak)) == 0) {
+ dhcpState = DHCP_NONE;
return;
}
diag_printf("DHCP reply: %d/%d/%d, not %d/%d/%d\n",
p[0], p[1], p[2], expected[0], expected[1], expected[2]);
- dhcpState = DHCP_NONE; // Reset state machine
return;
#else
// Simple BOOTP - this is all there is!
memcpy(__local_ip_addr, &b->bp_yiaddr, 4);
#endif
@@ -165,10 +169,11 @@ __bootp_find_local_ip(bootp_header_t *in
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;
@@ -221,75 +226,78 @@ __bootp_find_local_ip(bootp_header_t *in
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:
- // These states should never occur here!
- diag_printf("Invalid DHCP state: %d\n", dhcpState);
- abort = true;
}
- if (abort) break; // From while loop
// 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);
do {
__enet_poll();
#ifdef CYGSEM_REDBOOT_NETWORKING_DHCP
- if (dhcpState == DHCP_ACK) {
- unsigned char *end;
- int optlen;
- // Address information has now arrived!
- memcpy(__local_ip_addr, &bp_info->bp_yiaddr, 4);
+ 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);
+ 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) {
- case TAG_SUBNET_MASK: // subnet mask
- memcpy(__local_ip_mask,p,4);
+ 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) {
+ case TAG_SUBNET_MASK: // subnet mask
+ memcpy(__local_ip_mask,p,4);
+ break;
#ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
- case TAG_GATEWAY: // router
- memcpy(__local_ip_gate,p,4);
- break;
-#endif
- default:
- break;
+ case TAG_GATEWAY: // router
+ memcpy(__local_ip_gate,p,4);
+ break;
+#endif
+ default:
+ break;
+ }
}
+ p += optlen;
}
- p += optlen;
+ __udp_remove_listener(IPPORT_BOOTPC);
+ return 0;
+ } else {
+ break; // State changed, handle it
}
- __udp_remove_listener(IPPORT_BOOTPC);
- return 0;
}
#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]) {