xref: /dflybsd-src/sys/vfs/nfs/nfs_mountrpc.c (revision 0e8ff41ac29f4cf41084018e133c4758a1f73f73)
1*0e8ff41aSMatthew Dillon /*
2*0e8ff41aSMatthew Dillon  * Copyright (c) 1995 Gordon Ross, Adam Glass
3*0e8ff41aSMatthew Dillon  * Copyright (c) 1992 Regents of the University of California.
4*0e8ff41aSMatthew Dillon  * All rights reserved.
5*0e8ff41aSMatthew Dillon  *
6*0e8ff41aSMatthew Dillon  * This software was developed by the Computer Systems Engineering group
7*0e8ff41aSMatthew Dillon  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8*0e8ff41aSMatthew Dillon  * contributed to Berkeley.
9*0e8ff41aSMatthew Dillon  *
10*0e8ff41aSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
11*0e8ff41aSMatthew Dillon  * modification, are permitted provided that the following conditions
12*0e8ff41aSMatthew Dillon  * are met:
13*0e8ff41aSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
14*0e8ff41aSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
15*0e8ff41aSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
16*0e8ff41aSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
17*0e8ff41aSMatthew Dillon  *    documentation and/or other materials provided with the distribution.
18*0e8ff41aSMatthew Dillon  * 3. All advertising materials mentioning features or use of this software
19*0e8ff41aSMatthew Dillon  *    must display the following acknowledgement:
20*0e8ff41aSMatthew Dillon  *	This product includes software developed by the University of
21*0e8ff41aSMatthew Dillon  *	California, Lawrence Berkeley Laboratory and its contributors.
22*0e8ff41aSMatthew Dillon  * 4. Neither the name of the University nor the names of its contributors
23*0e8ff41aSMatthew Dillon  *    may be used to endorse or promote products derived from this software
24*0e8ff41aSMatthew Dillon  *    without specific prior written permission.
25*0e8ff41aSMatthew Dillon  *
26*0e8ff41aSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27*0e8ff41aSMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28*0e8ff41aSMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29*0e8ff41aSMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30*0e8ff41aSMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31*0e8ff41aSMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32*0e8ff41aSMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33*0e8ff41aSMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34*0e8ff41aSMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35*0e8ff41aSMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36*0e8ff41aSMatthew Dillon  * SUCH DAMAGE.
37*0e8ff41aSMatthew Dillon  *
38*0e8ff41aSMatthew Dillon  * nfs/krpc_subr.c
39*0e8ff41aSMatthew Dillon  * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
40*0e8ff41aSMatthew Dillon  * $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.9 2003/04/24 16:51:08 ambrisko Exp $
41*0e8ff41aSMatthew Dillon  * $DragonFly: src/sys/vfs/nfs/nfs_mountrpc.c,v 1.1 2005/09/04 01:29:00 dillon Exp $
42*0e8ff41aSMatthew Dillon  */
43*0e8ff41aSMatthew Dillon /*
44*0e8ff41aSMatthew Dillon  * Procedures used by NFS_ROOT and BOOTP to do an NFS mount rpc to obtain
45*0e8ff41aSMatthew Dillon  * the nfs root file handle for a NFS-based root mount point.  This module
46*0e8ff41aSMatthew Dillon  * is not used by normal operating code because the 'mount' command has a
47*0e8ff41aSMatthew Dillon  * far more sophisticated implementation.
48*0e8ff41aSMatthew Dillon  */
49*0e8ff41aSMatthew Dillon #include "opt_bootp.h"
50*0e8ff41aSMatthew Dillon #include "opt_nfsroot.h"
51*0e8ff41aSMatthew Dillon 
52*0e8ff41aSMatthew Dillon #if defined(BOOTP) || defined(NFS_ROOT)
53*0e8ff41aSMatthew Dillon 
54*0e8ff41aSMatthew Dillon #include <sys/param.h>
55*0e8ff41aSMatthew Dillon #include <sys/systm.h>
56*0e8ff41aSMatthew Dillon #include <sys/kernel.h>
57*0e8ff41aSMatthew Dillon #include <sys/sockio.h>
58*0e8ff41aSMatthew Dillon #include <sys/proc.h>
59*0e8ff41aSMatthew Dillon #include <sys/malloc.h>
60*0e8ff41aSMatthew Dillon #include <sys/mount.h>
61*0e8ff41aSMatthew Dillon #include <sys/mbuf.h>
62*0e8ff41aSMatthew Dillon #include <sys/socket.h>
63*0e8ff41aSMatthew Dillon #include <sys/socketvar.h>
64*0e8ff41aSMatthew Dillon #include <sys/sysctl.h>
65*0e8ff41aSMatthew Dillon #include <sys/uio.h>
66*0e8ff41aSMatthew Dillon 
67*0e8ff41aSMatthew Dillon #include <net/if.h>
68*0e8ff41aSMatthew Dillon #include <net/route.h>
69*0e8ff41aSMatthew Dillon 
70*0e8ff41aSMatthew Dillon #include <netinet/in.h>
71*0e8ff41aSMatthew Dillon #include <net/if_types.h>
72*0e8ff41aSMatthew Dillon #include <net/if_dl.h>
73*0e8ff41aSMatthew Dillon 
74*0e8ff41aSMatthew Dillon #include "rpcv2.h"
75*0e8ff41aSMatthew Dillon #include "nfsproto.h"
76*0e8ff41aSMatthew Dillon #include "nfs.h"
77*0e8ff41aSMatthew Dillon #include "nfsdiskless.h"
78*0e8ff41aSMatthew Dillon #include "krpc.h"
79*0e8ff41aSMatthew Dillon #include "xdr_subs.h"
80*0e8ff41aSMatthew Dillon #include "nfsmountrpc.h"
81*0e8ff41aSMatthew Dillon 
82*0e8ff41aSMatthew Dillon /*
83*0e8ff41aSMatthew Dillon  * What is the longest we will wait before re-sending a request?
84*0e8ff41aSMatthew Dillon  * Note this is also the frequency of "RPC timeout" messages.
85*0e8ff41aSMatthew Dillon  * The re-send loop count sup linearly to this maximum, so the
86*0e8ff41aSMatthew Dillon  * first complaint will happen after (1+2+3+4+5)=15 seconds.
87*0e8ff41aSMatthew Dillon  */
88*0e8ff41aSMatthew Dillon 
89*0e8ff41aSMatthew Dillon extern struct nfsv3_diskless nfsv3_diskless;
90*0e8ff41aSMatthew Dillon 
91*0e8ff41aSMatthew Dillon static int getdec(char **ptr);
92*0e8ff41aSMatthew Dillon static char *substr(char *a,char *b);
93*0e8ff41aSMatthew Dillon static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
94*0e8ff41aSMatthew Dillon static int xdr_int_decode(struct mbuf **ptr, int *iptr);
95*0e8ff41aSMatthew Dillon 
96*0e8ff41aSMatthew Dillon void
97*0e8ff41aSMatthew Dillon mountopts(struct nfs_args *args, char *p)
98*0e8ff41aSMatthew Dillon {
99*0e8ff41aSMatthew Dillon 	char *tmp;
100*0e8ff41aSMatthew Dillon 
101*0e8ff41aSMatthew Dillon 	args->version = NFS_ARGSVERSION;
102*0e8ff41aSMatthew Dillon 	args->rsize = 8192;
103*0e8ff41aSMatthew Dillon 	args->wsize = 8192;
104*0e8ff41aSMatthew Dillon 	args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
105*0e8ff41aSMatthew Dillon 	args->sotype = SOCK_DGRAM;
106*0e8ff41aSMatthew Dillon 	if (p == NULL)
107*0e8ff41aSMatthew Dillon 		return;
108*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "rsize=")))
109*0e8ff41aSMatthew Dillon 		args->rsize = getdec(&tmp);
110*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "wsize=")))
111*0e8ff41aSMatthew Dillon 		args->wsize = getdec(&tmp);
112*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "intr")))
113*0e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_INT;
114*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "soft")))
115*0e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_SOFT;
116*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "noconn")))
117*0e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_NOCONN;
118*0e8ff41aSMatthew Dillon 	if ((tmp = (char *)substr(p, "tcp")))
119*0e8ff41aSMatthew Dillon 		args->sotype = SOCK_STREAM;
120*0e8ff41aSMatthew Dillon }
121*0e8ff41aSMatthew Dillon 
122*0e8ff41aSMatthew Dillon /*
123*0e8ff41aSMatthew Dillon  * RPC: mountd/mount
124*0e8ff41aSMatthew Dillon  * Given a server pathname, get an NFS file handle.
125*0e8ff41aSMatthew Dillon  * Also, sets sin->sin_port to the NFS service port.
126*0e8ff41aSMatthew Dillon  */
127*0e8ff41aSMatthew Dillon int
128*0e8ff41aSMatthew Dillon md_mount(struct sockaddr_in *mdsin,		/* mountd server address */
129*0e8ff41aSMatthew Dillon 	 char *path,
130*0e8ff41aSMatthew Dillon 	 u_char *fhp,
131*0e8ff41aSMatthew Dillon 	 int *fhsizep,
132*0e8ff41aSMatthew Dillon 	 struct nfs_args *args,
133*0e8ff41aSMatthew Dillon 	 struct thread *td)
134*0e8ff41aSMatthew Dillon {
135*0e8ff41aSMatthew Dillon 	struct mbuf *m;
136*0e8ff41aSMatthew Dillon 	int error;
137*0e8ff41aSMatthew Dillon 	int authunixok;
138*0e8ff41aSMatthew Dillon 	int authcount;
139*0e8ff41aSMatthew Dillon 	int authver;
140*0e8ff41aSMatthew Dillon 
141*0e8ff41aSMatthew Dillon #ifdef BOOTP_NFSV3
142*0e8ff41aSMatthew Dillon 	/* First try NFS v3 */
143*0e8ff41aSMatthew Dillon 	/* Get port number for MOUNTD. */
144*0e8ff41aSMatthew Dillon 	error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
145*0e8ff41aSMatthew Dillon 			     &mdsin->sin_port, td);
146*0e8ff41aSMatthew Dillon 	if (error == 0) {
147*0e8ff41aSMatthew Dillon 		m = xdr_string_encode(path, strlen(path));
148*0e8ff41aSMatthew Dillon 
149*0e8ff41aSMatthew Dillon 		/* Do RPC to mountd. */
150*0e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
151*0e8ff41aSMatthew Dillon 				  RPCMNT_MOUNT, &m, NULL, td);
152*0e8ff41aSMatthew Dillon 	}
153*0e8ff41aSMatthew Dillon 	if (error == 0) {
154*0e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_NFSV3;
155*0e8ff41aSMatthew Dillon 	} else {
156*0e8ff41aSMatthew Dillon #endif
157*0e8ff41aSMatthew Dillon 		/* Fallback to NFS v2 */
158*0e8ff41aSMatthew Dillon 
159*0e8ff41aSMatthew Dillon 		/* Get port number for MOUNTD. */
160*0e8ff41aSMatthew Dillon 		error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
161*0e8ff41aSMatthew Dillon 				     &mdsin->sin_port, td);
162*0e8ff41aSMatthew Dillon 		if (error != 0)
163*0e8ff41aSMatthew Dillon 			return error;
164*0e8ff41aSMatthew Dillon 
165*0e8ff41aSMatthew Dillon 		m = xdr_string_encode(path, strlen(path));
166*0e8ff41aSMatthew Dillon 
167*0e8ff41aSMatthew Dillon 		/* Do RPC to mountd. */
168*0e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
169*0e8ff41aSMatthew Dillon 				  RPCMNT_MOUNT, &m, NULL, td);
170*0e8ff41aSMatthew Dillon 		if (error != 0)
171*0e8ff41aSMatthew Dillon 			return error;	/* message already freed */
172*0e8ff41aSMatthew Dillon 
173*0e8ff41aSMatthew Dillon #ifdef BOOTP_NFSV3
174*0e8ff41aSMatthew Dillon 	}
175*0e8ff41aSMatthew Dillon #endif
176*0e8ff41aSMatthew Dillon 
177*0e8ff41aSMatthew Dillon 	if (xdr_int_decode(&m, &error) != 0 || error != 0)
178*0e8ff41aSMatthew Dillon 		goto bad;
179*0e8ff41aSMatthew Dillon 
180*0e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
181*0e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, fhsizep) != 0 ||
182*0e8ff41aSMatthew Dillon 		    *fhsizep > NFSX_V3FHMAX ||
183*0e8ff41aSMatthew Dillon 		    *fhsizep <= 0)
184*0e8ff41aSMatthew Dillon 			goto bad;
185*0e8ff41aSMatthew Dillon 	} else
186*0e8ff41aSMatthew Dillon 		*fhsizep = NFSX_V2FH;
187*0e8ff41aSMatthew Dillon 
188*0e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
189*0e8ff41aSMatthew Dillon 		goto bad;
190*0e8ff41aSMatthew Dillon 
191*0e8ff41aSMatthew Dillon 	if (args->flags & NFSMNT_NFSV3) {
192*0e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, &authcount) != 0)
193*0e8ff41aSMatthew Dillon 			goto bad;
194*0e8ff41aSMatthew Dillon 		authunixok = 0;
195*0e8ff41aSMatthew Dillon 		if (authcount < 0 || authcount > 100)
196*0e8ff41aSMatthew Dillon 			goto bad;
197*0e8ff41aSMatthew Dillon 		while (authcount > 0) {
198*0e8ff41aSMatthew Dillon 			if (xdr_int_decode(&m, &authver) != 0)
199*0e8ff41aSMatthew Dillon 				goto bad;
200*0e8ff41aSMatthew Dillon 			if (authver == RPCAUTH_UNIX)
201*0e8ff41aSMatthew Dillon 				authunixok = 1;
202*0e8ff41aSMatthew Dillon 			authcount--;
203*0e8ff41aSMatthew Dillon 		}
204*0e8ff41aSMatthew Dillon 		if (authunixok == 0)
205*0e8ff41aSMatthew Dillon 			goto bad;
206*0e8ff41aSMatthew Dillon 	}
207*0e8ff41aSMatthew Dillon 
208*0e8ff41aSMatthew Dillon 	/* Set port number for NFS use. */
209*0e8ff41aSMatthew Dillon 	error = krpc_portmap(mdsin, NFS_PROG,
210*0e8ff41aSMatthew Dillon 			     (args->flags &
211*0e8ff41aSMatthew Dillon 			      NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
212*0e8ff41aSMatthew Dillon 			     &mdsin->sin_port, td);
213*0e8ff41aSMatthew Dillon 
214*0e8ff41aSMatthew Dillon 	goto out;
215*0e8ff41aSMatthew Dillon 
216*0e8ff41aSMatthew Dillon bad:
217*0e8ff41aSMatthew Dillon 	error = EBADRPC;
218*0e8ff41aSMatthew Dillon 
219*0e8ff41aSMatthew Dillon out:
220*0e8ff41aSMatthew Dillon 	m_freem(m);
221*0e8ff41aSMatthew Dillon 	return error;
222*0e8ff41aSMatthew Dillon }
223*0e8ff41aSMatthew Dillon 
224*0e8ff41aSMatthew Dillon int
225*0e8ff41aSMatthew Dillon md_lookup_swap(struct sockaddr_in *mdsin,	/* mountd server address */
226*0e8ff41aSMatthew Dillon 	       char *path,
227*0e8ff41aSMatthew Dillon 	       u_char *fhp,
228*0e8ff41aSMatthew Dillon 	       int *fhsizep,
229*0e8ff41aSMatthew Dillon 	       struct nfs_args *args,
230*0e8ff41aSMatthew Dillon 	       struct thread *td)
231*0e8ff41aSMatthew Dillon {
232*0e8ff41aSMatthew Dillon 	struct mbuf *m;
233*0e8ff41aSMatthew Dillon 	int error;
234*0e8ff41aSMatthew Dillon 	int size = -1;
235*0e8ff41aSMatthew Dillon 	int attribs_present;
236*0e8ff41aSMatthew Dillon 	int status;
237*0e8ff41aSMatthew Dillon 	union {
238*0e8ff41aSMatthew Dillon 		u_int32_t v2[17];
239*0e8ff41aSMatthew Dillon 		u_int32_t v3[21];
240*0e8ff41aSMatthew Dillon 	} fattribs;
241*0e8ff41aSMatthew Dillon 
242*0e8ff41aSMatthew Dillon 	m = m_get(MB_WAIT,MT_DATA);
243*0e8ff41aSMatthew Dillon 	if (m == NULL)
244*0e8ff41aSMatthew Dillon 	  	return ENOBUFS;
245*0e8ff41aSMatthew Dillon 
246*0e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
247*0e8ff41aSMatthew Dillon 		*mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
248*0e8ff41aSMatthew Dillon 		bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
249*0e8ff41aSMatthew Dillon 		m->m_len = *fhsizep + sizeof(u_int32_t);
250*0e8ff41aSMatthew Dillon 	} else {
251*0e8ff41aSMatthew Dillon 		bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
252*0e8ff41aSMatthew Dillon 		m->m_len = NFSX_V2FH;
253*0e8ff41aSMatthew Dillon 	}
254*0e8ff41aSMatthew Dillon 
255*0e8ff41aSMatthew Dillon 	m->m_next = xdr_string_encode(path, strlen(path));
256*0e8ff41aSMatthew Dillon 	if (m->m_next == NULL) {
257*0e8ff41aSMatthew Dillon 		error = ENOBUFS;
258*0e8ff41aSMatthew Dillon 		goto out;
259*0e8ff41aSMatthew Dillon 	}
260*0e8ff41aSMatthew Dillon 
261*0e8ff41aSMatthew Dillon 	/* Do RPC to nfsd. */
262*0e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0)
263*0e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
264*0e8ff41aSMatthew Dillon 				  NFSPROC_LOOKUP, &m, NULL, td);
265*0e8ff41aSMatthew Dillon 	else
266*0e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
267*0e8ff41aSMatthew Dillon 				  NFSV2PROC_LOOKUP, &m, NULL, td);
268*0e8ff41aSMatthew Dillon 	if (error != 0)
269*0e8ff41aSMatthew Dillon 		return error;	/* message already freed */
270*0e8ff41aSMatthew Dillon 
271*0e8ff41aSMatthew Dillon 	if (xdr_int_decode(&m, &status) != 0)
272*0e8ff41aSMatthew Dillon 		goto bad;
273*0e8ff41aSMatthew Dillon 	if (status != 0) {
274*0e8ff41aSMatthew Dillon 		error = ENOENT;
275*0e8ff41aSMatthew Dillon 		goto out;
276*0e8ff41aSMatthew Dillon 	}
277*0e8ff41aSMatthew Dillon 
278*0e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
279*0e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, fhsizep) != 0 ||
280*0e8ff41aSMatthew Dillon 		    *fhsizep > NFSX_V3FHMAX ||
281*0e8ff41aSMatthew Dillon 		    *fhsizep <= 0)
282*0e8ff41aSMatthew Dillon 			goto bad;
283*0e8ff41aSMatthew Dillon 	} else
284*0e8ff41aSMatthew Dillon 		*fhsizep = NFSX_V2FH;
285*0e8ff41aSMatthew Dillon 
286*0e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
287*0e8ff41aSMatthew Dillon 		goto bad;
288*0e8ff41aSMatthew Dillon 
289*0e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
290*0e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, &attribs_present) != 0)
291*0e8ff41aSMatthew Dillon 			goto bad;
292*0e8ff41aSMatthew Dillon 		if (attribs_present != 0) {
293*0e8ff41aSMatthew Dillon 			if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3,
294*0e8ff41aSMatthew Dillon 					      sizeof(u_int32_t) * 21) != 0)
295*0e8ff41aSMatthew Dillon 				goto bad;
296*0e8ff41aSMatthew Dillon 			size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
297*0e8ff41aSMatthew Dillon 		}
298*0e8ff41aSMatthew Dillon 	} else {
299*0e8ff41aSMatthew Dillon 		if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
300*0e8ff41aSMatthew Dillon 				      sizeof(u_int32_t) * 17) != 0)
301*0e8ff41aSMatthew Dillon 			goto bad;
302*0e8ff41aSMatthew Dillon 		size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
303*0e8ff41aSMatthew Dillon 	}
304*0e8ff41aSMatthew Dillon 
305*0e8ff41aSMatthew Dillon 	if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
306*0e8ff41aSMatthew Dillon 		nfsv3_diskless.swap_nblks = size / 1024;
307*0e8ff41aSMatthew Dillon 		printf("md_lookup_swap: Swap size is %d KB\n",
308*0e8ff41aSMatthew Dillon 		       nfsv3_diskless.swap_nblks);
309*0e8ff41aSMatthew Dillon 	}
310*0e8ff41aSMatthew Dillon 
311*0e8ff41aSMatthew Dillon 	goto out;
312*0e8ff41aSMatthew Dillon 
313*0e8ff41aSMatthew Dillon bad:
314*0e8ff41aSMatthew Dillon 	error = EBADRPC;
315*0e8ff41aSMatthew Dillon 
316*0e8ff41aSMatthew Dillon out:
317*0e8ff41aSMatthew Dillon 	m_freem(m);
318*0e8ff41aSMatthew Dillon 	return error;
319*0e8ff41aSMatthew Dillon }
320*0e8ff41aSMatthew Dillon 
321*0e8ff41aSMatthew Dillon int
322*0e8ff41aSMatthew Dillon setfs(struct sockaddr_in *addr, char *path, char *p)
323*0e8ff41aSMatthew Dillon {
324*0e8ff41aSMatthew Dillon 	unsigned int ip;
325*0e8ff41aSMatthew Dillon 	int val;
326*0e8ff41aSMatthew Dillon 
327*0e8ff41aSMatthew Dillon 	ip = 0;
328*0e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
329*0e8ff41aSMatthew Dillon 		return 0;
330*0e8ff41aSMatthew Dillon 	ip = val << 24;
331*0e8ff41aSMatthew Dillon 	if (*p != '.')
332*0e8ff41aSMatthew Dillon 		return 0;
333*0e8ff41aSMatthew Dillon 	p++;
334*0e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
335*0e8ff41aSMatthew Dillon 		return 0;
336*0e8ff41aSMatthew Dillon 	ip |= (val << 16);
337*0e8ff41aSMatthew Dillon 	if (*p != '.')
338*0e8ff41aSMatthew Dillon 		return 0;
339*0e8ff41aSMatthew Dillon 	p++;
340*0e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
341*0e8ff41aSMatthew Dillon 		return 0;
342*0e8ff41aSMatthew Dillon 	ip |= (val << 8);
343*0e8ff41aSMatthew Dillon 	if (*p != '.')
344*0e8ff41aSMatthew Dillon 		return 0;
345*0e8ff41aSMatthew Dillon 	p++;
346*0e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
347*0e8ff41aSMatthew Dillon 		return 0;
348*0e8ff41aSMatthew Dillon 	ip |= val;
349*0e8ff41aSMatthew Dillon 	if (*p != ':')
350*0e8ff41aSMatthew Dillon 		return 0;
351*0e8ff41aSMatthew Dillon 	p++;
352*0e8ff41aSMatthew Dillon 
353*0e8ff41aSMatthew Dillon 	addr->sin_addr.s_addr = htonl(ip);
354*0e8ff41aSMatthew Dillon 	addr->sin_len = sizeof(struct sockaddr_in);
355*0e8ff41aSMatthew Dillon 	addr->sin_family = AF_INET;
356*0e8ff41aSMatthew Dillon 
357*0e8ff41aSMatthew Dillon 	strncpy(path, p, MNAMELEN - 1);
358*0e8ff41aSMatthew Dillon 	return 1;
359*0e8ff41aSMatthew Dillon }
360*0e8ff41aSMatthew Dillon 
361*0e8ff41aSMatthew Dillon static int
362*0e8ff41aSMatthew Dillon getdec(char **ptr)
363*0e8ff41aSMatthew Dillon {
364*0e8ff41aSMatthew Dillon 	char *p;
365*0e8ff41aSMatthew Dillon 	int ret;
366*0e8ff41aSMatthew Dillon 
367*0e8ff41aSMatthew Dillon 	p = *ptr;
368*0e8ff41aSMatthew Dillon 	ret = 0;
369*0e8ff41aSMatthew Dillon 	if ((*p < '0') || (*p > '9'))
370*0e8ff41aSMatthew Dillon 		return -1;
371*0e8ff41aSMatthew Dillon 	while ((*p >= '0') && (*p <= '9')) {
372*0e8ff41aSMatthew Dillon 		ret = ret * 10 + (*p - '0');
373*0e8ff41aSMatthew Dillon 		p++;
374*0e8ff41aSMatthew Dillon 	}
375*0e8ff41aSMatthew Dillon 	*ptr = p;
376*0e8ff41aSMatthew Dillon 	return ret;
377*0e8ff41aSMatthew Dillon }
378*0e8ff41aSMatthew Dillon 
379*0e8ff41aSMatthew Dillon static char *
380*0e8ff41aSMatthew Dillon substr(char *a, char *b)
381*0e8ff41aSMatthew Dillon {
382*0e8ff41aSMatthew Dillon 	char *loc1;
383*0e8ff41aSMatthew Dillon 	char *loc2;
384*0e8ff41aSMatthew Dillon 
385*0e8ff41aSMatthew Dillon         while (*a != '\0') {
386*0e8ff41aSMatthew Dillon                 loc1 = a;
387*0e8ff41aSMatthew Dillon                 loc2 = b;
388*0e8ff41aSMatthew Dillon                 while (*loc1 == *loc2++) {
389*0e8ff41aSMatthew Dillon                         if (*loc1 == '\0')
390*0e8ff41aSMatthew Dillon 				return 0;
391*0e8ff41aSMatthew Dillon                         loc1++;
392*0e8ff41aSMatthew Dillon                         if (*loc2 == '\0')
393*0e8ff41aSMatthew Dillon 				return loc1;
394*0e8ff41aSMatthew Dillon                 }
395*0e8ff41aSMatthew Dillon 		a++;
396*0e8ff41aSMatthew Dillon         }
397*0e8ff41aSMatthew Dillon         return 0;
398*0e8ff41aSMatthew Dillon }
399*0e8ff41aSMatthew Dillon 
400*0e8ff41aSMatthew Dillon static int
401*0e8ff41aSMatthew Dillon xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
402*0e8ff41aSMatthew Dillon {
403*0e8ff41aSMatthew Dillon 	struct mbuf *m;
404*0e8ff41aSMatthew Dillon 	int alignedlen;
405*0e8ff41aSMatthew Dillon 
406*0e8ff41aSMatthew Dillon 	m = *mptr;
407*0e8ff41aSMatthew Dillon 	alignedlen = ( len + 3 ) & ~3;
408*0e8ff41aSMatthew Dillon 
409*0e8ff41aSMatthew Dillon 	if (m->m_len < alignedlen) {
410*0e8ff41aSMatthew Dillon 		m = m_pullup(m, alignedlen);
411*0e8ff41aSMatthew Dillon 		if (m == NULL) {
412*0e8ff41aSMatthew Dillon 			*mptr = NULL;
413*0e8ff41aSMatthew Dillon 			return EBADRPC;
414*0e8ff41aSMatthew Dillon 		}
415*0e8ff41aSMatthew Dillon 	}
416*0e8ff41aSMatthew Dillon 	bcopy(mtod(m, u_char *), buf, len);
417*0e8ff41aSMatthew Dillon 	m_adj(m, alignedlen);
418*0e8ff41aSMatthew Dillon 	*mptr = m;
419*0e8ff41aSMatthew Dillon 	return 0;
420*0e8ff41aSMatthew Dillon }
421*0e8ff41aSMatthew Dillon 
422*0e8ff41aSMatthew Dillon static int
423*0e8ff41aSMatthew Dillon xdr_int_decode(struct mbuf **mptr, int *iptr)
424*0e8ff41aSMatthew Dillon {
425*0e8ff41aSMatthew Dillon 	u_int32_t i;
426*0e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
427*0e8ff41aSMatthew Dillon 		return EBADRPC;
428*0e8ff41aSMatthew Dillon 	*iptr = fxdr_unsigned(u_int32_t, i);
429*0e8ff41aSMatthew Dillon 	return 0;
430*0e8ff41aSMatthew Dillon }
431*0e8ff41aSMatthew Dillon 
432*0e8ff41aSMatthew Dillon #endif	/* BOOTP && NFS_ROOT */
433*0e8ff41aSMatthew Dillon 
434