2 * Copyright (c) 1995 Gordon Ross, Adam Glass
3 * Copyright (c) 1992 Regents of the University of California.
6 * This software was developed by the Computer Systems Engineering group
7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8 * contributed to Berkeley.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Lawrence Berkeley Laboratory and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
40 * $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.9 2003/04/24 16:51:08 ambrisko Exp $
41 * $DragonFly: src/sys/vfs/nfs/nfs_mountrpc.c,v 1.2 2006/12/23 00:41:29 swildner Exp $
44 * Procedures used by NFS_ROOT and BOOTP to do an NFS mount rpc to obtain
45 * the nfs root file handle for a NFS-based root mount point. This module
46 * is not used by normal operating code because the 'mount' command has a
47 * far more sophisticated implementation.
49 #include "opt_bootp.h"
50 #include "opt_nfsroot.h"
52 #if defined(BOOTP) || defined(NFS_ROOT)
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/sockio.h>
59 #include <sys/malloc.h>
60 #include <sys/mount.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/sysctl.h>
68 #include <net/route.h>
70 #include <netinet/in.h>
71 #include <net/if_types.h>
72 #include <net/if_dl.h>
77 #include "nfsdiskless.h"
80 #include "nfsmountrpc.h"
83 * What is the longest we will wait before re-sending a request?
84 * Note this is also the frequency of "RPC timeout" messages.
85 * The re-send loop count sup linearly to this maximum, so the
86 * first complaint will happen after (1+2+3+4+5)=15 seconds.
89 static int getdec(char **ptr
);
90 static char *substr(char *a
,char *b
);
91 static int xdr_opaque_decode(struct mbuf
**ptr
, u_char
*buf
, int len
);
92 static int xdr_int_decode(struct mbuf
**ptr
, int *iptr
);
95 mountopts(struct nfs_args
*args
, char *p
)
99 args
->version
= NFS_ARGSVERSION
;
102 args
->flags
= NFSMNT_RSIZE
| NFSMNT_WSIZE
| NFSMNT_RESVPORT
;
103 args
->sotype
= SOCK_DGRAM
;
106 if ((tmp
= (char *)substr(p
, "rsize=")))
107 args
->rsize
= getdec(&tmp
);
108 if ((tmp
= (char *)substr(p
, "wsize=")))
109 args
->wsize
= getdec(&tmp
);
110 if ((tmp
= (char *)substr(p
, "intr")))
111 args
->flags
|= NFSMNT_INT
;
112 if ((tmp
= (char *)substr(p
, "soft")))
113 args
->flags
|= NFSMNT_SOFT
;
114 if ((tmp
= (char *)substr(p
, "noconn")))
115 args
->flags
|= NFSMNT_NOCONN
;
116 if ((tmp
= (char *)substr(p
, "tcp")))
117 args
->sotype
= SOCK_STREAM
;
122 * Given a server pathname, get an NFS file handle.
123 * Also, sets sin->sin_port to the NFS service port.
126 md_mount(struct sockaddr_in
*mdsin
, /* mountd server address */
130 struct nfs_args
*args
,
140 /* First try NFS v3 */
141 /* Get port number for MOUNTD. */
142 error
= krpc_portmap(mdsin
, RPCPROG_MNT
, RPCMNT_VER3
,
143 &mdsin
->sin_port
, td
);
145 m
= xdr_string_encode(path
, strlen(path
));
147 /* Do RPC to mountd. */
148 error
= krpc_call(mdsin
, RPCPROG_MNT
, RPCMNT_VER3
,
149 RPCMNT_MOUNT
, &m
, NULL
, td
);
152 args
->flags
|= NFSMNT_NFSV3
;
155 /* Fallback to NFS v2 */
157 /* Get port number for MOUNTD. */
158 error
= krpc_portmap(mdsin
, RPCPROG_MNT
, RPCMNT_VER1
,
159 &mdsin
->sin_port
, td
);
163 m
= xdr_string_encode(path
, strlen(path
));
165 /* Do RPC to mountd. */
166 error
= krpc_call(mdsin
, RPCPROG_MNT
, RPCMNT_VER1
,
167 RPCMNT_MOUNT
, &m
, NULL
, td
);
169 return error
; /* message already freed */
175 if (xdr_int_decode(&m
, &error
) != 0 || error
!= 0)
178 if ((args
->flags
& NFSMNT_NFSV3
) != 0) {
179 if (xdr_int_decode(&m
, fhsizep
) != 0 ||
180 *fhsizep
> NFSX_V3FHMAX
||
184 *fhsizep
= NFSX_V2FH
;
186 if (xdr_opaque_decode(&m
, fhp
, *fhsizep
) != 0)
189 if (args
->flags
& NFSMNT_NFSV3
) {
190 if (xdr_int_decode(&m
, &authcount
) != 0)
193 if (authcount
< 0 || authcount
> 100)
195 while (authcount
> 0) {
196 if (xdr_int_decode(&m
, &authver
) != 0)
198 if (authver
== RPCAUTH_UNIX
)
206 /* Set port number for NFS use. */
207 error
= krpc_portmap(mdsin
, NFS_PROG
,
209 NFSMNT_NFSV3
) ? NFS_VER3
: NFS_VER2
,
210 &mdsin
->sin_port
, td
);
223 md_lookup_swap(struct sockaddr_in
*mdsin
, /* mountd server address */
227 struct nfs_args
*args
,
240 m
= m_get(MB_WAIT
,MT_DATA
);
244 if ((args
->flags
& NFSMNT_NFSV3
) != 0) {
245 *mtod(m
, u_int32_t
*) = txdr_unsigned(*fhsizep
);
246 bcopy(fhp
, mtod(m
, u_char
*) + sizeof(u_int32_t
), *fhsizep
);
247 m
->m_len
= *fhsizep
+ sizeof(u_int32_t
);
249 bcopy(fhp
, mtod(m
, u_char
*), NFSX_V2FH
);
250 m
->m_len
= NFSX_V2FH
;
253 m
->m_next
= xdr_string_encode(path
, strlen(path
));
254 if (m
->m_next
== NULL
) {
259 /* Do RPC to nfsd. */
260 if ((args
->flags
& NFSMNT_NFSV3
) != 0)
261 error
= krpc_call(mdsin
, NFS_PROG
, NFS_VER3
,
262 NFSPROC_LOOKUP
, &m
, NULL
, td
);
264 error
= krpc_call(mdsin
, NFS_PROG
, NFS_VER2
,
265 NFSV2PROC_LOOKUP
, &m
, NULL
, td
);
267 return error
; /* message already freed */
269 if (xdr_int_decode(&m
, &status
) != 0)
276 if ((args
->flags
& NFSMNT_NFSV3
) != 0) {
277 if (xdr_int_decode(&m
, fhsizep
) != 0 ||
278 *fhsizep
> NFSX_V3FHMAX
||
282 *fhsizep
= NFSX_V2FH
;
284 if (xdr_opaque_decode(&m
, fhp
, *fhsizep
) != 0)
287 if ((args
->flags
& NFSMNT_NFSV3
) != 0) {
288 if (xdr_int_decode(&m
, &attribs_present
) != 0)
290 if (attribs_present
!= 0) {
291 if (xdr_opaque_decode(&m
, (u_char
*) &fattribs
.v3
,
292 sizeof(u_int32_t
) * 21) != 0)
294 size
= fxdr_unsigned(u_int32_t
, fattribs
.v3
[6]);
297 if (xdr_opaque_decode(&m
,(u_char
*) &fattribs
.v2
,
298 sizeof(u_int32_t
) * 17) != 0)
300 size
= fxdr_unsigned(u_int32_t
, fattribs
.v2
[5]);
303 if (nfsv3_diskless
.swap_nblks
== 0 && size
!= -1) {
304 nfsv3_diskless
.swap_nblks
= size
/ 1024;
305 kprintf("md_lookup_swap: Swap size is %d KB\n",
306 nfsv3_diskless
.swap_nblks
);
320 setfs(struct sockaddr_in
*addr
, char *path
, char *p
)
326 if (((val
= getdec(&p
)) < 0) || (val
> 255))
332 if (((val
= getdec(&p
)) < 0) || (val
> 255))
338 if (((val
= getdec(&p
)) < 0) || (val
> 255))
344 if (((val
= getdec(&p
)) < 0) || (val
> 255))
351 addr
->sin_addr
.s_addr
= htonl(ip
);
352 addr
->sin_len
= sizeof(struct sockaddr_in
);
353 addr
->sin_family
= AF_INET
;
355 strncpy(path
, p
, MNAMELEN
- 1);
367 if ((*p
< '0') || (*p
> '9'))
369 while ((*p
>= '0') && (*p
<= '9')) {
370 ret
= ret
* 10 + (*p
- '0');
378 substr(char *a
, char *b
)
386 while (*loc1
== *loc2
++) {
399 xdr_opaque_decode(struct mbuf
**mptr
, u_char
*buf
, int len
)
405 alignedlen
= ( len
+ 3 ) & ~3;
407 if (m
->m_len
< alignedlen
) {
408 m
= m_pullup(m
, alignedlen
);
414 bcopy(mtod(m
, u_char
*), buf
, len
);
415 m_adj(m
, alignedlen
);
421 xdr_int_decode(struct mbuf
**mptr
, int *iptr
)
424 if (xdr_opaque_decode(mptr
, (u_char
*) &i
, sizeof(u_int32_t
)) != 0)
426 *iptr
= fxdr_unsigned(u_int32_t
, i
);
430 #endif /* BOOTP && NFS_ROOT */