Index: etherboot-5.4.3/src/core/nic.c
===================================================================
--- etherboot-5.4.3.orig/src/core/nic.c	2008-07-31 11:45:51.000000000 -0700
+++ etherboot-5.4.3/src/core/nic.c	2008-07-31 11:49:23.000000000 -0700
@@ -63,6 +63,7 @@
 #ifdef	NO_DHCP_SUPPORT
 static unsigned char	rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
 #else	/* NO_DHCP_SUPPORT */
+static int await_bootp_ignore_proxy;
 static int dhcp_reply;
 static in_addr dhcp_server = { 0L };
 static unsigned char	rfc1533_cookie[] = { RFC1533_COOKIE };
@@ -966,6 +967,7 @@
 	struct udphdr *udp, struct tcphdr *tcp __unused)
 {
 	struct	bootp_t *bootpreply;
+	int ok_return = 0;
 	if (!udp) {
 		return 0;
 	}
@@ -1037,20 +1039,28 @@
 			       DHCP_OPT_LEN + MAX_BOOTP_EXTLEN,
 #endif	/* NO_DHCP_SUPPORT */
 			       1);
+		ok_return = 1;
 #ifdef PXE_EXPORT
 	} else {
+		int decode_rfc1533_proxydhcp(unsigned char *p, unsigned int len);
+
 		/* Offer without an IP address - use as ProxyDHCP server */
 		arptable[ARP_PROXYDHCP].ipaddr.s_addr = bootpreply->bp_siaddr.s_addr;
 		memset(arptable[ARP_PROXYDHCP].node, 0, ETH_ALEN);	/* Kill arp */
 		/* Grab only the bootfile name from a ProxyDHCP packet */
 		memcpy(KERNEL_BUF, bootpreply->bp_file, sizeof(KERNEL_BUF));
+		/* Grab server address from rfc1533 Server Identifier field*/
+		decode_rfc1533_proxydhcp(bootpreply->bp_vend,
+					 DHCP_OPT_LEN + MAX_BOOTP_EXTLEN);
+		if (await_bootp_ignore_proxy == 0)
+			ok_return = 1;
 #endif /* PXE_EXPORT */
 	}
 #ifdef	REQUIRE_VCI_ETHERBOOT
 	if (!vci_etherboot)
 		return (0);
 #endif
-	return(1);
+	return(ok_return);
 }
 
 static int bootp(void)
@@ -1115,6 +1125,7 @@
 		if (await_reply(await_bootp, 0, NULL, remaining_time))
 			return(1);
 #else
+		await_bootp_ignore_proxy = 1;
 		while ( remaining_time > 0 ) {
 			/* Collect all DHCP OFFER packets that arrive within
 			 * the timeout period. This is essential for DHCP
@@ -1124,6 +1135,7 @@
 			(void)await_reply(await_bootp, 0, NULL, remaining_time);
 			remaining_time = stop_time - currticks();
 		}
+		await_bootp_ignore_proxy = 0;
 		if ( ! arptable[ARP_CLIENT].ipaddr.s_addr ) {
 			printf("No IP address\n");
 			continue;
@@ -1153,12 +1165,21 @@
 				     sizeof(struct bootpip_t), &ip);
 			dhcp_reply=0;
 			timeout = rfc2131_sleep_interval(BOOTP_TIMEOUT, reqretry++);
-			if (!await_reply(await_bootp, 0, NULL, timeout))
+			await_bootp_ignore_proxy = 1;
+			if (!await_reply(await_bootp, 0, NULL, timeout)) {
+				await_bootp_ignore_proxy = 0;
 				continue;
+			}
+			await_bootp_ignore_proxy = 0;
 			if (dhcp_reply != DHCPACK)
 				continue;
 			dhcp_reply = 0;
 #ifdef PXE_EXPORT
+			if ( !arptable[ARP_PROXYDHCP].ipaddr.s_addr &&
+			     KERNEL_BUF[0] == '\0' ) {
+			    arptable[ARP_PROXYDHCP].ipaddr.s_addr =
+				arptable[ARP_SERVER].ipaddr.s_addr;
+			}
 			if ( arptable[ARP_PROXYDHCP].ipaddr.s_addr ) {
 #ifdef PXE_DHCP_STRICT
 				/* boot menu items must not be mixed from different servers */
@@ -2034,6 +2055,46 @@
 	return 1;	/* proceed with next block */
 }
 
+/**************************************************************************
+DECODE_RFC1533_PROXYDHCP - Decodes RFC1533 header in proxydhcp offer
+**************************************************************************/
+int decode_rfc1533_proxydhcp(unsigned char *p, unsigned int len)
+{
+	unsigned char		*endp;
+
+#define RFC1533_SERVER_IDENT 54
+
+	if (memcmp(p, rfc1533_cookie, 4))
+	  return(0); /* no RFC 1533 header found */
+	p += 4;
+	endp = p + len;
+	while (p < endp) {
+		unsigned char c = *p;
+		if (c == RFC1533_PAD) {
+			p++;
+			continue;
+		}
+		else if (c == RFC1533_END) {
+			endp = p;
+			continue;
+		}
+		else if (c == RFC1533_SERVER_IDENT)
+			arptable[ARP_PROXYDHCP].ipaddr.s_addr =
+				*(uint32_t *)(p+2);
+		else {
+#if 0
+			unsigned char *q;
+			printf("Unknown proxydhcp RFC1533-tag ");
+			for(q=p;q<p+2+TAG_LEN(p);q++)
+				printf("%hhX ",*q);
+			putchar('\n');
+#endif
+		}
+		p += TAG_LEN(p) + 2;
+	}
+	return 1;	/* proceed with next block */
+}
+
 
 /* FIXME double check TWO_SECOND_DIVISOR */
 #define TWO_SECOND_DIVISOR (RAND_MAX/TICKS_PER_SEC)
