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 
                                        <[EMAIL PROTECTED]>


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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to