Author: kevans
Date: Sat Feb 10 04:56:07 2018
New Revision: 329100
URL: https://svnweb.freebsd.org/changeset/base/329100

Log:
  MFC Loader Fixes 2017q2: r316437,r316577,r316578,r316585,r316590,r316612,
  r316625,r316628,r316654,r316682,r316704,r316771,r317092,r317097,r317099,
  r317652,r317785,r317886,r317887,r318142,r318320,r318356,r318678,r318754,
  r318982,r318986,r318987,r318988,r318989,r318990,r318991,r318992,r318993,
  r318994,r318999,r319083,r319084,r319085,r320011,r320234,r320288,r320304,
  r320467,r320482
  
  r316437: Small cleanup to make i386/loader match efi/loader boot environment
  code
  
  r316577: loader: part.c cstyle cleanup
  
  r316578: loader: want mechanism to avoid RA with bcache
  
  r316585: loader: zfs reader should check all labels
  
  r316590: libstand/dosfs: cache FAT32 in 128 Kb blocks to save loader memory
  
  r316612: In r298230 the value of HEAP_MIN was changed from 3MB to 64MB.
  Correct a comment.
  
  r316625: Do not use -msoft-float with intention of disabling FP on aarch64
  
  r316628: Silence GCC warning by initializing the local variable.
  
  r316654: loader: r316585 did miss userboot update
  
  r316682: loader: r316585 did miss sparc/ofw
  
  r316704: loader.efi: only fetch zfs pool guid for the actual boot device
  
  r316771: loader: Avoid possible overflow via environment variable
  
  r317092: loader: zfs reader vdev_probe should check for minimum device size
  
  r317097: loader: F_READ/F_WRITE should be checked against masked flag
  
  r317099: loader: uboot disk ioctl should call disk_ioctl
  
  r317652: loader.efi: ResetSystem does not use data with EFI_SUCCESS
  
  r317785: zfsboot: drvsize() may be unusable on some systems
  
  r317886: distinguish NFS versus TFTP boot by rootpath
  
  r317887: loader: network read rework
  
  r318142: libstand: NULL pointer dereference in rarp
  
  r318320: loader: add ip layer code into libstand
  
  r318356: libstand: increase nfs max read size to 16k
  
  r318678: Replacing iterating over rootpath by strsep(3).
  
  r318754: Pass -N directly to ld via -Wl rather than passing it to the
  compiler driver.
  
  r318982: Pass a "FREEBSD" user-class in PXE dhcp request
  
  r318986: add a comment on vendor index 19 and 20 to avoid confusion
  
  r318987: Support URI scheme for root-path in netbooting
  
  r318988: Always build tftpfs support along with nfs for pxeboot
  
  r318989: Always issue the pxe request
  
  r318990: Partially revert r314948
  
  r318991: Document recent changes on pxeboot
  
  r318992: Capitalize DHCP
  
  r318993: Use the usual FreeBSD spelling for the DHCP user class
  
  r318994: Catch with the change in the user class
  
  r318999: Update the comments concerning net_parse_rootpath to reflect what
  it is now
  
  r319083: Followup on the user-class changes
  
  r319084: Small cleanup in dev_net.c
  
  r319085: use the same option list for dhcp discovery and request
  
  r320011: Add chain loader support for loader
  
  r320234: Make structure padding explicit in EFI_MEMORY_DESCRIPTOR
  
  r320288: Allow Clang's integrated assembler to assemble boot0
  
  r320304: loader.efi: Disable smbios for arm
  
  r320467: loader: chain load relocate data declaration is bad
  
  r320482: As with arm64 mark the EFI PE header as allocated on arm.
  
  PR:           218473

Added:
  stable/11/lib/libstand/ip.c
     - copied unchanged from r318320, head/lib/libstand/ip.c
  stable/11/sys/boot/i386/libi386/relocater_tramp.S
     - copied unchanged from r320011, 
head/sys/boot/i386/libi386/relocater_tramp.S
  stable/11/sys/boot/i386/loader/chain.c
     - copied, changed from r320011, head/sys/boot/i386/loader/chain.c
