]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_boot.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_boot.c
index 232cdc1782869505488e979b3ca7cec38e4f9d39..65728d3b1ec0e2a77540b97f015ef293414077a4 100644 (file)
@@ -1,15 +1,20 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,8 +22,8 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995, 1997 NeXT Computer, Inc. All Rights Reserved */
 /*
@@ -87,6 +92,9 @@
  *     - replaced big automatic arrays with MALLOC'd data
  */
 
+#include <nfs/nfs_conf.h>
+#if CONFIG_NFS_CLIENT
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 
 #if NETHER == 0
 
-int nfs_boot_init(struct nfs_diskless *nd, proc_t procp)
+int
+nfs_boot_init(__unused struct nfs_diskless *nd)
 {
        panic("nfs_boot_init: no ether");
 }
 
-int nfs_boot_getfh(struct nfs_diskless *nd, proc_t procp, int v3, int sotype)
+int
+nfs_boot_getfh(__unused struct nfs_diskless *nd, __unused int v3, __unused int sotype)
 {
        panic("nfs_boot_getfh: no ether");
 }
@@ -156,70 +166,71 @@ int nfs_boot_getfh(struct nfs_diskless *nd, proc_t procp, int v3, int sotype)
 
 /* bootparam RPC */
 static int bp_whoami(struct sockaddr_in *bpsin,
-       struct in_addr *my_ip, struct in_addr *gw_ip);
+    struct in_addr *my_ip, struct in_addr *gw_ip);
 static int bp_getfile(struct sockaddr_in *bpsin, const char *key,
-       struct sockaddr_in *mdsin, char *servname, char *path);
+    struct sockaddr_in *mdsin, char *servname, char *path);
 
 /* mountd RPC */
 static int md_mount(struct sockaddr_in *mdsin, char *path, int v3, int sotype,
-       u_char *fhp, u_long *fhlenp);
+    u_char *fhp, u_int32_t *fhlenp);
 
 /* other helpers */
 static int get_file_handle(struct nfs_dlmount *ndmntp);
 
 
-#define IP_FORMAT      "%d.%d.%d.%d"
-#define IP_CH(ip)      ((u_char *)ip)
-#define IP_LIST(ip)    IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
-
-extern boolean_t
-netboot_iaddr(struct in_addr * iaddr_p);
+#define IP_FORMAT       "%d.%d.%d.%d"
+#define IP_CH(ip)       ((u_char *)ip)
+#define IP_LIST(ip)     IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
 
-extern boolean_t
-netboot_rootpath(struct in_addr * server_ip,
-                char * name, int name_len, 
-                char * path, int path_len);
+#include <sys/netboot.h>
 
 /*
  * Called with an empty nfs_diskless struct to be filled in.
  */
 int
