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>
