Index: lib/libstand/bootp.c =================================================================== --- lib/libstand/bootp.c (revision 256006) +++ lib/libstand/bootp.c (working copy) @@ -73,18 +73,10 @@ /* Local forwards */ static ssize_t bootpsend(struct iodesc *, void *, size_t); static ssize_t bootprecv(struct iodesc *, void *, size_t, time_t); -static int vend_rfc1048(u_char *, u_int); #ifdef BOOTP_VEND_CMU static void vend_cmu(u_char *); #endif -#ifdef DHCP_ENV /* export the dhcp response to kenv */ -struct dhcp_opt; -static void setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts); -#else -#define setenv_(a, b, c) -#endif - #ifdef SUPPORT_DHCP static char expected_dhcpmsgtype = -1, dhcp_ok; struct in_addr dhcp_serverip; @@ -330,7 +322,7 @@ /* Suck out vendor info */ if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) { - if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0) + if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend), 1) != 0) goto bad; } #ifdef BOOTP_VEND_CMU @@ -346,10 +338,11 @@ return (-1); } -static int -vend_rfc1048(cp, len) +int +vend_rfc1048(cp, len, check_dhcp_messagetype) u_char *cp; u_int len; + int check_dhcp_messagetype; { u_char *ep; int size; @@ -364,7 +357,7 @@ /* Step over magic cookie */ cp += sizeof(int); - setenv_(cp, ep, NULL); + dhcp_setenv(cp, ep, NULL); while (cp < ep) { tag = *cp++; @@ -373,7 +366,7 @@ break; if (tag == TAG_SUBNET_MASK) { - bcopy(cp, &smask, sizeof(smask)); + bcopy(cp, &netmask, sizeof(netmask)); } if (tag == TAG_GATEWAY) { bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr)); @@ -391,9 +384,11 @@ hostname[size] = '\0'; } #ifdef SUPPORT_DHCP - if (tag == TAG_DHCP_MSGTYPE) { - if(*cp != expected_dhcpmsgtype) + if (check_dhcp_messagetype && tag == TAG_DHCP_MSGTYPE) { + if(*cp != expected_dhcpmsgtype) { + printf("Unexpected DHCP message type 0x%x\n", *cp); return(-1); + } dhcp_ok = 1; } if (tag == TAG_SERVERID) { @@ -452,12 +447,6 @@ __VE, /* vendor specific, recurse */ }; -struct dhcp_opt { - uint8_t tag; - uint8_t fmt; - const char *desc; -}; - static struct dhcp_opt vndr_opt[] = { /* Vendor Specific Options */ #if DHCP_ENV == DHCP_ENV_FREEBSD /* FreeBSD table in the original code */ {0, 0, "FreeBSD"}, /* prefix */ @@ -602,8 +591,8 @@ * names and values according to the tables above. Also set dhcp.tags * to the list of selected tags. */ -static void -setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts) +void +dhcp_setenv(u_char *cp, u_char *ep, struct dhcp_opt *opts) { u_char *ncp; u_char tag; @@ -651,7 +640,7 @@ break; /* should not happen */ case __VE: /* recurse, vendor specific */ - setenv_(cp, cp+size, vndr_opt); + dhcp_setenv(cp, cp+size, vndr_opt); break; case __IP: /* ip address */ Index: lib/libstand/net.h =================================================================== --- lib/libstand/net.h (revision 256006) +++ lib/libstand/net.h (working copy) @@ -108,7 +108,18 @@ void *, size_t); /* bootp/DHCP */ +#ifndef DHCP_OPT_DEFINED +#define DHCP_OPT_DEFINED +struct dhcp_opt { + uint8_t tag; + uint8_t fmt; + const char *desc; +}; +#endif + void bootp(int, int); +int vend_rfc1048(u_char *, u_int, int); +void dhcp_setenv(u_char *, u_char *, struct dhcp_opt *); /* Utilities: */ char *ether_sprintf(u_char *); Index: sys/boot/i386/libi386/pxe.c =================================================================== --- sys/boot/i386/libi386/pxe.c (revision 256006) +++ sys/boot/i386/libi386/pxe.c (working copy) @@ -255,6 +255,7 @@ char temp[FNAME_SIZE]; int error = 0; int i; + struct iodesc *d; va_start(args, f); devname = va_arg(args, char*); @@ -272,44 +273,51 @@ if (pxe_debug) printf("pxe_open: netif_open() succeeded\n"); } - if (rootip.s_addr == 0) { - /* - * 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. - */ - bootp(pxe_sock, BOOTP_PXE); - if (rootip.s_addr == 0) - rootip.s_addr = bootplayer.sip; - if (!rootpath[0]) - strcpy(rootpath, PXENFSROOTPATH); + /* + * Populate global variables and socket descriptor with + * data from the cached DHCP response. + */ + + d = socktodesc(pxe_sock); + d->myip.s_addr = myip.s_addr = bootplayer.yip; + rootip.s_addr = bootplayer.sip; + gateip.s_addr = bootplayer.gip; + vend_rfc1048((u_char *)&(bootplayer.vendor.d), 1024, 0); - for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) - if (rootpath[i] == ':') - break; - if (i && i != FNAME_SIZE && rootpath[i] == ':') { - rootpath[i++] = '\0'; - if (inet_addr(&rootpath[0]) != INADDR_NONE) - rootip.s_addr = inet_addr(&rootpath[0]); - bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); - bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); - } - printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); - printf("pxe_open: server path: %s\n", rootpath); - printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); + /* If no root path was provided, use a default. */ + if (!rootpath[0]) + strcpy(rootpath, PXENFSROOTPATH); - setenv("boot.netif.ip", inet_ntoa(myip), 1); - setenv("boot.netif.netmask", intoa(netmask), 1); - setenv("boot.netif.gateway", inet_ntoa(gateip), 1); - if (bootplayer.Hardware == ETHER_TYPE) { - sprintf(temp, "%6D", bootplayer.CAddr, ":"); - setenv("boot.netif.hwaddr", temp, 1); - } - setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); - setenv("boot.nfsroot.path", rootpath, 1); - setenv("dhcp.host-name", hostname, 1); + /* Parse the root path DHCP option for the server IP and NFS mount path. */ + for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) + if (rootpath[i] == ':') + break; + if (i && i != FNAME_SIZE && rootpath[i] == ':') { + rootpath[i++] = '\0'; + if (inet_addr(&rootpath[0]) != INADDR_NONE) + rootip.s_addr = inet_addr(&rootpath[0]); + bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); + bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); } + + printf("pxe_open: ip address: %s/%d\n", inet_ntoa(myip), (33 - ffs(bswap32(netmask)))); + printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); + printf("pxe_open: server path: %s\n", rootpath); + printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); + + setenv("boot.netif.ip", inet_ntoa(myip), 1); + setenv("boot.netif.netmask", intoa(netmask), 1); + setenv("boot.netif.gateway", inet_ntoa(gateip), 1); + if (bootplayer.Hardware == ETHER_TYPE) { + sprintf(temp, "%6D", bootplayer.CAddr, ":"); + setenv("boot.netif.hwaddr", temp, 1); + } + setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); + setenv("boot.nfsroot.path", rootpath, 1); + setenv("dhcp.host-name", hostname, 1); + + /* Leak a reference so we don't do this all again */ + pxe_opens++; } pxe_opens++; f->f_devdata = &pxe_sock;