-nfs_boot_init(struct nfs_diskless *nd, __unused proc_t procp)
+nfs_boot_init(struct nfs_diskless *nd)
 {
-       struct sockaddr_in      bp_sin;
-       boolean_t               do_bpwhoami = TRUE;
-       boolean_t               do_bpgetfile = TRUE;
-       int                     error = 0;
-       struct in_addr          my_ip;
-       struct sockaddr_in *    sin_p;
+       struct sockaddr_in      bp_sin;
+       boolean_t               do_bpwhoami = TRUE;
+       boolean_t               do_bpgetfile = TRUE;
+       int                     error = 0;
+       struct in_addr          my_ip;
+       struct sockaddr_in *    sin_p;
 
        /* make sure mbuf constants are set up */
-       if (!nfs_mbuf_mlen)
+       if (!nfs_mbuf_mhlen) {
                nfs_mbuf_init();
+       }
 
        /* by this point, networking must already have been configured */
        if (netboot_iaddr(&my_ip) == FALSE) {
-           printf("nfs_boot: networking is not initialized\n");
-           error = ENXIO;
-           goto failed;
+               printf("nfs_boot: networking is not initialized\n");
+               error = ENXIO;
+               goto failed;
        }
 
        /* get the root path information */
        MALLOC_ZONE(nd->nd_root.ndm_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
        if (!nd->nd_root.ndm_path) {
-           printf("nfs_boot: can't allocate root path buffer\n");
-           error = ENOMEM;
-           goto failed;
+               printf("nfs_boot: can't allocate root path buffer\n");
+               error = ENOMEM;
+               goto failed;
+       }
+       MALLOC_ZONE(nd->nd_root.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+       if (!nd->nd_root.ndm_mntfrom) {
+               printf("nfs_boot: can't allocate root mntfrom buffer\n");
+               error = ENOMEM;
+               goto failed;
        }
        sin_p = &nd->nd_root.ndm_saddr;
        bzero((caddr_t)sin_p, sizeof(*sin_p));
        sin_p->sin_len = sizeof(*sin_p);
        sin_p->sin_family = AF_INET;
-       if (netboot_rootpath(&sin_p->sin_addr, nd->nd_root.ndm_host, 
-                            sizeof(nd->nd_root.ndm_host),
-                            nd->nd_root.ndm_path, MAXPATHLEN) == TRUE) {
-           do_bpgetfile = FALSE;
-           do_bpwhoami = FALSE;
+       if (netboot_rootpath(&sin_p->sin_addr, nd->nd_root.ndm_host,
+           sizeof(nd->nd_root.ndm_host),
+           nd->nd_root.ndm_path, MAXPATHLEN) == TRUE) {
+               do_bpgetfile = FALSE;
+               do_bpwhoami = FALSE;
        }
        nd->nd_private.ndm_saddr.sin_addr.s_addr = 0;
 
@@ -237,27 +248,28 @@ nfs_boot_init(struct nfs_diskless *nd, __unused proc_t procp)
                bp_sin.sin_len = sizeof(bp_sin);
                bp_sin.sin_family = AF_INET;
                bp_sin.sin_addr.s_addr = INADDR_BROADCAST;
-               hostnamelen = MAXHOSTNAMELEN;
                router.s_addr = 0;
                error = bp_whoami(&bp_sin, &my_ip, &router);
                if (error) {
                        printf("nfs_boot: bootparam whoami, error=%d", error);
                        goto failed;
                }
-               printf("nfs_boot: BOOTPARAMS server " IP_FORMAT "\n", 
-                      IP_LIST(&bp_sin.sin_addr));
+               printf("nfs_boot: BOOTPARAMS server " IP_FORMAT "\n",
+                   IP_LIST(&bp_sin.sin_addr));
+               lck_mtx_lock(&hostname_lock);
                printf("nfs_boot: hostname %s\n", hostname);
+               lck_mtx_unlock(&hostname_lock);
        }
        if (do_bpgetfile) {
                error = bp_getfile(&bp_sin, "root", &nd->nd_root.ndm_saddr,
-                                  nd->nd_root.ndm_host, nd->nd_root.ndm_path);
+                   nd->nd_root.ndm_host, nd->nd_root.ndm_path);
                if (error) {
                        printf("nfs_boot: bootparam get root: %d\n", error);
                        goto failed;
                }
        }
 
-#if !defined(NO_MOUNT_PRIVATE) 
+#if !defined(NO_MOUNT_PRIVATE)
        if (do_bpgetfile) { /* get private path */
                MALLOC_ZONE(nd->nd_private.ndm_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                if (!nd->nd_private.ndm_path) {
@@ -265,13 +277,19 @@ nfs_boot_init(struct nfs_diskless *nd, __unused proc_t procp)
                        error = ENOMEM;
                        goto failed;
                }
-               error = bp_getfile(&bp_sin, "private", 
-                                  &nd->nd_private.ndm_saddr,
-                                  nd->nd_private.ndm_host,
-                                  nd->nd_private.ndm_path);
+               MALLOC_ZONE(nd->nd_private.ndm_mntfrom, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
+               if (!nd->nd_private.ndm_mntfrom) {
+                       printf("nfs_boot: can't allocate private host buffer\n");
+                       error = ENOMEM;
+                       goto failed;
+               }
+               error = bp_getfile(&bp_sin, "private",
+                   &nd->nd_private.ndm_saddr,
+                   nd->nd_private.ndm_host,
+                   nd->nd_private.ndm_path);
                if (!error) {
                        char * check_path = NULL;
-                       
+
                        MALLOC_ZONE(check_path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
                        if (!check_path) {
                                printf("nfs_boot: can't allocate check_path buffer\n");
@@ -279,25 +297,23 @@ nfs_boot_init(struct nfs_diskless *nd, __unused proc_t procp)
                                goto failed;
                        }
                        snprintf(check_path, MAXPATHLEN, "%s/private", nd->nd_root.ndm_path);
-                       if ((nd->nd_root.ndm_saddr.sin_addr.s_addr 
-                            == nd->nd_private.ndm_saddr.sin_addr.s_addr)
-                           && (strcmp(check_path, nd->nd_private.ndm_path) == 0)) {
+                       if ((nd->nd_root.ndm_saddr.sin_addr.s_addr
+                           == nd->nd_private.ndm_saddr.sin_addr.s_addr)
+                           && (strncmp(check_path, nd->nd_private.ndm_path, MAXPATHLEN) == 0)) {
                                /* private path is prefix of root path, don't mount */
                                nd->nd_private.ndm_saddr.sin_addr.s_addr = 0;
                        }
                        FREE_ZONE(check_path, MAXPATHLEN, M_NAMEI);
-               }
-               else { 
+               } else {
                        /* private key not defined, don't mount */
                        nd->nd_private.ndm_saddr.sin_addr.s_addr = 0;
                }
-       }
-       else {
+       } else {
                error = 0;
        }
 #endif /* NO_MOUNT_PRIVATE */
 failed:
-       return (error);
+       return error;
 }
 
 /*
@@ -305,7 +321,7 @@ failed:
  * with file handles to be filled in.
  */
 int
-nfs_boot_getfh(struct nfs_diskless *nd, __unused proc_t procp, int v3, int sotype)
+nfs_boot_getfh(struct nfs_diskless *nd, int v3, int sotype)
 {
        int error = 0;
 
@@ -314,11 +330,11 @@ nfs_boot_getfh(struct nfs_diskless *nd, __unused proc_t procp, int v3, int sotyp
        error = get_file_handle(&nd->nd_root);
        if (error) {
                printf("nfs_boot: get_file_handle(v%d) root failed, %d\n",
-                       v3 ? 3 : 2, error);
+                   v3 ? 3 : 2, error);
                goto failed;
        }
 
-#if !defined(NO_MOUNT_PRIVATE) 
+#if !defined(NO_MOUNT_PRIVATE)
        if (nd->nd_private.ndm_saddr.sin_addr.s_addr) {
                /* get private file handle */
                nd->nd_private.ndm_nfsv3 = v3;
@@ -326,18 +342,17 @@ nfs_boot_getfh(struct nfs_diskless *nd, __unused proc_t procp, int v3, int sotyp
                error = get_file_handle(&nd->nd_private);
                if (error) {
                        printf("nfs_boot: get_file_handle(v%d) private failed, %d\n",
-                               v3 ? 3 : 2, error);
+                           v3 ? 3 : 2, error);
                        goto failed;
                }
        }
 #endif /* NO_MOUNT_PRIVATE */
 failed:
-       return (error);
+       return error;
 }
 
 static int
-get_file_handle(ndmntp)
-       struct nfs_dlmount *ndmntp;
+get_file_handle(struct nfs_dlmount *ndmntp)
 {
        char *sp, *dp, *endp;
        int error;
@@ -347,20 +362,25 @@ get_file_handle(ndmntp)
         * using RPC to mountd/mount
         */
        error = md_mount(&ndmntp->ndm_saddr, ndmntp->ndm_path, ndmntp->ndm_nfsv3,
-                       ndmntp->ndm_sotype, ndmntp->ndm_fh, &ndmntp->ndm_fhlen);
-       if (error)
-               return (error);
+           ndmntp->ndm_sotype, ndmntp->ndm_fh, &ndmntp->ndm_fhlen);
+       if (error) {
+               return error;
+       }
 
        /* Construct remote path (for getmntinfo(3)) */
-       dp = ndmntp->ndm_host;
-       endp = dp + MNAMELEN - 1;
-       dp += strlen(dp);
-       *dp++ = ':';
-       for (sp = ndmntp->ndm_path; *sp && dp < endp;)
+       dp = ndmntp->ndm_mntfrom;
+       endp = dp + MAXPATHLEN - 1;
+       for (sp = ndmntp->ndm_host; *sp && dp < endp;) {
                *dp++ = *sp++;
+       }
+       if (dp < endp) {
+               *dp++ = ':';
+       }
+       for (sp = ndmntp->ndm_path; *sp && dp < endp;) {
+               *dp++ = *sp++;
+       }
        *dp = '\0';
-       return (0);
-
+       return 0;
 }
 
 
@@ -369,24 +389,26 @@ get_file_handle(ndmntp)
  * initialize the pkthdr length field.
  */
 static int
-mbuf_get_with_len(int msg_len, mbuf_t *m)
+mbuf_get_with_len(size_t msg_len, mbuf_t *m)
 {
        int error;
        error = mbuf_gethdr(MBUF_WAITOK, MBUF_TYPE_DATA, m);
-       if (error)
-               return (error);
+       if (error) {
+               return error;
+       }
        if (msg_len > mbuf_maxlen(*m)) {
                error = mbuf_mclget(MBUF_WAITOK, MBUF_TYPE_DATA, m);
                if (error) {
                        mbuf_freem(*m);
-                       return (error);
+                       return error;
                }
-               if (msg_len > mbuf_maxlen(*m))
+               if (msg_len > mbuf_maxlen(*m)) {
                        panic("nfs_boot: msg_len > MCLBYTES");
+               }
        }
        mbuf_setlen(*m, msg_len);
        mbuf_pkthdr_setlen(*m, msg_len);
-       return (0);
+       return 0;
 }
 
 
@@ -394,20 +416,20 @@ mbuf_get_with_len(int msg_len, mbuf_t *m)
  * String representation for RPC.
  */
 struct rpc_string {
-       u_long len;             /* length without null or padding */
-       u_char data[4]; /* data (longer, of course) */
-    /* data is padded to a long-word boundary */
+       u_int32_t len;          /* length without null or padding */
+       u_char data[4]; /* data (longer, of course) */
+       /* data is padded to a long-word boundary */
 };
 /* Compute space used given string length. */
-#define        RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3))
+#define RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3))
 
 /*
  * Inet address in RPC messages
- * (Note, really four longs, NOT chars.  Blech.)
+ * (Note, really four 32-bit ints, NOT chars.  Blech.)
  */
 struct bp_inaddr {
-       u_long  atype;
-       long    addr[4];
+       u_int32_t  atype;
+       int32_t addr[4];
 };
 
 
@@ -427,17 +449,16 @@ struct bp_inaddr {
  * know about us (don't want to broadcast a getport call).
  */
 static int
-bp_whoami(bpsin, my_ip, gw_ip)
-       struct sockaddr_in *bpsin;
-       struct in_addr *my_ip;
-       struct in_addr *gw_ip;
+bp_whoami(struct sockaddr_in *bpsin,
+    struct in_addr *my_ip,
+    struct in_addr *gw_ip)
 {
        /* RPC structures for PMAPPROC_CALLIT */
        struct whoami_call {
-               u_long call_prog;
-               u_long call_vers;
-               u_long call_proc;
-               u_long call_arglen;
+               u_int32_t call_prog;
+               u_int32_t call_vers;
+               u_int32_t call_proc;
+               u_int32_t call_arglen;
                struct bp_inaddr call_ia;
        } *call;
 
@@ -445,18 +466,20 @@ bp_whoami(bpsin, my_ip, gw_ip)
        struct bp_inaddr *bia;
        mbuf_t m;
        struct sockaddr_in sin;
-       int error, msg_len;
-       int cn_len, dn_len;
+       int error;
+       size_t msg_len, cn_len, dn_len;
        u_char *p;
-       long *lp;
+       int32_t *lp;
+       size_t encapsulated_size;
 
        /*
         * Get message buffer of sufficient size.
         */
        msg_len = sizeof(*call);
        error = mbuf_get_with_len(msg_len, &m);
-       if (error)
+       if (error) {
                return error;
+       }
 
        /*
         * Build request message for PMAPPROC_CALLIT.
@@ -471,17 +494,18 @@ bp_whoami(bpsin, my_ip, gw_ip)
        call->call_ia.atype = htonl(1);
        p = (u_char*)my_ip;
        lp = call->call_ia.addr;
-       *lp++ = htonl(*p);      p++;
-       *lp++ = htonl(*p);      p++;
-       *lp++ = htonl(*p);      p++;
-       *lp++ = htonl(*p);      p++;
+       *lp++ = htonl(*p); p++;
+       *lp++ = htonl(*p); p++;
+       *lp++ = htonl(*p); p++;
+       *lp++ = htonl(*p); p++;
 
        /* RPC: portmap/callit */
        bpsin->sin_port = htons(PMAPPORT);
 
        error = krpc_call(bpsin, SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT, &m, &sin);
-       if (error)
+       if (error) {
                return error;
+       }
 
        /*
         * Parse result message.
@@ -490,54 +514,67 @@ bp_whoami(bpsin, my_ip, gw_ip)
        lp = mbuf_data(m);
 
        /* bootparam server port (also grab from address). */
-       if (msg_len < (int)sizeof(*lp))
+       if (msg_len < sizeof(*lp)) {
                goto bad;
+       }
        msg_len -= sizeof(*lp);
        bpsin->sin_port = htons((short)ntohl(*lp++));
        bpsin->sin_addr.s_addr = sin.sin_addr.s_addr;
 
        /* length of encapsulated results */
-       if (msg_len < (ntohl(*lp) + (int)sizeof(*lp)))
+       if (os_add_overflow((size_t) ntohl(*lp), sizeof(*lp), &encapsulated_size)
+           || msg_len < encapsulated_size) {
                goto bad;
+       }
        msg_len = ntohl(*lp++);
-       p = (char*)lp;
+       p = (u_char*)lp;
 
        /* client name */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str)) {
                goto bad;
+       }
        str = (struct rpc_string *)p;
        cn_len = ntohl(str->len);
-       if (msg_len < cn_len)
+       if ((msg_len - 4) < cn_len) {
                goto bad;
-       if (cn_len >= MAXHOSTNAMELEN)
+       }
+       if (cn_len >= MAXHOSTNAMELEN) {
                goto bad;
+       }
+       lck_mtx_lock(&hostname_lock);
        bcopy(str->data, hostname, cn_len);
        hostname[cn_len] = '\0';
-       hostnamelen = cn_len;
+       lck_mtx_unlock(&hostname_lock);
        p += RPC_STR_SIZE(cn_len);
        msg_len -= RPC_STR_SIZE(cn_len);
 
        /* domain name */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str)) {
                goto bad;
+       }
        str = (struct rpc_string *)p;
        dn_len = ntohl(str->len);
-       if (msg_len < dn_len)
+       if ((msg_len - 4) < dn_len) {
                goto bad;
-       if (dn_len >= MAXHOSTNAMELEN)
+       }
+       if (dn_len >= MAXHOSTNAMELEN) {
                goto bad;
+       }
+       lck_mtx_lock(&domainname_lock);
        bcopy(str->data, domainname, dn_len);
        domainname[dn_len] = '\0';
-       domainnamelen = dn_len;
+       lck_mtx_unlock(&domainname_lock);
        p += RPC_STR_SIZE(dn_len);
        msg_len -= RPC_STR_SIZE(dn_len);
 
        /* gateway address */
-       if (msg_len < (int)sizeof(*bia))
+       if (msg_len < sizeof(*bia)) {
                goto bad;
+       }
        bia = (struct bp_inaddr *)p;
-       if (bia->atype != htonl(1))
+       if (bia->atype != htonl(1)) {
                goto bad;
+       }
        p = (u_char*)gw_ip;
        *p++ = ntohl(bia->addr[0]);
        *p++ = ntohl(bia->addr[1]);
@@ -551,7 +588,7 @@ bad:
 
 out:
        mbuf_freem(m);
-       return(error);
+       return error;
 }
 
 
@@ -563,32 +600,34 @@ out:
  *     server pathname
  */
 static int
-bp_getfile(bpsin, key, md_sin, serv_name, pathname)
-       struct sockaddr_in *bpsin;
-       const char *key;
-       struct sockaddr_in *md_sin;
-       char *serv_name;
-       char *pathname;
+bp_getfile(struct sockaddr_in *bpsin,
+    const char *key,
+    struct sockaddr_in *md_sin,
+    char *serv_name,
+    char *pathname)
 {
        struct rpc_string *str;
        mbuf_t m;
        struct bp_inaddr *bia;
        struct sockaddr_in *sin;
        u_char *p, *q;
-       int error, msg_len;
-       int cn_len, key_len, sn_len, path_len;
+       int error;
+       size_t msg_len, cn_len, key_len, sn_len, path_len;
 
        /*
         * Get message buffer of sufficient size.
         */
-       cn_len = hostnamelen;
+       lck_mtx_lock(&hostname_lock);
+       cn_len = strlen(hostname);
+       lck_mtx_unlock(&hostname_lock);
        key_len = strlen(key);
        msg_len = 0;
        msg_len += RPC_STR_SIZE(cn_len);
        msg_len += RPC_STR_SIZE(key_len);
        error = mbuf_get_with_len(msg_len, &m);
-       if (error)
+       if (error) {
                return error;
+       }
 
        /*
         * Build request message.
@@ -598,7 +637,9 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        /* client name (hostname) */
        str = (struct rpc_string *)p;
        str->len = htonl(cn_len);
+       lck_mtx_lock(&hostname_lock);
        bcopy(hostname, str->data, cn_len);
+       lck_mtx_unlock(&hostname_lock);
        p += RPC_STR_SIZE(cn_len);
        /* key name (root or swap) */
        str = (struct rpc_string *)p;
@@ -607,9 +648,10 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
 
        /* RPC: bootparam/getfile */
        error = krpc_call(bpsin, SOCK_DGRAM, BOOTPARAM_PROG, BOOTPARAM_VERS,
-                       BOOTPARAM_GETFILE, &m, NULL);
-       if (error)
+           BOOTPARAM_GETFILE, &m, NULL);
+       if (error) {
                return error;
+       }
 
        /*
         * Parse result message.
@@ -618,25 +660,30 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        msg_len = mbuf_len(m);
 
        /* server name */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str)) {
                goto bad;
+       }
        str = (struct rpc_string *)p;
        sn_len = ntohl(str->len);
