]>
git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_boot.c
2 * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995, 1997 NeXT Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1994 Adam Glass, Gordon Ross
31 * All rights reserved.
33 * This software was developed by the Computer Systems Engineering group
34 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
35 * contributed to Berkeley.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by the University of
48 * California, Lawrence Berkeley Laboratory and its contributors.
49 * 4. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * 14-March-97 Dieter Siegmund (dieter@next.com)
67 * - Use BOOTP instead of RARP to get the IP address at boot time
69 * 23-May-97 Umesh Vaishampayan (umeshv@apple.com)
70 * - Added the ability to mount "/private" separately.
72 * 30-May-97 Dieter Siegmund (dieter@next.com)
73 * - Clear out the ireq structure before using it to prevent
74 * our sending using a bogus source IP address, we should use
75 * an IP address of all zeroes
76 * - Right after BOOTP, get the correct netmask using AUTONETMASK
77 * 18-Jul-97 Dieter Siegmund (dieter@apple.com)
78 * - we can't restrict the netmask until we have a default route,
79 * removed AUTONETMASK call (ifdef'd out)
80 * 5-Aug-97 Dieter Siegmund (dieter@apple.com)
81 * - use the default route from the bpwhoami call, enabled autonetmask
83 * 19-Feb-1999 Dieter Siegmund (dieter@apple.com)
84 * - use new BOOTP routine to get the subnet mask and router
85 * and stop using SIOCAUTOADDR
86 * - don't bother mounting private separately if it's not
87 * specified or not required because they are substrings of
88 * one another ie. root=host:/A and private=host:/A/private
89 * - allow the root path to be specified in the boot variable
90 * "rp" (AKA "rootpath")
91 * 19-Jul-1999 Dieter Siegmund (dieter@apple.com)
92 * - replaced big automatic arrays with MALLOC'd data
95 #include <nfs/nfs_conf.h>
98 #include <sys/param.h>
99 #include <sys/systm.h>
100 #include <sys/kernel.h>
101 #include <sys/conf.h>
102 #include <sys/ioctl.h>
103 #include <sys/proc.h>
104 #include <sys/mount_internal.h>
105 #include <sys/kpi_mbuf.h>
107 #include <sys/malloc.h>
108 #include <sys/socket.h>
111 #include <net/if_dl.h>
112 #include <net/if_types.h>
113 #include <net/route.h>
115 #include <netinet/in.h>
116 #include <netinet/if_ether.h>
118 #include <nfs/rpcv2.h>
119 #include <nfs/nfsproto.h>
121 #include <nfs/nfsdiskless.h>
122 #include <nfs/krpc.h>
124 #include <pexpert/pexpert.h>
128 #include <libkern/libkern.h>
134 nfs_boot_init(__unused
struct nfs_diskless
*nd
)
136 panic("nfs_boot_init: no ether");
140 nfs_boot_getfh(__unused
struct nfs_diskless
*nd
, __unused
int v3
, __unused
int sotype
)
142 panic("nfs_boot_getfh: no ether");
148 * Support for NFS diskless booting, specifically getting information
149 * about where to boot from, what pathnames, etc.
151 * This implememtation uses RARP and the bootparam RPC.
152 * We are forced to implement RPC anyway (to get file handles)
153 * so we might as well take advantage of it for bootparam too.
155 * The diskless boot sequence goes as follows:
156 * (1) Use RARP to get our interface address
157 * (2) Use RPC/bootparam/whoami to get our hostname,
158 * our IP address, and the server's IP address.
159 * (3) Use RPC/bootparam/getfile to get the root path
160 * (4) Use RPC/mountd to get the root file handle
161 * (5) Use RPC/bootparam/getfile to get the swap path
162 * (6) Use RPC/mountd to get the swap file handle
164 * (This happens to be the way Sun does it too.)
168 static int bp_whoami(struct sockaddr_in
*bpsin
,
169 struct in_addr
*my_ip
, struct in_addr
*gw_ip
);
170 static int bp_getfile(struct sockaddr_in
*bpsin
, const char *key
,
171 struct sockaddr_in
*mdsin
, char *servname
, char *path
);
174 static int md_mount(struct sockaddr_in
*mdsin
, char *path
, int v3
, int sotype
,
175 u_char
*fhp
, u_int32_t
*fhlenp
);
178 static int get_file_handle(struct nfs_dlmount
*ndmntp
);
181 #define IP_FORMAT "%d.%d.%d.%d"
182 #define IP_CH(ip) ((u_char *)ip)
183 #define IP_LIST(ip) IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
185 #include <sys/netboot.h>
188 * Called with an empty nfs_diskless struct to be filled in.
191 nfs_boot_init(struct nfs_diskless
*nd
)
193 struct sockaddr_in bp_sin
;
194 boolean_t do_bpwhoami
= TRUE
;
195 boolean_t do_bpgetfile
= TRUE
;
197 struct in_addr my_ip
;
198 struct sockaddr_in
* sin_p
;
200 /* make sure mbuf constants are set up */
201 if (!nfs_mbuf_mhlen
) {
205 /* by this point, networking must already have been configured */
206 if (netboot_iaddr(&my_ip
) == FALSE
) {
207 printf("nfs_boot: networking is not initialized\n");
212 /* get the root path information */
213 nd
->nd_root
.ndm_path
= zalloc(ZV_NAMEI
);
214 nd
->nd_root
.ndm_mntfrom
= zalloc(ZV_NAMEI
);
216 sin_p
= &nd
->nd_root
.ndm_saddr
;
217 bzero((caddr_t
)sin_p
, sizeof(*sin_p
));
218 sin_p
->sin_len
= sizeof(*sin_p
);
219 sin_p
->sin_family
= AF_INET
;
220 if (netboot_rootpath(&sin_p
->sin_addr
, nd
->nd_root
.ndm_host
,
221 sizeof(nd
->nd_root
.ndm_host
),
222 nd
->nd_root
.ndm_path
, MAXPATHLEN
) == TRUE
) {
223 do_bpgetfile
= FALSE
;
226 nd
->nd_private
.ndm_saddr
.sin_addr
.s_addr
= 0;
229 struct in_addr router
;
231 * Get client name and gateway address.
232 * RPC: bootparam/whoami
233 * Use the old broadcast address for the WHOAMI
234 * call because we do not yet know our netmask.
235 * The server address returned by the WHOAMI call
236 * is used for all subsequent booptaram RPCs.
238 bzero((caddr_t
)&bp_sin
, sizeof(bp_sin
));
239 bp_sin
.sin_len
= sizeof(bp_sin
);
240 bp_sin
.sin_family
= AF_INET
;
241 bp_sin
.sin_addr
.s_addr
= INADDR_BROADCAST
;
243 error
= bp_whoami(&bp_sin
, &my_ip
, &router
);
245 printf("nfs_boot: bootparam whoami, error=%d", error
);
248 printf("nfs_boot: BOOTPARAMS server " IP_FORMAT
"\n",
249 IP_LIST(&bp_sin
.sin_addr
));
250 lck_mtx_lock(&hostname_lock
);
251 printf("nfs_boot: hostname %s\n", hostname
);
252 lck_mtx_unlock(&hostname_lock
);
255 error
= bp_getfile(&bp_sin
, "root", &nd
->nd_root
.ndm_saddr
,
256 nd
->nd_root
.ndm_host
, nd
->nd_root
.ndm_path
);
258 printf("nfs_boot: bootparam get root: %d\n", error
);
263 #if !defined(NO_MOUNT_PRIVATE)
264 if (do_bpgetfile
) { /* get private path */
265 nd
->nd_private
.ndm_path
= zalloc(ZV_NAMEI
);
266 nd
->nd_private
.ndm_mntfrom
= zalloc(ZV_NAMEI
);
267 error
= bp_getfile(&bp_sin
, "private",
268 &nd
->nd_private
.ndm_saddr
,
269 nd
->nd_private
.ndm_host
,
270 nd
->nd_private
.ndm_path
);
272 char * check_path
= NULL
;
274 check_path
= zalloc(ZV_NAMEI
);
275 snprintf(check_path
, MAXPATHLEN
, "%s/private", nd
->nd_root
.ndm_path
);
276 if ((nd
->nd_root
.ndm_saddr
.sin_addr
.s_addr
277 == nd
->nd_private
.ndm_saddr
.sin_addr
.s_addr
)
278 && (strncmp(check_path
, nd
->nd_private
.ndm_path
, MAXPATHLEN
) == 0)) {
279 /* private path is prefix of root path, don't mount */
280 nd
->nd_private
.ndm_saddr
.sin_addr
.s_addr
= 0;
282 NFS_ZFREE(ZV_NAMEI
, check_path
);
284 /* private key not defined, don't mount */
285 nd
->nd_private
.ndm_saddr
.sin_addr
.s_addr
= 0;
290 #endif /* NO_MOUNT_PRIVATE */
296 * Called with a partially initialized nfs_diskless struct
297 * with file handles to be filled in.
300 nfs_boot_getfh(struct nfs_diskless
*nd
, int v3
, int sotype
)
304 nd
->nd_root
.ndm_nfsv3
= v3
;
305 nd
->nd_root
.ndm_sotype
= sotype
;
306 error
= get_file_handle(&nd
->nd_root
);
308 printf("nfs_boot: get_file_handle(v%d) root failed, %d\n",
313 #if !defined(NO_MOUNT_PRIVATE)
314 if (nd
->nd_private
.ndm_saddr
.sin_addr
.s_addr
) {
315 /* get private file handle */
316 nd
->nd_private
.ndm_nfsv3
= v3
;
317 nd
->nd_private
.ndm_sotype
= sotype
;
318 error
= get_file_handle(&nd
->nd_private
);
320 printf("nfs_boot: get_file_handle(v%d) private failed, %d\n",
325 #endif /* NO_MOUNT_PRIVATE */
331 get_file_handle(struct nfs_dlmount
*ndmntp
)
333 char *sp
, *dp
, *endp
;
337 * Get file handle for "key" (root or swap)
338 * using RPC to mountd/mount
340 error
= md_mount(&ndmntp
->ndm_saddr
, ndmntp
->ndm_path
, ndmntp
->ndm_nfsv3
,
341 ndmntp
->ndm_sotype
, ndmntp
->ndm_fh
, &ndmntp
->ndm_fhlen
);
346 /* Construct remote path (for getmntinfo(3)) */
347 dp
= ndmntp
->ndm_mntfrom
;
348 endp
= dp
+ MAXPATHLEN
- 1;
349 for (sp
= ndmntp
->ndm_host
; *sp
&& dp
< endp
;) {
355 for (sp
= ndmntp
->ndm_path
; *sp
&& dp
< endp
;) {
364 * Get an mbuf with the given length, and
365 * initialize the pkthdr length field.
368 mbuf_get_with_len(size_t msg_len
, mbuf_t
*m
)
371 error
= mbuf_gethdr(MBUF_WAITOK
, MBUF_TYPE_DATA
, m
);
375 if (msg_len
> mbuf_maxlen(*m
)) {
376 error
= mbuf_mclget(MBUF_WAITOK
, MBUF_TYPE_DATA
, m
);
381 if (msg_len
> mbuf_maxlen(*m
)) {
382 panic("nfs_boot: msg_len > MCLBYTES");
385 mbuf_setlen(*m
, msg_len
);
386 mbuf_pkthdr_setlen(*m
, msg_len
);
392 * String representation for RPC.
395 size_t len
; /* length without null or padding */
396 u_char data
[4]; /* data (longer, of course) */
397 /* data is padded to a long-word boundary */
399 /* Compute space used given string length. */
400 #define RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3))
403 * Inet address in RPC messages
404 * (Note, really four 32-bit ints, NOT chars. Blech.)
413 * RPC: bootparam/whoami
414 * Given client IP address, get:
415 * client name (hostname)
416 * domain name (domainname)
419 * The hostname and domainname are set here for convenience.
421 * Note - bpsin is initialized to the broadcast address,
422 * and will be replaced with the bootparam server address
423 * after this call is complete. Have to use PMAP_PROC_CALL
424 * to make sure we get responses only from a servers that
425 * know about us (don't want to broadcast a getport call).
428 bp_whoami(struct sockaddr_in
*bpsin
,
429 struct in_addr
*my_ip
,
430 struct in_addr
*gw_ip
)
432 /* RPC structures for PMAPPROC_CALLIT */
437 u_int32_t call_arglen
;
438 struct bp_inaddr call_ia
;
441 struct rpc_string
*str
;
442 struct bp_inaddr
*bia
;
444 struct sockaddr_in sin
;
446 size_t msg_len
, cn_len
, dn_len
;
449 size_t encapsulated_size
;
452 * Get message buffer of sufficient size.
454 msg_len
= sizeof(*call
);
455 error
= mbuf_get_with_len(msg_len
, &m
);
461 * Build request message for PMAPPROC_CALLIT.
464 call
->call_prog
= htonl(BOOTPARAM_PROG
);
465 call
->call_vers
= htonl(BOOTPARAM_VERS
);
466 call
->call_proc
= htonl(BOOTPARAM_WHOAMI
);
467 call
->call_arglen
= htonl(sizeof(struct bp_inaddr
));
469 /* client IP address */
470 call
->call_ia
.atype
= htonl(1);
472 lp
= call
->call_ia
.addr
;
473 *lp
++ = htonl(*p
); p
++;
474 *lp
++ = htonl(*p
); p
++;
475 *lp
++ = htonl(*p
); p
++;
476 *lp
++ = htonl(*p
); p
++;
478 /* RPC: portmap/callit */
479 bpsin
->sin_port
= htons(PMAPPORT
);
481 error
= krpc_call(bpsin
, SOCK_DGRAM
, PMAPPROG
, PMAPVERS
, PMAPPROC_CALLIT
, &m
, &sin
);
487 * Parse result message.
489 msg_len
= mbuf_len(m
);
492 /* bootparam server port (also grab from address). */
493 if (msg_len
< sizeof(*lp
)) {
496 msg_len
-= sizeof(*lp
);
497 bpsin
->sin_port
= htons((short)ntohl(*lp
++));
498 bpsin
->sin_addr
.s_addr
= sin
.sin_addr
.s_addr
;
500 /* length of encapsulated results */
501 if (os_add_overflow((size_t) ntohl(*lp
), sizeof(*lp
), &encapsulated_size
)
502 || msg_len
< encapsulated_size
) {
505 msg_len
= ntohl(*lp
++);
509 if (msg_len
< sizeof(*str
)) {
512 str
= (struct rpc_string
*)p
;
513 cn_len
= ntohll(str
->len
);
514 if ((msg_len
- 4) < cn_len
) {
517 if (cn_len
>= MAXHOSTNAMELEN
) {
520 lck_mtx_lock(&hostname_lock
);
521 bcopy(str
->data
, hostname
, cn_len
);
522 hostname
[cn_len
] = '\0';
523 lck_mtx_unlock(&hostname_lock
);
524 p
+= RPC_STR_SIZE(cn_len
);
525 msg_len
-= RPC_STR_SIZE(cn_len
);
528 if (msg_len
< sizeof(*str
)) {
531 str
= (struct rpc_string
*)p
;
532 dn_len
= ntohll(str
->len
);
533 if ((msg_len
- 4) < dn_len
) {
536 if (dn_len
>= MAXHOSTNAMELEN
) {
539 lck_mtx_lock(&domainname_lock
);
540 bcopy(str
->data
, domainname
, dn_len
);
541 domainname
[dn_len
] = '\0';
542 lck_mtx_unlock(&domainname_lock
);
543 p
+= RPC_STR_SIZE(dn_len
);
544 msg_len
-= RPC_STR_SIZE(dn_len
);
546 /* gateway address */
547 if (msg_len
< sizeof(*bia
)) {
550 bia
= (struct bp_inaddr
*)p
;
551 if (bia
->atype
!= htonl(1)) {
555 *p
++ = ntohl(bia
->addr
[0]) & 0xff;
556 *p
++ = ntohl(bia
->addr
[1]) & 0xff;
557 *p
++ = ntohl(bia
->addr
[2]) & 0xff;
558 *p
++ = ntohl(bia
->addr
[3]) & 0xff;
562 printf("nfs_boot: bootparam_whoami: bad reply\n");
572 * RPC: bootparam/getfile
573 * Given client name and file "key", get:
579 bp_getfile(struct sockaddr_in
*bpsin
,
581 struct sockaddr_in
*md_sin
,
585 struct rpc_string
*str
;
587 struct bp_inaddr
*bia
;
588 struct sockaddr_in
*sin
;
591 size_t msg_len
, cn_len
, key_len
, sn_len
, path_len
;
594 * Get message buffer of sufficient size.
596 lck_mtx_lock(&hostname_lock
);
597 cn_len
= strlen(hostname
);
598 lck_mtx_unlock(&hostname_lock
);
599 key_len
= strlen(key
);
601 msg_len
+= RPC_STR_SIZE(cn_len
);
602 msg_len
+= RPC_STR_SIZE(key_len
);
603 error
= mbuf_get_with_len(msg_len
, &m
);
609 * Build request message.
613 /* client name (hostname) */
614 str
= (struct rpc_string
*)p
;
615 str
->len
= htonll(cn_len
);
616 lck_mtx_lock(&hostname_lock
);
617 bcopy(hostname
, str
->data
, cn_len
);
618 lck_mtx_unlock(&hostname_lock
);
619 p
+= RPC_STR_SIZE(cn_len
);
620 /* key name (root or swap) */
621 str
= (struct rpc_string
*)p
;
622 str
->len
= htonll(key_len
);
623 bcopy(key
, str
->data
, key_len
);
625 /* RPC: bootparam/getfile */
626 error
= krpc_call(bpsin
, SOCK_DGRAM
, BOOTPARAM_PROG
, BOOTPARAM_VERS
,
627 BOOTPARAM_GETFILE
, &m
, NULL
);
633 * Parse result message.
636 msg_len
= mbuf_len(m
);
639 if (msg_len
< sizeof(*str
)) {
642 str
= (struct rpc_string
*)p
;
643 sn_len
= ntohll(str
->len
);
644 if ((msg_len
- 4) < sn_len
) {
647 if (sn_len
>= MAXHOSTNAMELEN
) {
650 bcopy(str
->data
, serv_name
, sn_len
);
651 serv_name
[sn_len
] = '\0';
652 p
+= RPC_STR_SIZE(sn_len
);
653 msg_len
-= RPC_STR_SIZE(sn_len
);
655 /* server IP address (mountd) */
656 if (msg_len
< sizeof(*bia
)) {
659 bia
= (struct bp_inaddr
*)p
;
660 if (bia
->atype
!= htonl(1)) {
664 bzero((caddr_t
)sin
, sizeof(*sin
));
665 sin
->sin_len
= sizeof(*sin
);
666 sin
->sin_family
= AF_INET
;
667 q
= (u_char
*) &sin
->sin_addr
;
668 *q
++ = ntohl(bia
->addr
[0]) & 0xff;
669 *q
++ = ntohl(bia
->addr
[1]) & 0xff;
670 *q
++ = ntohl(bia
->addr
[2]) & 0xff;
671 *q
++ = ntohl(bia
->addr
[3]) & 0xff;
673 msg_len
-= sizeof(*bia
);
675 /* server pathname */
676 if (msg_len
< sizeof(*str
)) {
679 str
= (struct rpc_string
*)p
;
680 path_len
= ntohll(str
->len
);
681 if ((msg_len
- 4) < path_len
) {
684 if (path_len
>= MAXPATHLEN
) {
687 bcopy(str
->data
, pathname
, path_len
);
688 pathname
[path_len
] = '\0';
692 printf("nfs_boot: bootparam_getfile: bad reply\n");
703 * Given a server pathname, get an NFS file handle.
704 * Also, sets sin->sin_port to the NFS service port.
707 md_mount(struct sockaddr_in
*mdsin
, /* mountd server address */
714 /* The RPC structures */
715 struct rpc_string
*str
;
718 u_char data
[NFSX_V3FHMAX
+ sizeof(u_int32_t
)];
723 int mntversion
= v3
? RPCMNT_VER3
: RPCMNT_VER1
;
724 int proto
= (sotype
== SOCK_STREAM
) ? IPPROTO_TCP
: IPPROTO_UDP
;
725 in_port_t mntport
, nfsport
;
727 /* Get port number for MOUNTD. */
728 error
= krpc_portmap(mdsin
, RPCPROG_MNT
, mntversion
, proto
, &mntport
);
733 /* Get port number for NFS use. */
734 /* (If NFS/proto unavailable, don't bother with the mount call) */
735 error
= krpc_portmap(mdsin
, NFS_PROG
, v3
? NFS_VER3
: NFS_VER2
, proto
, &nfsport
);
740 /* Set port number for MOUNTD */
741 mdsin
->sin_port
= mntport
;
744 mlen
= RPC_STR_SIZE(slen
);
746 error
= mbuf_get_with_len(mlen
, &m
);
751 str
->len
= htonll(slen
);
752 bcopy(path
, str
->data
, slen
);
754 /* Do RPC to mountd. */
755 error
= krpc_call(mdsin
, sotype
, RPCPROG_MNT
, mntversion
, RPCMNT_MOUNT
, &m
, NULL
);
757 return error
; /* message already freed */
760 * the reply must be long enough to hold the errno plus either of:
762 * + a v3 filehandle length + a v3 filehandle
765 if (mlen
< sizeof(u_int32_t
)) {
768 rdata
= mbuf_data(m
);
769 error
= ntohl(rdata
->errno
);
776 if (mlen
< sizeof(u_int32_t
) * 2) {
779 fhlen
= ntohl(*(u_int32_t
*)rdata
->data
);
780 fh
= rdata
->data
+ sizeof(u_int32_t
);
781 if (mlen
< (sizeof(u_int32_t
) * 2 + fhlen
)
782 || fhlen
>= (NFSX_V3FHMAX
+ sizeof(u_int32_t
))) {
785 bcopy(fh
, fhp
, fhlen
);
788 if (mlen
< (sizeof(u_int32_t
) + NFSX_V2FH
)) {
791 bcopy(rdata
->data
, fhp
, NFSX_V2FH
);
795 /* Set port number for NFS use. */
796 mdsin
->sin_port
= nfsport
;
809 #endif /* CONFIG_NFS_CLIENT */