Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Feb 2003 20:09:53 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        freebsd-hackers@freebsd.org
Subject:   DHCP problem with pxeboot over wireless via LinkSys WAP11
Message-ID:  <200302180409.h1I49rnR048462@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help
    I came across an interesting problem trying to pxeboot a diskless
    machine over a wireless network.  

    The sequence of events goes like this:

    network bios:
	network bios issues DHCP request from 0.0.0.0 (via wireless bridge)
	my dhcp server replies
	network bios sets IP address
	network bios loads pxeboot successfully

    pxeboot runs:
	pxeboot issues DHCP request from <IP> (ip assigned by network bios)
	mh dhcp server replies
	LinkSys WAP11 eats the reply.  poof gone.

	[repeat until pxeboot gives up]

    I think the LinkSys is just plain broken but it's weird that the network
    bios was able to issue a request without the reply getting eaten, and
    the kernel (once one is able to boot that far) is also able to issue
    a request and get a reply that isn't eaten.  And yet the reply to
    pxeboot's bootp() request gets eaten by the WAP11 every time.  It works
    fine on a hard line, but blows up through the wireless.

    Anyone see this before?

    In anycase, I found a solution, which is to extract the RFC1048 data
    from the PXE cache in the PXE code.  Then if the PXE's bootp() attempt
    fails (which it does for me :-( ), it can use the data extracted from
    the PXE cache to set the appropriate variables.

    This patch is for -stable and it needs a bit of cleaning up, and still
    has some debugging, and the bootp() call is #if 0'd out to test the
    PXE cache data interpretation, but once cleaned up I believe it can be
    committed and, in fact, we might be able to avoid having to call bootp()
    at all if the PXE cache has all the necessary info.

					-Matt
					Matthew Dillon 
					<dillon@backplane.com>


Index: i386/libi386/pxe.c
===================================================================
RCS file: /home/ncvs/src/sys/boot/i386/libi386/pxe.c,v
retrieving revision 1.3.2.9
diff -u -r1.3.2.9 pxe.c
--- i386/libi386/pxe.c	15 Mar 2001 08:35:54 -0000	1.3.2.9
+++ i386/libi386/pxe.c	18 Feb 2003 04:02:51 -0000
@@ -96,6 +96,7 @@
 extern u_int16_t		__pxenvseg;
 extern u_int16_t		__pxenvoff;
 extern void			__pxenventry(void);
+extern struct in_addr		servip;
 
 struct netif_dif pxe_ifs[] = {
 /*      dif_unit        dif_nsel        dif_stats       dif_private     */
@@ -256,6 +257,7 @@
     char temp[FNAME_SIZE];
     int error = 0;
     int i;
+    struct iodesc *d;
 	
     va_start(args, f);
     devname = va_arg(args, char*);
@@ -273,16 +275,49 @@
 	    if (pxe_debug)
 		printf("pxe_open: netif_open() succeeded\n");
 	}
+	if (!(d = socktodesc(pxe_sock))) {
+		printf("pxe_open: bad socket. %d\n", pxe_sock);
+		return (ENXIO);
+	}
 	if (rootip.s_addr == 0) {
 		/*
+		 * Try to extract the RFC1048 data from PXE
+		 *
+		 * It turns out that at some wireless bridges/access-points
+		 * eat dhcpd responses to pxeboot's bootp requests.  This
+		 * may save us if the bootp() attempt below fails.  In fact,
+		 * if we get enough info we can skip the bootp() attempt XXX.
+		 */
+		if (dhcp_try_rfc1048(bootplayer.vendor.d, BOOTP_DHCPVEND))
+		    printf("pxe_open: no RFC1048 data in PXE Cache\n");
+		else
+		    printf("pxe_open: loaded RFC1048 data from PXE Cache\n");
+
+		/*
 		 * Do a bootp/dhcp request to find out where our
 		 * NFS/TFTP server is.  Even if we dont get back
 		 * the proper information, fall back to the server
 		 * which brought us to life and a default rootpath.
 		 */
+#if 0
 		bootp(pxe_sock, BOOTP_PXE);
+#endif
+
+		/*
+		 * Failsafe
+		 */
 		if (rootip.s_addr == 0)
 			rootip.s_addr = bootplayer.sip;
+		if (gateip.s_addr == 0)
+			gateip.s_addr = bootplayer.gip;
+		if (myip.s_addr == 0)
+			myip.s_addr = bootplayer.yip;
+		if (servip.s_addr == 0)
+			servip = rootip;
+		if (d->myip.s_addr == 0)
+			d->myip = myip;
+		printf("d->MYIP %04x d->servip %04x\n", d->myip.s_addr, servip.s_addr);
+
 		if (!rootpath[1])
 			strcpy(rootpath, PXENFSROOTPATH);
 
@@ -503,6 +538,7 @@
 
 	bzero(udpopen_p, sizeof(*udpopen_p));
 	udpopen_p->src_ip = bootplayer.yip;
+
 	pxe_call(PXENV_UDP_OPEN);
 
 	if (udpopen_p->status != 0) {
@@ -549,7 +585,7 @@
 {
 	t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer;
 	bzero(udpwrite_p, sizeof(*udpwrite_p));
-	
+
 	udpwrite_p->ip             = h->destip.s_addr;
 	udpwrite_p->dst_port       = h->destport;
 	udpwrite_p->src_port       = h->myport;
Index: bootp.c
===================================================================
RCS file: /home/ncvs/src/lib/libstand/bootp.c,v
retrieving revision 1.1.1.1.6.2
diff -u -r1.1.1.1.6.2 bootp.c
--- bootp.c	20 Sep 2000 18:37:25 -0000	1.1.1.1.6.2
+++ bootp.c	18 Feb 2003 03:52:34 -0000
@@ -335,6 +335,16 @@
 	return (-1);
 }
 
+int
+dhcp_try_rfc1048(u_char *cp, u_int len)
+{
+	expected_dhcpmsgtype = DHCPACK;
+	if (bcmp(vm_rfc1048, cp, sizeof(vm_rfc1048)) == 0) {
+		return(vend_rfc1048(cp, len));
+	}
+	return(-1);
+}
+
 static int
 vend_rfc1048(cp, len)
 	register u_char *cp;
@@ -356,6 +366,7 @@
 	while (cp < ep) {
 		tag = *cp++;
 		size = *cp++;
+
 		if (tag == TAG_END)
 			break;
 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200302180409.h1I49rnR048462>