-       if (msg_len < sn_len)
+       if ((msg_len - 4) < sn_len) {
                goto bad;
-       if (sn_len >= MNAMELEN)
+       }
+       if (sn_len >= MAXHOSTNAMELEN) {
                goto bad;
+       }
        bcopy(str->data, serv_name, sn_len);
        serv_name[sn_len] = '\0';
        p += RPC_STR_SIZE(sn_len);
        msg_len -= RPC_STR_SIZE(sn_len);
 
        /* server IP address (mountd) */
-       if (msg_len < (int)sizeof(*bia))
+       if (msg_len < sizeof(*bia)) {
                goto bad;
+       }
        bia = (struct bp_inaddr *)p;
-       if (bia->atype != htonl(1))
+       if (bia->atype != htonl(1)) {
                goto bad;
+       }
        sin = md_sin;
        bzero((caddr_t)sin, sizeof(*sin));
        sin->sin_len = sizeof(*sin);
@@ -650,14 +697,17 @@ bp_getfile(bpsin, key, md_sin, serv_name, pathname)
        msg_len -= sizeof(*bia);
 
        /* server pathname */
-       if (msg_len < (int)sizeof(*str))
+       if (msg_len < sizeof(*str)) {
                goto bad;
+       }
        str = (struct rpc_string *)p;
        path_len = ntohl(str->len);