Modified:
  stable/11/lib/libstand/Makefile
  stable/11/lib/libstand/arp.c
  stable/11/lib/libstand/bootp.c
  stable/11/lib/libstand/bootp.h
  stable/11/lib/libstand/bootparam.c
  stable/11/lib/libstand/dosfs.c
  stable/11/lib/libstand/dosfs.h
  stable/11/lib/libstand/ether.c
  stable/11/lib/libstand/globals.c
  stable/11/lib/libstand/net.c
  stable/11/lib/libstand/net.h
  stable/11/lib/libstand/netif.c
  stable/11/lib/libstand/netif.h
  stable/11/lib/libstand/nfs.c
  stable/11/lib/libstand/rarp.c
  stable/11/lib/libstand/rpc.c
  stable/11/lib/libstand/rpc.h
  stable/11/lib/libstand/stand.h
  stable/11/lib/libstand/tftp.c
  stable/11/lib/libstand/udp.c
  stable/11/share/mk/bsd.stand.mk
  stable/11/sys/boot/common/bcache.c
  stable/11/sys/boot/common/commands.c
  stable/11/sys/boot/common/dev_net.c
  stable/11/sys/boot/common/disk.c
  stable/11/sys/boot/common/md.c
  stable/11/sys/boot/common/part.c
  stable/11/sys/boot/efi/Makefile.inc
  stable/11/sys/boot/efi/boot1/Makefile
  stable/11/sys/boot/efi/boot1/boot1.c
  stable/11/sys/boot/efi/boot1/zfs_module.c
  stable/11/sys/boot/efi/fdt/Makefile
  stable/11/sys/boot/efi/include/efidef.h
  stable/11/sys/boot/efi/libefi/Makefile
  stable/11/sys/boot/efi/libefi/efinet.c
  stable/11/sys/boot/efi/libefi/efipart.c
  stable/11/sys/boot/efi/libefi/time.c
  stable/11/sys/boot/efi/loader/Makefile
  stable/11/sys/boot/efi/loader/arch/arm/start.S
  stable/11/sys/boot/efi/loader/arch/arm64/Makefile.inc
  stable/11/sys/boot/efi/loader/main.c
  stable/11/sys/boot/forth/menu.rc
  stable/11/sys/boot/i386/boot0/Makefile
  stable/11/sys/boot/i386/common/drv.h
  stable/11/sys/boot/i386/libi386/Makefile
  stable/11/sys/boot/i386/libi386/bioscd.c
  stable/11/sys/boot/i386/libi386/biosdisk.c
  stable/11/sys/boot/i386/libi386/biosmem.c
  stable/11/sys/boot/i386/libi386/libi386.h
  stable/11/sys/boot/i386/libi386/pxe.c
  stable/11/sys/boot/i386/libi386/pxe.h
  stable/11/sys/boot/i386/loader/Makefile
  stable/11/sys/boot/i386/loader/help.i386
  stable/11/sys/boot/i386/loader/main.c
  stable/11/sys/boot/i386/pxeldr/pxeboot.8
  stable/11/sys/boot/i386/zfsboot/zfsboot.c
  stable/11/sys/boot/mips/beri/boot2/Makefile
  stable/11/sys/boot/mips/beri/loader/beri_disk_cfi.c
  stable/11/sys/boot/mips/beri/loader/beri_disk_sdcard.c
  stable/11/sys/boot/ofw/libofw/ofw_disk.c
  stable/11/sys/boot/ofw/libofw/ofw_net.c
  stable/11/sys/boot/ofw/libofw/openfirm.c
  stable/11/sys/boot/ofw/libofw/openfirm.h
  stable/11/sys/boot/powerpc/ps3/ps3cdrom.c
  stable/11/sys/boot/powerpc/ps3/ps3disk.c
  stable/11/sys/boot/sparc64/loader/main.c
  stable/11/sys/boot/uboot/lib/disk.c
  stable/11/sys/boot/uboot/lib/net.c
  stable/11/sys/boot/usb/storage/umass_loader.c
  stable/11/sys/boot/userboot/userboot/main.c
  stable/11/sys/boot/userboot/userboot/userboot_disk.c
  stable/11/sys/boot/zfs/libzfs.h
  stable/11/sys/boot/zfs/zfsimpl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libstand/Makefile
==============================================================================
--- stable/11/lib/libstand/Makefile     Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/Makefile     Sat Feb 10 04:56:07 2018        
(r329100)
@@ -141,7 +141,7 @@ SRCS+=      closeall.c dev.c ioctl.c nullfs.c stat.c \
        fstat.c close.c lseek.c open.c read.c write.c readdir.c
 
 # network routines
-SRCS+= arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
+SRCS+= arp.c ether.c ip.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
 
 # network info services:
 SRCS+= bootp.c rarp.c bootparam.c

Modified: stable/11/lib/libstand/arp.c
==============================================================================
--- stable/11/lib/libstand/arp.c        Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/arp.c        Sat Feb 10 04:56:07 2018        
(r329100)
@@ -65,17 +65,16 @@ int arp_num = 1;
 
 /* Local forwards */
 static ssize_t arpsend(struct iodesc *, void *, size_t);
-static ssize_t arprecv(struct iodesc *, void *, size_t, time_t);
+static ssize_t arprecv(struct iodesc *, void **, void **, time_t);
 
 /* Broadcast an ARP packet, asking who has addr on interface d */
 u_char *
-arpwhohas(d, addr)
-       struct iodesc *d;
-       struct in_addr addr;
+arpwhohas(struct iodesc *d, struct in_addr addr)
 {
        int i;
        struct ether_arp *ah;
        struct arp_list *al;
+       void *pkt;
        struct {
                struct ether_header eh;
                struct {
@@ -83,13 +82,6 @@ arpwhohas(d, addr)
                        u_char pad[18];         /* 60 - sizeof(...) */
                } data;
        } wbuf;
-       struct {
-               struct ether_header eh;
-               struct {
-                       struct ether_arp arp;
-                       u_char pad[24];         /* extra space */
-               } data;
-       } rbuf;
 
        /* Try for cached answer first */
        for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
@@ -122,20 +114,24 @@ arpwhohas(d, addr)
        /* Store ip address in cache (incomplete entry). */
        al->addr = addr;
 
+       pkt = NULL;
+       ah = NULL;
        i = sendrecv(d,
            arpsend, &wbuf.data, sizeof(wbuf.data),
-           arprecv, &rbuf.data, sizeof(rbuf.data));
+           arprecv, &pkt, (void **)&ah);
        if (i == -1) {
                panic("arp: no response for %s\n",
                          inet_ntoa(addr));
        }
 
        /* Store ethernet address in cache */
-       ah = &rbuf.data.arp;
 #ifdef ARP_DEBUG
        if (debug) {
+               struct ether_header *eh;
+
+               eh = (struct ether_header *)((uintptr_t)pkt + ETHER_ALIGN);
                printf("arp: response from %s\n",
-                   ether_sprintf(rbuf.eh.ether_shost));
+                   ether_sprintf(eh->ether_shost));
                printf("arp: cacheing %s --> %s\n",
                    inet_ntoa(addr), ether_sprintf(ah->arp_sha));
        }
@@ -143,14 +139,12 @@ arpwhohas(d, addr)
        MACPY(ah->arp_sha, al->ea);
        ++arp_num;
 
+       free(pkt);
        return (al->ea);
 }
 
 static ssize_t
-arpsend(d, pkt, len)
-       struct iodesc *d;
-       void *pkt;
-       size_t len;
+arpsend(struct iodesc *d, void *pkt, size_t len)
 {
 
 #ifdef ARP_DEBUG
@@ -166,28 +160,27 @@ arpsend(d, pkt, len)
  * else -1 (and errno == 0)
  */
 static ssize_t
-arprecv(d, pkt, len, tleft)
-       struct iodesc *d;
-       void *pkt;
-       size_t len;
-       time_t tleft;
+arprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
 {
        ssize_t n;
        struct ether_arp *ah;
        u_int16_t etype;        /* host order */
+       void *ptr;
 
 #ifdef ARP_DEBUG
        if (debug)
                printf("arprecv: ");
 #endif
 
-       n = readether(d, pkt, len, tleft, &etype);
+       ptr = NULL;
+       n = readether(d, &ptr, (void **)&ah, tleft, &etype);
        errno = 0;      /* XXX */
        if (n == -1 || n < sizeof(struct ether_arp)) {
 #ifdef ARP_DEBUG
                if (debug)
                        printf("bad len=%d\n", n);
 #endif
+               free(ptr);
                return (-1);
        }
 
@@ -196,12 +189,11 @@ arprecv(d, pkt, len, tleft)
                if (debug)
                        printf("not arp type=%d\n", etype);
 #endif
+               free(ptr);
                return (-1);
        }
 
        /* Ethernet address now checked in readether() */
-
-       ah = (struct ether_arp *)pkt;
        if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
            ah->arp_pro != htons(ETHERTYPE_IP) ||
            ah->arp_hln != sizeof(ah->arp_sha) ||
@@ -211,6 +203,7 @@ arprecv(d, pkt, len, tleft)
                if (debug)
                        printf("bad hrd/pro/hln/pln\n");
 #endif
+               free(ptr);
                return (-1);
        }
 
@@ -220,6 +213,7 @@ arprecv(d, pkt, len, tleft)
                        printf("is request\n");
 #endif
                arp_reply(d, ah);
+               free(ptr);
                return (-1);
        }
 
@@ -228,6 +222,7 @@ arprecv(d, pkt, len, tleft)
                if (debug)
                        printf("not ARP reply\n");
 #endif
+               free(ptr);
                return (-1);
        }
 
@@ -239,6 +234,7 @@ arprecv(d, pkt, len, tleft)
                if (debug)
                        printf("unwanted address\n");
 #endif
+               free(ptr);
                return (-1);
        }
        /* We don't care who the reply was sent to. */
@@ -248,6 +244,8 @@ arprecv(d, pkt, len, tleft)
        if (debug)
                printf("got it\n");
 #endif
+       *pkt = ptr;
+       *payload = ah;
        return (n);
 }
 
@@ -256,9 +254,7 @@ arprecv(d, pkt, len, tleft)
  * Notes:  Re-uses buffer.  Pad to length = 46.
  */
 void