-       if (msg_len < path_len)
+       if ((msg_len - 4) < path_len) {
                goto bad;
-       if (path_len >= MAXPATHLEN)
+       }
+       if (path_len >= MAXPATHLEN) {
                goto bad;
+       }
        bcopy(str->data, pathname, path_len);
        pathname[path_len] = '\0';
        goto out;
@@ -668,7 +718,7 @@ bad:
 
 out:
        mbuf_freem(m);
-       return(0);
+       return 0;
 }
 
 
@@ -678,36 +728,38 @@ out:
  * Also, sets sin->sin_port to the NFS service port.
  */
 static int
-md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
-       struct sockaddr_in *mdsin;              /* mountd server address */
-       char *path;
-       int v3;
-       int sotype;
-       u_char *fhp;
-       u_long *fhlenp;
+md_mount(struct sockaddr_in *mdsin,             /* mountd server address */
+    char *path,
+    int v3,
+    int sotype,
+    u_char *fhp,
+    u_int32_t *fhlenp)
 {
        /* The RPC structures */
        struct rpc_string *str;
        struct rdata {
-               u_long  errno;
-               u_char  data[NFSX_V3FHMAX + sizeof(u_long)];
+               u_int32_t       errno;
+               u_char  data[NFSX_V3FHMAX + sizeof(u_int32_t)];
        } *rdata;
        mbuf_t m;
-       int error, mlen, slen;
+       size_t mlen;
+       int error, slen;
        int mntversion = v3 ? RPCMNT_VER3 : RPCMNT_VER1;
        int proto = (sotype == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP;
        in_port_t mntport, nfsport;
 
        /* Get port number for MOUNTD. */
        error = krpc_portmap(mdsin, RPCPROG_MNT, mntversion, proto, &mntport);
-       if (error)
+       if (error) {
                return error;
+       }
 
        /* Get port number for NFS use. */
        /* (If NFS/proto unavailable, don't bother with the mount call) */
        error = krpc_portmap(mdsin, NFS_PROG, v3 ? NFS_VER3 : NFS_VER2, proto, &nfsport);
-       if (error)
+       if (error) {
                return error;
+       }
 
        /* Set port number for MOUNTD */
        mdsin->sin_port = mntport;
@@ -716,43 +768,50 @@ md_mount(mdsin, path, v3, sotype, fhp, fhlenp)
        mlen = RPC_STR_SIZE(slen);
 
        error = mbuf_get_with_len(mlen, &m);
-       if (error)
+       if (error) {
                return error;
+       }
        str = mbuf_data(m);
        str->len = htonl(slen);
        bcopy(path, str->data, slen);
 
        /* Do RPC to mountd. */
        error = krpc_call(mdsin, sotype, RPCPROG_MNT, mntversion, RPCMNT_MOUNT, &m, NULL);
-       if (error)
-               return error;   /* message already freed */
-
+       if (error) {
+               return error;   /* message already freed */
+       }
        /*
         * the reply must be long enough to hold the errno plus either of:
         * + a v2 filehandle
         * + a v3 filehandle length + a v3 filehandle
         */
        mlen = mbuf_len(m);
-       if (mlen < (int)sizeof(u_long))
+       if (mlen < sizeof(u_int32_t)) {
                goto bad;
+       }
        rdata = mbuf_data(m);
        error = ntohl(rdata->errno);
-       if (error)
+       if (error) {
                goto out;
+       }
        if (v3) {
-               u_long fhlen;
+               u_int32_t fhlen;
                u_char *fh;
-               if (mlen < (int)sizeof(u_long)*2)
+               if (mlen < sizeof(u_int32_t) * 2) {
                        goto bad;
-               fhlen = ntohl(*(u_long*)rdata->data);
-               fh = rdata->data + sizeof(u_long);
-               if (mlen < (int)(sizeof(u_long)*2 + fhlen))
+               }
+               fhlen = ntohl(*(u_int32_t*)rdata->data);
+               fh = rdata->data + sizeof(u_int32_t);
+               if (mlen < (sizeof(u_int32_t) * 2 + fhlen)
+                   || fhlen >= (NFSX_V3FHMAX + sizeof(u_int32_t))) {
                        goto bad;
+               }
                bcopy(fh, fhp, fhlen);
                *fhlenp = fhlen;
        } else {
-               if (mlen < ((int)sizeof(u_long) + NFSX_V2FH))
+               if (mlen < (sizeof(u_int32_t) + NFSX_V2FH)) {
                        goto bad;
+               }
                bcopy(rdata->data, fhp, NFSX_V2FH);
                *fhlenp = NFSX_V2FH;
        }
@@ -770,3 +829,5 @@ out:
 }
 
 #endif /* NETHER */
+
+#endif /* CONFIG_NFS_CLIENT */