-arp_reply(d, pkt)
-       struct iodesc *d;
-       void *pkt;              /* the request */
+arp_reply(struct iodesc *d, void *pkt)
 {
        struct ether_arp *arp = pkt;
 

Modified: stable/11/lib/libstand/bootp.c
==============================================================================
--- stable/11/lib/libstand/bootp.c      Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/bootp.c      Sat Feb 10 04:56:07 2018        
(r329100)
@@ -38,6 +38,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/limits.h>
 #include <sys/endian.h>
@@ -72,7 +73,7 @@ static        char vm_cmu[4] = VM_CMU;
 
 /* Local forwards */
 static ssize_t bootpsend(struct iodesc *, void *, size_t);
-static ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
+static ssize_t bootprecv(struct iodesc *, void **, void **, time_t);
 static int vend_rfc1048(u_char *, u_int);
 #ifdef BOOTP_VEND_CMU
 static void vend_cmu(u_char *);
@@ -89,23 +90,50 @@ static void setenv_(u_char *cp,  u_char *ep, struct dh
 static char expected_dhcpmsgtype = -1, dhcp_ok;
 struct in_addr dhcp_serverip;
 #endif
+struct bootp *bootp_response;
+size_t bootp_response_size;
 
+static void
+bootp_fill_request(unsigned char *bp_vend)
+{
+       /*
+        * We are booting from PXE, we want to send the string
+        * 'PXEClient' to the DHCP server so you have the option of
+        * only responding to PXE aware dhcp requests.
+        */
+       bp_vend[0] = TAG_CLASSID;
+       bp_vend[1] = 9;
+       bcopy("PXEClient", &bp_vend[2], 9);
+       bp_vend[11] = TAG_USER_CLASS;
+       /* len of each user class + number of user class */
+       bp_vend[12] = 8;
+       /* len of the first user class */
+       bp_vend[13] = 7;
+       bcopy("FreeBSD", &bp_vend[14], 7);
+       bp_vend[21] = TAG_PARAM_REQ;
+       bp_vend[22] = 7;
+       bp_vend[23] = TAG_ROOTPATH;
+       bp_vend[24] = TAG_HOSTNAME;
+       bp_vend[25] = TAG_SWAPSERVER;
+       bp_vend[26] = TAG_GATEWAY;
+       bp_vend[27] = TAG_SUBNET_MASK;
+       bp_vend[28] = TAG_INTF_MTU;
+       bp_vend[29] = TAG_SERVERID;
+       bp_vend[30] = TAG_END;
+}
+
 /* Fetch required bootp infomation */
 void
-bootp(sock, flag)
-       int sock;
-       int flag;
+bootp(int sock)
 {
+       void *pkt;
        struct iodesc *d;
        struct bootp *bp;
        struct {
                u_char header[HEADER_SIZE];
                struct bootp wbootp;
        } wbuf;
-       struct {
-               u_char header[HEADER_SIZE];
-               struct bootp rbootp;
-       } rbuf;
+       struct bootp *rbootp;
 
 #ifdef BOOTP_DEBUG
        if (debug)
@@ -137,29 +165,8 @@ bootp(sock, flag)
        bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
        bp->bp_vend[5] = 1;
        bp->bp_vend[6] = DHCPDISCOVER;
+       bootp_fill_request(&bp->bp_vend[7]);
 
-       /*
-        * If we are booting from PXE, we want to send the string
-        * 'PXEClient' to the DHCP server so you have the option of
-        * only responding to PXE aware dhcp requests.
-        */
-       if (flag & BOOTP_PXE) {
-               bp->bp_vend[7] = TAG_CLASSID;
-               bp->bp_vend[8] = 9;
-               bcopy("PXEClient", &bp->bp_vend[9], 9);
-               bp->bp_vend[18] = TAG_PARAM_REQ;
-               bp->bp_vend[19] = 8;
-               bp->bp_vend[20] = TAG_ROOTPATH;
-               bp->bp_vend[21] = TAG_TFTP_SERVER;
-               bp->bp_vend[22] = TAG_HOSTNAME;
-               bp->bp_vend[23] = TAG_SWAPSERVER;
-               bp->bp_vend[24] = TAG_GATEWAY;
-               bp->bp_vend[25] = TAG_SUBNET_MASK;
-               bp->bp_vend[26] = TAG_INTF_MTU;
-               bp->bp_vend[27] = TAG_SERVERID;
-               bp->bp_vend[28] = TAG_END;
-       } else
-               bp->bp_vend[7] = TAG_END;
 #else
        bp->bp_vend[4] = TAG_END;
 #endif
@@ -176,8 +183,7 @@ bootp(sock, flag)
 
        if(sendrecv(d,
                    bootpsend, bp, sizeof(*bp),
-                   bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
-          == -1) {
+                   bootprecv, &pkt, (void **)&rbootp) == -1) {
            printf("bootp: no reply\n");
            return;
        }
@@ -188,7 +194,7 @@ bootp(sock, flag)
                bp->bp_vend[6] = DHCPREQUEST;
                bp->bp_vend[7] = TAG_REQ_ADDR;
                bp->bp_vend[8] = 4;
-               bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
+               bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4);
                bp->bp_vend[13] = TAG_SERVERID;
                bp->bp_vend[14] = 4;
                bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
@@ -196,30 +202,25 @@ bootp(sock, flag)
                bp->bp_vend[20] = 4;
                leasetime = htonl(300);
                bcopy(&leasetime, &bp->bp_vend[21], 4);
-               if (flag & BOOTP_PXE) {
-                       bp->bp_vend[25] = TAG_CLASSID;
-                       bp->bp_vend[26] = 9;
-                       bcopy("PXEClient", &bp->bp_vend[27], 9);
-                       bp->bp_vend[36] = TAG_END;
-               } else
-                       bp->bp_vend[25] = TAG_END;
+               bootp_fill_request(&bp->bp_vend[25]);
 
                expected_dhcpmsgtype = DHCPACK;
 
+               free(pkt);
                if(sendrecv(d,
                            bootpsend, bp, sizeof(*bp),
-                           bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
-                  == -1) {
+                           bootprecv, &pkt, (void **)&rbootp) == -1) {
                        printf("DHCPREQUEST failed\n");
                        return;
                }
        }
 #endif
 
-       myip = d->myip = rbuf.rbootp.bp_yiaddr;
-       servip = rbuf.rbootp.bp_siaddr;
-       if(rootip.s_addr == INADDR_ANY) rootip = servip;
-       bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
+       myip = d->myip = rbootp->bp_yiaddr;
+       servip = rbootp->bp_siaddr;
+       if (rootip.s_addr == INADDR_ANY)
+               rootip = servip;
+       bcopy(rbootp->bp_file, bootfile, sizeof(bootfile));
        bootfile[sizeof(bootfile) - 1] = '\0';
 
        if (!netmask) {
@@ -259,14 +260,12 @@ bootp(sock, flag)
 
        /* Bump xid so next request will be unique. */
        ++d->xid;
+       free(pkt);
 }
 
 /* Transmit a bootp request */
 static ssize_t
-bootpsend(d, pkt, len)
-       struct iodesc *d;
-       void *pkt;
-       size_t len;
+bootpsend(struct iodesc *d, void *pkt, size_t len)
 {
        struct bootp *bp;
 
@@ -287,30 +286,25 @@ bootpsend(d, pkt, len)
 }
 
 static ssize_t
-bootprecv(d, pkt, len, tleft)
-struct iodesc *d;
-void *pkt;
-size_t len;
-time_t tleft;
+bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
 {
        ssize_t n;
        struct bootp *bp;
+       void *ptr;
 
-#ifdef BOOTP_DEBUGx
+#ifdef BOOTP_DEBUG
        if (debug)
                printf("bootp_recvoffer: called\n");
 #endif
 
-       n = readudp(d, pkt, len, tleft);
+       ptr = NULL;
+       n = readudp(d, &ptr, (void **)&bp, tleft);
        if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
                goto bad;
 
-       bp = (struct bootp *)pkt;
-       
 #ifdef BOOTP_DEBUG
        if (debug)
-               printf("bootprecv: checked.  bp = 0x%lx, n = %d\n",
-                   (long)bp, (int)n);
+               printf("bootprecv: checked.  bp = %p, n = %zd\n", bp, n);
 #endif
        if (bp->bp_xid != htonl(d->xid)) {
 #ifdef BOOTP_DEBUG
@@ -329,8 +323,21 @@ time_t tleft;
 
        /* 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)
+               int vsize = n - offsetof(struct bootp, bp_vend);
+               if (vend_rfc1048(bp->bp_vend, vsize) != 0)
                    goto bad;
+
+               /* Save copy of bootp reply or DHCP ACK message */
+               if (bp->bp_op == BOOTREPLY &&
+                   ((dhcp_ok == 1 && expected_dhcpmsgtype == DHCPACK) ||
+                   dhcp_ok == 0)) {
+                       free(bootp_response);
+                       bootp_response = malloc(n);
+                       if (bootp_response != NULL) {
+                               bootp_response_size = n;
+                               bcopy(bp, bootp_response, bootp_response_size);
+                       }
+               }
        }
 #ifdef BOOTP_VEND_CMU
        else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
@@ -339,8 +346,11 @@ time_t tleft;
        else
                printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
 
-       return(n);
+       *pkt = ptr;
+       *payload = bp;
+       return (n);
 bad:
+       free(ptr);
        errno = 0;
        return (-1);
 }
@@ -357,9 +367,7 @@ dhcp_try_rfc1048(u_char *cp, u_int len)
 }
 
 static int
-vend_rfc1048(cp, len)
-       u_char *cp;
-       u_int len;
+vend_rfc1048(u_char *cp, u_int len)
 {
        u_char *ep;
        int size;
@@ -438,10 +446,6 @@ vend_rfc1048(cp, len)
                        bcopy(cp, &dhcp_serverip.s_addr,
                              sizeof(dhcp_serverip.s_addr));
                }
-               if (tag == TAG_TFTP_SERVER) {
-                       bcopy(cp, &tftpip.s_addr,
-                             sizeof(tftpip.s_addr));
-               }
 #endif
                cp += size;
        }
@@ -450,8 +454,7 @@ vend_rfc1048(cp, len)
 
 #ifdef BOOTP_VEND_CMU
 static void
-vend_cmu(cp)
-       u_char *cp;
+vend_cmu(u_char *cp)
 {
        struct cmu_vend *vp;
 

Modified: stable/11/lib/libstand/bootp.h
==============================================================================
--- stable/11/lib/libstand/bootp.h      Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/bootp.h      Sat Feb 10 04:56:07 2018        
(r329100)
@@ -108,7 +108,7 @@ struct bootp {
 #define TAG_T2                 ((unsigned char)  59)
 #define TAG_CLASSID            ((unsigned char)  60)
 #define TAG_CLIENTID           ((unsigned char)  61)
-#define TAG_TFTP_SERVER                ((unsigned char) 150)
+#define TAG_USER_CLASS         ((unsigned char)  77)
 #endif
 
 #define TAG_END                        ((unsigned char) 255)
@@ -124,12 +124,6 @@ struct bootp {
 #endif
 
 /*
- * bootp flags
- */
-#define        BOOTP_NONE              0x0000          /* No flags */
-#define        BOOTP_PXE               0x0001          /* Booting from PXE. */
-
-/*
  * "vendor" data permitted for CMU bootp clients.
  */
 
@@ -147,6 +141,10 @@ struct cmu_vend {
 
 /* v_flags values */
 #define VF_SMASK       1       /* Subnet mask field contains valid data */
+
+/* cached bootp response/dhcp ack */
+extern struct bootp *bootp_response;
+extern size_t bootp_response_size;
 
 int    dhcp_try_rfc1048(u_char *cp, u_int len);
 

Modified: stable/11/lib/libstand/bootparam.c
==============================================================================
--- stable/11/lib/libstand/bootparam.c  Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/bootparam.c  Sat Feb 10 04:56:07 2018        
(r329100)
@@ -104,8 +104,7 @@ int xdr_string_decode(char **p, char *str, int *len_p)
  * know about us (don't want to broadcast a getport call).
  */
 int
-bp_whoami(sockfd)
-       int sockfd;
+bp_whoami(int sockfd)
 {
        /* RPC structures for PMAPPROC_CALLIT */
        struct args {
@@ -126,22 +125,19 @@ bp_whoami(sockfd)
                n_long  h[RPC_HEADER_WORDS];
                struct args d;
        } sdata;
-       struct {
-               n_long  h[RPC_HEADER_WORDS];
-               struct repl d;
-       } rdata;
        char *send_tail, *recv_head;
        struct iodesc *d;
-       int len, x;
+       void *pkt;
+       int len, x, rc;
 
        RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
 
+       rc = -1;
        if (!(d = socktodesc(sockfd))) {
                RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
-               return (-1);
+               return (rc);
        }
        args = &sdata.d;
-       repl = &rdata.d;
 
        /*
         * Build request args for PMAPPROC_CALLIT.
@@ -156,19 +152,19 @@ bp_whoami(sockfd)
         * append encapsulated data (client IP address)
         */
        if (xdr_inaddr_encode(&send_tail, myip))
-               return (-1);
+               return (rc);
 
        /* RPC: portmap/callit */
        d->myport = htons(--rpc_port);
        d->destip.s_addr = INADDR_BROADCAST;    /* XXX: subnet bcast? */
        /* rpc_call will set d->destport */
 
+       pkt = NULL;
        len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
-                                 args, send_tail - (char*)args,
-                                 repl, sizeof(*repl));
+           args, send_tail - (char*)args, (void **)&repl, &pkt);
        if (len < 8) {
                printf("bootparamd: 'whoami' call failed\n");
-               return (-1);
+               goto done;
        }
 
        /* Save bootparam server address (from IP header). */
@@ -196,7 +192,7 @@ bp_whoami(sockfd)
        x = ntohl(repl->encap_len);
        if (len < x) {
                printf("bp_whoami: short reply, %d < %d\n", len, x);
-               return (-1);
+               goto done;
        }
        recv_head = (char*) repl->capsule;
 
@@ -204,24 +200,27 @@ bp_whoami(sockfd)
        hostnamelen = MAXHOSTNAMELEN-1;
        if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
                RPC_PRINTF(("bp_whoami: bad hostname\n"));
-               return (-1);
+               goto done;
        }
 
        /* domain name */
        domainnamelen = MAXHOSTNAMELEN-1;
        if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
                RPC_PRINTF(("bp_whoami: bad domainname\n"));
-               return (-1);
+               goto done;
        }
 
        /* gateway address */
        if (xdr_inaddr_decode(&recv_head, &gateip)) {
                RPC_PRINTF(("bp_whoami: bad gateway\n"));
-               return (-1);
+               goto done;
        }
 
        /* success */
-       return(0);
+       rc = 0;
+done:
+       free(pkt);
+       return (rc);
 }
 
 
@@ -233,25 +232,18 @@ bp_whoami(sockfd)
  *     server pathname
  */
 int
-bp_getfile(sockfd, key, serv_addr, pathname)
-       int sockfd;
-       char *key;
-       char *pathname;
-       struct in_addr *serv_addr;
+bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
 {
        struct {
                n_long  h[RPC_HEADER_WORDS];
                n_long  d[64];
        } sdata;
-       struct {
-               n_long  h[RPC_HEADER_WORDS];
-               n_long  d[128];
-       } rdata;
+       void *pkt;
        char serv_name[FNAME_SIZE];
-       char *send_tail, *recv_head;
+       char *rdata, *send_tail;
        /* misc... */
        struct iodesc *d;
-       int sn_len, path_len, rlen;
+       int rc = -1, sn_len, path_len, rlen;
 
        if (!(d = socktodesc(sockfd))) {
                RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
@@ -259,7 +251,6 @@ bp_getfile(sockfd, key, serv_addr, pathname)
        }
 
        send_tail = (char*) sdata.d;
-       recv_head = (char*) rdata.d;
 
        /*
         * Build request message.
@@ -281,17 +272,16 @@ bp_getfile(sockfd, key, serv_addr, pathname)
        d->myport = htons(--rpc_port);
        d->destip   = bp_server_addr;
        /* rpc_call will set d->destport */
-
+       pkt = NULL;
        rlen = rpc_call(d,
                BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
                sdata.d, send_tail - (char*)sdata.d,
-               rdata.d, sizeof(rdata.d));
+               (void **)&rdata, &pkt);
        if (rlen < 4) {
                RPC_PRINTF(("bp_getfile: short reply\n"));
                errno = EBADRPC;
-               return (-1);
+               goto done;
        }
-       recv_head = (char*) rdata.d;
 
        /*
         * Parse result message.
@@ -299,26 +289,29 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 
        /* server name */
        sn_len = FNAME_SIZE-1;
-       if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
+       if (xdr_string_decode(&rdata, serv_name, &sn_len)) {
                RPC_PRINTF(("bp_getfile: bad server name\n"));
-               return (-1);
+               goto done;
        }
 
        /* server IP address (mountd/NFS) */
-       if (xdr_inaddr_decode(&recv_head, serv_addr)) {
+       if (xdr_inaddr_decode(&rdata, serv_addr)) {
                RPC_PRINTF(("bp_getfile: bad server addr\n"));
-               return (-1);
+               goto done;
        }
 
        /* server pathname */
        path_len = MAXPATHLEN-1;
-       if (xdr_string_decode(&recv_head, pathname, &path_len)) {
+       if (xdr_string_decode(&rdata, pathname, &path_len)) {
                RPC_PRINTF(("bp_getfile: bad server path\n"));
-               return (-1);
+               goto done;
        }
 
        /* success */
-       return(0);
+       rc = 0;
+done:
+       free(pkt);
+       return (rc);
 }
 
 
@@ -329,17 +322,14 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 
 
 int
-xdr_string_encode(pkt, str, len)
-       char **pkt;
-       char *str;
-       int len;
+xdr_string_encode(char **pkt, char *str, int len)
 {
-       u_int32_t *lenp;
+       uint32_t *lenp;
        char *datap;
        int padlen = (len + 3) & ~3;    /* padded length */
 
        /* The data will be int aligned. */
-       lenp = (u_int32_t*) *pkt;
+       lenp = (uint32_t *) *pkt;
        *pkt += sizeof(*lenp);
        *lenp = htonl(len);
 
@@ -351,18 +341,15 @@ xdr_string_encode(pkt, str, len)
 }
 
 int
-xdr_string_decode(pkt, str, len_p)
-       char **pkt;
-       char *str;
-       int *len_p;             /* bufsize - 1 */
+xdr_string_decode(char **pkt, char *str, int *len_p)
 {
-       u_int32_t *lenp;
+       uint32_t *lenp;
        char *datap;
        int slen;       /* string length */
        int plen;       /* padded length */
 
        /* The data will be int aligned. */
-       lenp = (u_int32_t*) *pkt;
+       lenp = (uint32_t *) *pkt;
        *pkt += sizeof(*lenp);
        slen = ntohl(*lenp);
        plen = (slen + 3) & ~3;
@@ -381,9 +368,7 @@ xdr_string_decode(pkt, str, len_p)
 
 
 int
-xdr_inaddr_encode(pkt, ia)
-       char **pkt;
-       struct in_addr ia;              /* network order */
+xdr_inaddr_encode(char **pkt, struct in_addr ia)
 {
        struct xdr_inaddr *xi;
        u_char *cp;
@@ -414,9 +399,7 @@ xdr_inaddr_encode(pkt, ia)
 }
 
 int
-xdr_inaddr_decode(pkt, ia)
-       char **pkt;
-       struct in_addr *ia;             /* network order */
+xdr_inaddr_decode(char **pkt, struct in_addr *ia)
 {
        struct xdr_inaddr *xi;
        u_char *cp;

Modified: stable/11/lib/libstand/dosfs.c
==============================================================================
--- stable/11/lib/libstand/dosfs.c      Sat Feb 10 04:37:44 2018        
(r329099)
+++ stable/11/lib/libstand/dosfs.c      Sat Feb 10 04:56:07 2018        
(r329100)
@@ -65,6 +65,7 @@ struct fs_ops dosfs_fsops = {
 #define DEPSEC   16             /* directory entries per sector */
 #define DSHIFT    4             /* DEPSEC shift */
 #define LOCLUS    2             /* lowest cluster number */
+#define FATBLKSZ  0x20000       /* size of block in the FAT cache buffer */
 
 /* DOS "BIOS Parameter Block" */
 typedef struct {
@@ -132,18 +133,6 @@ static DOS_DE dot[2] = {
                          ((u_int)cv2((de)->dex.h_clus) << 16) |  \
                         cv2((de)->clus))
 
-/*
- * fat cache metadata
- */
-struct fatcache {
-       int unit;       /* disk unit number */
-       int size;       /* buffer (and fat) size in sectors */
-       u_char *buf;
-};
-
-static struct fatcache fat;
-
-static int dosunmount(DOS_FS *);
 static int parsebs(DOS_FS *, DOS_BS *);
 static int namede(DOS_FS *, const char *, DOS_DE **);
 static int lookup(DOS_FS *, u_int, const char *, DOS_DE **);
@@ -153,36 +142,37 @@ static off_t fsize(DOS_FS *, DOS_DE *);
 static int fatcnt(DOS_FS *, u_int);
 static int fatget(DOS_FS *, u_int *);
 static int fatend(u_int, u_int);
-static int ioread(DOS_FS *, u_int, void *, u_int);
-static int ioget(struct open_file *, daddr_t, void *, u_int);
+static int ioread(DOS_FS *, u_int, void *, size_t);
+static int ioget(struct open_file *, daddr_t, void *, size_t);
 
-static void
-dos_read_fat(DOS_FS *fs, struct open_file *fd)
+static int
+dos_read_fatblk(DOS_FS *fs, struct open_file *fd, u_int blknum)
 {
-    struct devdesc *dd = fd->f_devdata;
+    int err;
+    size_t io_size;
+    daddr_t offset_in_fat, max_offset_in_fat;
 
-    if (fat.buf != NULL) {             /* can we reuse old buffer? */
-       if (fat.size != fs->spf) {
-           free(fat.buf);              /* no, free old buffer */
-           fat.buf = NULL;
-       }
-    }
+    offset_in_fat = ((daddr_t)blknum) * FATBLKSZ;
+    max_offset_in_fat = secbyt(fs->spf);
+    io_size = FATBLKSZ;
+    if (offset_in_fat > max_offset_in_fat)
+        offset_in_fat = max_offset_in_fat;
+    if (offset_in_fat + io_size > max_offset_in_fat)
+        io_size = ((size_t)(max_offset_in_fat - offset_in_fat));
 
-    if (fat.buf == NULL)
-       fat.buf = malloc(secbyt(fs->spf));
-
-    if (fat.buf != NULL) {
-       if (ioget(fd, fs->lsnfat, fat.buf, secbyt(fs->spf)) == 0) {
-           fat.size = fs->spf;
-           fat.unit = dd->d_unit;
-           return;
-       }
+    if (io_size != 0) {
+        err = ioget(fd, fs->lsnfat + bytsec(offset_in_fat),
+            fs->fatbuf, io_size);
+        if (err != 0) {
+            fs->fatbuf_blknum = ((u_int)(-1));
+            return (err);
+        }
     }
-    if (fat.buf != NULL)       /* got IO error */
-       free(fat.buf);
-    fat.buf = NULL;
-    fat.unit = -1;     /* impossible unit */
-    fat.size = 0;
+    if (io_size < FATBLKSZ)
+        memset(fs->fatbuf + io_size, 0, FATBLKSZ - io_size);
+
+    fs->fatbuf_blknum = blknum;
+    return (0);
 }
 
 /*
@@ -192,24 +182,27 @@ static int
 dos_mount(DOS_FS *fs, struct open_file *fd)
 {
     int err;
-    struct devdesc *dd = fd->f_devdata;
     u_char *buf;
 
     bzero(fs, sizeof(DOS_FS));
     fs->fd = fd;
 
-    if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) ||
-        (err = ioget(fs->fd, 0, buf, secbyt(1))) ||
+    if ((buf = malloc(secbyt(1))) == NULL)
+        return (errno);
+    if ((err = ioget(fs->fd, 0, buf, secbyt(1))) ||
         (err = parsebs(fs, (DOS_BS *)buf))) {
-       if (buf != NULL)
-           free(buf);
-        (void)dosunmount(fs);
+        free(buf);
         return (err);
     }
     free(buf);
 
-    if (fat.buf == NULL || fat.unit != dd->d_unit)
-       dos_read_fat(fs, fd);
+    if ((fs->fatbuf = malloc(FATBLKSZ)) == NULL)
+        return (errno);
+    err = dos_read_fatblk(fs, fd, 0);
+    if (err != 0) {
+        free(fs->fatbuf);
+        return (err);
+    }
 
     fs->root = dot[0];
     fs->root.name[0] = ' ';
@@ -228,21 +221,9 @@ dos_mount(DOS_FS *fs, struct open_file *fd)
 static int
 dos_unmount(DOS_FS *fs)
 {
-    int err;
-
     if (fs->links)
         return (EBUSY);
-    if ((err = dosunmount(fs)))
-        return (err);
-    return (0);
-}
-
-/*
- * Common code shared by dos_mount() and dos_unmount()
- */
-static int
-dosunmount(DOS_FS *fs)
-{
+    free(fs->fatbuf);
     free(fs);
     return (0);
 }
@@ -257,16 +238,20 @@ dos_open(const char *path, struct open_file *fd)
     DOS_FILE *f;
     DOS_FS *fs;
     u_int size, clus;
-    int err = 0;
+    int err;
 
     /* Allocate mount structure, associate with open */
-    fs = malloc(sizeof(DOS_FS));
-    
-    if ((err = dos_mount(fs, fd)))
-       goto out;
+    if ((fs = malloc(sizeof(DOS_FS))) == NULL)
+        return (errno);
+    if ((err = dos_mount(fs, fd))) {
+        free(fs);
+        return (err);
+    }
 
-    if ((err = namede(fs, path, &de)))
-       goto out;
+    if ((err = namede(fs, path, &de))) {
+        dos_unmount(fs);
+        return (err);
+    }
 
     clus = stclus(fs->fatsz, de);
     size = cv4(de->size);
@@ -274,18 +259,20 @@ dos_open(const char *path, struct open_file *fd)
     if ((!(de->attr & FA_DIR) && (!clus != !size)) ||
        ((de->attr & FA_DIR) && size) ||
        (clus && !okclus(fs, clus))) {
-        err = EINVAL;
-       goto out;
+        dos_unmount(fs);
+        return (EINVAL);
     }
-    f = malloc(sizeof(DOS_FILE));
+    if ((f = malloc(sizeof(DOS_FILE))) == NULL) {
+        err = errno;
+        dos_unmount(fs);
+        return (err);
+    }
     bzero(f, sizeof(DOS_FILE));
     f->fs = fs;
     fs->links++;
     f->de = *de;
     fd->f_fsdata = (void *)f;
-
- out:
-    return (err);
+    return (0);
 }
 
 /*
@@ -761,34 +748,57 @@ fatcnt(DOS_FS *fs, u_int c)
 }
 
 /*
- * Get next cluster in cluster chain. Use in core fat cache unless another
- * device replaced it.
+ * Get next cluster in cluster chain. Use in core fat cache unless
+ * the number of current 128K block in FAT has changed.
  */
 static int
 fatget(DOS_FS *fs, u_int *c)
 {
-    u_char buf[4];

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to