xref: /dragonfly/sys/vfs/nfs/nfs_mountrpc.c (revision b272101a)
10e8ff41aSMatthew Dillon /*
20e8ff41aSMatthew Dillon  * Copyright (c) 1995 Gordon Ross, Adam Glass
30e8ff41aSMatthew Dillon  * Copyright (c) 1992 Regents of the University of California.
40e8ff41aSMatthew Dillon  * All rights reserved.
50e8ff41aSMatthew Dillon  *
60e8ff41aSMatthew Dillon  * This software was developed by the Computer Systems Engineering group
70e8ff41aSMatthew Dillon  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
80e8ff41aSMatthew Dillon  * contributed to Berkeley.
90e8ff41aSMatthew Dillon  *
100e8ff41aSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
110e8ff41aSMatthew Dillon  * modification, are permitted provided that the following conditions
120e8ff41aSMatthew Dillon  * are met:
130e8ff41aSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
140e8ff41aSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
150e8ff41aSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
160e8ff41aSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
170e8ff41aSMatthew Dillon  *    documentation and/or other materials provided with the distribution.
180e8ff41aSMatthew Dillon  * 3. All advertising materials mentioning features or use of this software
190e8ff41aSMatthew Dillon  *    must display the following acknowledgement:
200e8ff41aSMatthew Dillon  *	This product includes software developed by the University of
210e8ff41aSMatthew Dillon  *	California, Lawrence Berkeley Laboratory and its contributors.
220e8ff41aSMatthew Dillon  * 4. Neither the name of the University nor the names of its contributors
230e8ff41aSMatthew Dillon  *    may be used to endorse or promote products derived from this software
240e8ff41aSMatthew Dillon  *    without specific prior written permission.
250e8ff41aSMatthew Dillon  *
260e8ff41aSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
270e8ff41aSMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
280e8ff41aSMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
290e8ff41aSMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
300e8ff41aSMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
310e8ff41aSMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
320e8ff41aSMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
330e8ff41aSMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
340e8ff41aSMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
350e8ff41aSMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
360e8ff41aSMatthew Dillon  * SUCH DAMAGE.
370e8ff41aSMatthew Dillon  *
380e8ff41aSMatthew Dillon  * nfs/krpc_subr.c
390e8ff41aSMatthew Dillon  * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
400e8ff41aSMatthew Dillon  * $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.9 2003/04/24 16:51:08 ambrisko Exp $
410e8ff41aSMatthew Dillon  */
420e8ff41aSMatthew Dillon /*
430e8ff41aSMatthew Dillon  * Procedures used by NFS_ROOT and BOOTP to do an NFS mount rpc to obtain
440e8ff41aSMatthew Dillon  * the nfs root file handle for a NFS-based root mount point.  This module
450e8ff41aSMatthew Dillon  * is not used by normal operating code because the 'mount' command has a
460e8ff41aSMatthew Dillon  * far more sophisticated implementation.
470e8ff41aSMatthew Dillon  */
480e8ff41aSMatthew Dillon #include "opt_bootp.h"
490e8ff41aSMatthew Dillon #include "opt_nfsroot.h"
500e8ff41aSMatthew Dillon 
510e8ff41aSMatthew Dillon #if defined(BOOTP) || defined(NFS_ROOT)
520e8ff41aSMatthew Dillon 
530e8ff41aSMatthew Dillon #include <sys/param.h>
540e8ff41aSMatthew Dillon #include <sys/systm.h>
550e8ff41aSMatthew Dillon #include <sys/kernel.h>
560e8ff41aSMatthew Dillon #include <sys/sockio.h>
570e8ff41aSMatthew Dillon #include <sys/proc.h>
580e8ff41aSMatthew Dillon #include <sys/malloc.h>
590e8ff41aSMatthew Dillon #include <sys/mount.h>
600e8ff41aSMatthew Dillon #include <sys/mbuf.h>
610e8ff41aSMatthew Dillon #include <sys/socket.h>
620e8ff41aSMatthew Dillon #include <sys/socketvar.h>
630e8ff41aSMatthew Dillon #include <sys/sysctl.h>
640e8ff41aSMatthew Dillon #include <sys/uio.h>
650e8ff41aSMatthew Dillon 
660e8ff41aSMatthew Dillon #include <net/if.h>
670e8ff41aSMatthew Dillon #include <net/route.h>
680e8ff41aSMatthew Dillon 
690e8ff41aSMatthew Dillon #include <netinet/in.h>
700e8ff41aSMatthew Dillon #include <net/if_types.h>
710e8ff41aSMatthew Dillon #include <net/if_dl.h>
720e8ff41aSMatthew Dillon 
730e8ff41aSMatthew Dillon #include "rpcv2.h"
740e8ff41aSMatthew Dillon #include "nfsproto.h"
750e8ff41aSMatthew Dillon #include "nfs.h"
760e8ff41aSMatthew Dillon #include "nfsdiskless.h"
770e8ff41aSMatthew Dillon #include "krpc.h"
780e8ff41aSMatthew Dillon #include "xdr_subs.h"
790e8ff41aSMatthew Dillon #include "nfsmountrpc.h"
800e8ff41aSMatthew Dillon 
810e8ff41aSMatthew Dillon /*
820e8ff41aSMatthew Dillon  * What is the longest we will wait before re-sending a request?
830e8ff41aSMatthew Dillon  * Note this is also the frequency of "RPC timeout" messages.
840e8ff41aSMatthew Dillon  * The re-send loop count sup linearly to this maximum, so the
850e8ff41aSMatthew Dillon  * first complaint will happen after (1+2+3+4+5)=15 seconds.
860e8ff41aSMatthew Dillon  */
870e8ff41aSMatthew Dillon 
880e8ff41aSMatthew Dillon static int getdec(char **ptr);
890e8ff41aSMatthew Dillon static char *substr(char *a,char *b);
900e8ff41aSMatthew Dillon static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
910e8ff41aSMatthew Dillon static int xdr_int_decode(struct mbuf **ptr, int *iptr);
920e8ff41aSMatthew Dillon 
930e8ff41aSMatthew Dillon void
nfs_mountopts(struct nfs_args * args,char * p)94b9a7a2bdSMatthew Dillon nfs_mountopts(struct nfs_args *args, char *p)
950e8ff41aSMatthew Dillon {
960e8ff41aSMatthew Dillon 	char *tmp;
970e8ff41aSMatthew Dillon 
980e8ff41aSMatthew Dillon 	args->version = NFS_ARGSVERSION;
990e8ff41aSMatthew Dillon 	args->rsize = 8192;
1000e8ff41aSMatthew Dillon 	args->wsize = 8192;
1010e8ff41aSMatthew Dillon 	args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
102b9a7a2bdSMatthew Dillon 	args->sotype = SOCK_STREAM;
1030e8ff41aSMatthew Dillon 	if (p == NULL)
1040e8ff41aSMatthew Dillon 		return;
10539215f4cSSascha Wildner 	if ((tmp = substr(p, "rsize=")))
1060e8ff41aSMatthew Dillon 		args->rsize = getdec(&tmp);
10739215f4cSSascha Wildner 	if ((tmp = substr(p, "wsize=")))
1080e8ff41aSMatthew Dillon 		args->wsize = getdec(&tmp);
10939215f4cSSascha Wildner 	if ((tmp = substr(p, "intr")))
1100e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_INT;
11139215f4cSSascha Wildner 	if ((tmp = substr(p, "soft")))
1120e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_SOFT;
11339215f4cSSascha Wildner 	if ((tmp = substr(p, "noconn")))
1140e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_NOCONN;
11539215f4cSSascha Wildner 	if ((tmp = substr(p, "udp")))
116b9a7a2bdSMatthew Dillon 		args->sotype = SOCK_DGRAM;
1170e8ff41aSMatthew Dillon }
1180e8ff41aSMatthew Dillon 
1190e8ff41aSMatthew Dillon /*
1200e8ff41aSMatthew Dillon  * RPC: mountd/mount
1210e8ff41aSMatthew Dillon  * Given a server pathname, get an NFS file handle.
1220e8ff41aSMatthew Dillon  * Also, sets sin->sin_port to the NFS service port.
1230e8ff41aSMatthew Dillon  */
1240e8ff41aSMatthew Dillon int
md_mount(struct sockaddr_in * mdsin,char * path,u_char * fhp,int * fhsizep,struct nfs_args * args,struct thread * td)1250e8ff41aSMatthew Dillon md_mount(struct sockaddr_in *mdsin,		/* mountd server address */
1260e8ff41aSMatthew Dillon 	 char *path,
1270e8ff41aSMatthew Dillon 	 u_char *fhp,
1280e8ff41aSMatthew Dillon 	 int *fhsizep,
1290e8ff41aSMatthew Dillon 	 struct nfs_args *args,
1300e8ff41aSMatthew Dillon 	 struct thread *td)
1310e8ff41aSMatthew Dillon {
1320e8ff41aSMatthew Dillon 	struct mbuf *m;
1330e8ff41aSMatthew Dillon 	int error;
1340e8ff41aSMatthew Dillon 	int authunixok;
1350e8ff41aSMatthew Dillon 	int authcount;
1360e8ff41aSMatthew Dillon 	int authver;
1370e8ff41aSMatthew Dillon 
1380e8ff41aSMatthew Dillon 	/* First try NFS v3 */
1390e8ff41aSMatthew Dillon 	/* Get port number for MOUNTD. */
1400e8ff41aSMatthew Dillon 	error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1410e8ff41aSMatthew Dillon 			     &mdsin->sin_port, td);
1420e8ff41aSMatthew Dillon 	if (error == 0) {
1430e8ff41aSMatthew Dillon 		m = xdr_string_encode(path, strlen(path));
1440e8ff41aSMatthew Dillon 
1450e8ff41aSMatthew Dillon 		/* Do RPC to mountd. */
1460e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1470e8ff41aSMatthew Dillon 				  RPCMNT_MOUNT, &m, NULL, td);
1480e8ff41aSMatthew Dillon 	}
1490e8ff41aSMatthew Dillon 	if (error == 0) {
1500e8ff41aSMatthew Dillon 		args->flags |= NFSMNT_NFSV3;
1510e8ff41aSMatthew Dillon 	} else {
1520e8ff41aSMatthew Dillon 		/* Fallback to NFS v2 */
1530e8ff41aSMatthew Dillon 
1540e8ff41aSMatthew Dillon 		/* Get port number for MOUNTD. */
1550e8ff41aSMatthew Dillon 		error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1560e8ff41aSMatthew Dillon 				     &mdsin->sin_port, td);
1570e8ff41aSMatthew Dillon 		if (error != 0)
1580e8ff41aSMatthew Dillon 			return error;
1590e8ff41aSMatthew Dillon 
1600e8ff41aSMatthew Dillon 		m = xdr_string_encode(path, strlen(path));
1610e8ff41aSMatthew Dillon 
1620e8ff41aSMatthew Dillon 		/* Do RPC to mountd. */
1630e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1640e8ff41aSMatthew Dillon 				  RPCMNT_MOUNT, &m, NULL, td);
1650e8ff41aSMatthew Dillon 		if (error != 0)
1660e8ff41aSMatthew Dillon 			return error;	/* message already freed */
167b9a7a2bdSMatthew Dillon 		args->flags &= ~NFSMNT_NFSV3;
1680e8ff41aSMatthew Dillon 	}
1690e8ff41aSMatthew Dillon 
1700e8ff41aSMatthew Dillon 	if (xdr_int_decode(&m, &error) != 0 || error != 0)
1710e8ff41aSMatthew Dillon 		goto bad;
1720e8ff41aSMatthew Dillon 
1730e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
1740e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, fhsizep) != 0 ||
1750e8ff41aSMatthew Dillon 		    *fhsizep > NFSX_V3FHMAX ||
1760e8ff41aSMatthew Dillon 		    *fhsizep <= 0)
1770e8ff41aSMatthew Dillon 			goto bad;
1780e8ff41aSMatthew Dillon 	} else
1790e8ff41aSMatthew Dillon 		*fhsizep = NFSX_V2FH;
1800e8ff41aSMatthew Dillon 
1810e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
1820e8ff41aSMatthew Dillon 		goto bad;
1830e8ff41aSMatthew Dillon 
1840e8ff41aSMatthew Dillon 	if (args->flags & NFSMNT_NFSV3) {
1850e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, &authcount) != 0)
1860e8ff41aSMatthew Dillon 			goto bad;
1870e8ff41aSMatthew Dillon 		authunixok = 0;
1880e8ff41aSMatthew Dillon 		if (authcount < 0 || authcount > 100)
1890e8ff41aSMatthew Dillon 			goto bad;
1900e8ff41aSMatthew Dillon 		while (authcount > 0) {
1910e8ff41aSMatthew Dillon 			if (xdr_int_decode(&m, &authver) != 0)
1920e8ff41aSMatthew Dillon 				goto bad;
1930e8ff41aSMatthew Dillon 			if (authver == RPCAUTH_UNIX)
1940e8ff41aSMatthew Dillon 				authunixok = 1;
1950e8ff41aSMatthew Dillon 			authcount--;
1960e8ff41aSMatthew Dillon 		}
1970e8ff41aSMatthew Dillon 		if (authunixok == 0)
1980e8ff41aSMatthew Dillon 			goto bad;
1990e8ff41aSMatthew Dillon 	}
2000e8ff41aSMatthew Dillon 
2010e8ff41aSMatthew Dillon 	/* Set port number for NFS use. */
2020e8ff41aSMatthew Dillon 	error = krpc_portmap(mdsin, NFS_PROG,
2030e8ff41aSMatthew Dillon 			     (args->flags &
2040e8ff41aSMatthew Dillon 			      NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
2050e8ff41aSMatthew Dillon 			     &mdsin->sin_port, td);
2060e8ff41aSMatthew Dillon 
2070e8ff41aSMatthew Dillon 	goto out;
2080e8ff41aSMatthew Dillon 
2090e8ff41aSMatthew Dillon bad:
2100e8ff41aSMatthew Dillon 	error = EBADRPC;
2110e8ff41aSMatthew Dillon 
2120e8ff41aSMatthew Dillon out:
2130e8ff41aSMatthew Dillon 	m_freem(m);
2140e8ff41aSMatthew Dillon 	return error;
2150e8ff41aSMatthew Dillon }
2160e8ff41aSMatthew Dillon 
2170e8ff41aSMatthew Dillon int
md_lookup_swap(struct sockaddr_in * mdsin,char * path,u_char * fhp,int * fhsizep,struct nfs_args * args,struct thread * td)2180e8ff41aSMatthew Dillon md_lookup_swap(struct sockaddr_in *mdsin,	/* mountd server address */
2190e8ff41aSMatthew Dillon 	       char *path,
2200e8ff41aSMatthew Dillon 	       u_char *fhp,
2210e8ff41aSMatthew Dillon 	       int *fhsizep,
2220e8ff41aSMatthew Dillon 	       struct nfs_args *args,
2230e8ff41aSMatthew Dillon 	       struct thread *td)
2240e8ff41aSMatthew Dillon {
2250e8ff41aSMatthew Dillon 	struct mbuf *m;
2260e8ff41aSMatthew Dillon 	int error;
2270e8ff41aSMatthew Dillon 	int size = -1;
2280e8ff41aSMatthew Dillon 	int attribs_present;
2290e8ff41aSMatthew Dillon 	int status;
2300e8ff41aSMatthew Dillon 	union {
2310e8ff41aSMatthew Dillon 		u_int32_t v2[17];
2320e8ff41aSMatthew Dillon 		u_int32_t v3[21];
2330e8ff41aSMatthew Dillon 	} fattribs;
2340e8ff41aSMatthew Dillon 
235*b5523eacSSascha Wildner 	m = m_get(M_WAITOK, MT_DATA);
2360e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
2370e8ff41aSMatthew Dillon 		*mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
2380e8ff41aSMatthew Dillon 		bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
2390e8ff41aSMatthew Dillon 		m->m_len = *fhsizep + sizeof(u_int32_t);
2400e8ff41aSMatthew Dillon 	} else {
2410e8ff41aSMatthew Dillon 		bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
2420e8ff41aSMatthew Dillon 		m->m_len = NFSX_V2FH;
2430e8ff41aSMatthew Dillon 	}
2440e8ff41aSMatthew Dillon 
2450e8ff41aSMatthew Dillon 	m->m_next = xdr_string_encode(path, strlen(path));
2460e8ff41aSMatthew Dillon 	if (m->m_next == NULL) {
2470e8ff41aSMatthew Dillon 		error = ENOBUFS;
2480e8ff41aSMatthew Dillon 		goto out;
2490e8ff41aSMatthew Dillon 	}
2500e8ff41aSMatthew Dillon 
2510e8ff41aSMatthew Dillon 	/* Do RPC to nfsd. */
2520e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0)
2530e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
2540e8ff41aSMatthew Dillon 				  NFSPROC_LOOKUP, &m, NULL, td);
2550e8ff41aSMatthew Dillon 	else
2560e8ff41aSMatthew Dillon 		error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
2570e8ff41aSMatthew Dillon 				  NFSV2PROC_LOOKUP, &m, NULL, td);
2580e8ff41aSMatthew Dillon 	if (error != 0)
2590e8ff41aSMatthew Dillon 		return error;	/* message already freed */
2600e8ff41aSMatthew Dillon 
2610e8ff41aSMatthew Dillon 	if (xdr_int_decode(&m, &status) != 0)
2620e8ff41aSMatthew Dillon 		goto bad;
2630e8ff41aSMatthew Dillon 	if (status != 0) {
2640e8ff41aSMatthew Dillon 		error = ENOENT;
2650e8ff41aSMatthew Dillon 		goto out;
2660e8ff41aSMatthew Dillon 	}
2670e8ff41aSMatthew Dillon 
2680e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
2690e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, fhsizep) != 0 ||
2700e8ff41aSMatthew Dillon 		    *fhsizep > NFSX_V3FHMAX ||
2710e8ff41aSMatthew Dillon 		    *fhsizep <= 0)
2720e8ff41aSMatthew Dillon 			goto bad;
2730e8ff41aSMatthew Dillon 	} else
2740e8ff41aSMatthew Dillon 		*fhsizep = NFSX_V2FH;
2750e8ff41aSMatthew Dillon 
2760e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
2770e8ff41aSMatthew Dillon 		goto bad;
2780e8ff41aSMatthew Dillon 
2790e8ff41aSMatthew Dillon 	if ((args->flags & NFSMNT_NFSV3) != 0) {
2800e8ff41aSMatthew Dillon 		if (xdr_int_decode(&m, &attribs_present) != 0)
2810e8ff41aSMatthew Dillon 			goto bad;
2820e8ff41aSMatthew Dillon 		if (attribs_present != 0) {
2830e8ff41aSMatthew Dillon 			if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3,
2840e8ff41aSMatthew Dillon 					      sizeof(u_int32_t) * 21) != 0)
2850e8ff41aSMatthew Dillon 				goto bad;
2860e8ff41aSMatthew Dillon 			size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
2870e8ff41aSMatthew Dillon 		}
2880e8ff41aSMatthew Dillon 	} else {
2890e8ff41aSMatthew Dillon 		if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
2900e8ff41aSMatthew Dillon 				      sizeof(u_int32_t) * 17) != 0)
2910e8ff41aSMatthew Dillon 			goto bad;
2920e8ff41aSMatthew Dillon 		size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
2930e8ff41aSMatthew Dillon 	}
2940e8ff41aSMatthew Dillon 
2950e8ff41aSMatthew Dillon 	if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
2960e8ff41aSMatthew Dillon 		nfsv3_diskless.swap_nblks = size / 1024;
297086c1d7eSSascha Wildner 		kprintf("md_lookup_swap: Swap size is %d KB\n",
2980e8ff41aSMatthew Dillon 		       nfsv3_diskless.swap_nblks);
2990e8ff41aSMatthew Dillon 	}
3000e8ff41aSMatthew Dillon 
3010e8ff41aSMatthew Dillon 	goto out;
3020e8ff41aSMatthew Dillon 
3030e8ff41aSMatthew Dillon bad:
3040e8ff41aSMatthew Dillon 	error = EBADRPC;
3050e8ff41aSMatthew Dillon 
3060e8ff41aSMatthew Dillon out:
3070e8ff41aSMatthew Dillon 	m_freem(m);
3080e8ff41aSMatthew Dillon 	return error;
3090e8ff41aSMatthew Dillon }
3100e8ff41aSMatthew Dillon 
3110e8ff41aSMatthew Dillon int
setfs(struct sockaddr_in * addr,char * path,char * p)3120e8ff41aSMatthew Dillon setfs(struct sockaddr_in *addr, char *path, char *p)
3130e8ff41aSMatthew Dillon {
3140e8ff41aSMatthew Dillon 	unsigned int ip;
3150e8ff41aSMatthew Dillon 	int val;
3160e8ff41aSMatthew Dillon 
3170e8ff41aSMatthew Dillon 	ip = 0;
3180e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
3190e8ff41aSMatthew Dillon 		return 0;
3200e8ff41aSMatthew Dillon 	ip = val << 24;
3210e8ff41aSMatthew Dillon 	if (*p != '.')
3220e8ff41aSMatthew Dillon 		return 0;
3230e8ff41aSMatthew Dillon 	p++;
3240e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
3250e8ff41aSMatthew Dillon 		return 0;
3260e8ff41aSMatthew Dillon 	ip |= (val << 16);
3270e8ff41aSMatthew Dillon 	if (*p != '.')
3280e8ff41aSMatthew Dillon 		return 0;
3290e8ff41aSMatthew Dillon 	p++;
3300e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
3310e8ff41aSMatthew Dillon 		return 0;
3320e8ff41aSMatthew Dillon 	ip |= (val << 8);
3330e8ff41aSMatthew Dillon 	if (*p != '.')
3340e8ff41aSMatthew Dillon 		return 0;
3350e8ff41aSMatthew Dillon 	p++;
3360e8ff41aSMatthew Dillon 	if (((val = getdec(&p)) < 0) || (val > 255))
3370e8ff41aSMatthew Dillon 		return 0;
3380e8ff41aSMatthew Dillon 	ip |= val;
3390e8ff41aSMatthew Dillon 	if (*p != ':')
3400e8ff41aSMatthew Dillon 		return 0;
3410e8ff41aSMatthew Dillon 	p++;
3420e8ff41aSMatthew Dillon 
3430e8ff41aSMatthew Dillon 	addr->sin_addr.s_addr = htonl(ip);
3440e8ff41aSMatthew Dillon 	addr->sin_len = sizeof(struct sockaddr_in);
3450e8ff41aSMatthew Dillon 	addr->sin_family = AF_INET;
3460e8ff41aSMatthew Dillon 
3470e8ff41aSMatthew Dillon 	strncpy(path, p, MNAMELEN - 1);
3480e8ff41aSMatthew Dillon 	return 1;
3490e8ff41aSMatthew Dillon }
3500e8ff41aSMatthew Dillon 
3510e8ff41aSMatthew Dillon static int
getdec(char ** ptr)3520e8ff41aSMatthew Dillon getdec(char **ptr)
3530e8ff41aSMatthew Dillon {
3540e8ff41aSMatthew Dillon 	char *p;
3550e8ff41aSMatthew Dillon 	int ret;
3560e8ff41aSMatthew Dillon 
3570e8ff41aSMatthew Dillon 	p = *ptr;
3580e8ff41aSMatthew Dillon 	ret = 0;
3590e8ff41aSMatthew Dillon 	if ((*p < '0') || (*p > '9'))
3600e8ff41aSMatthew Dillon 		return -1;
3610e8ff41aSMatthew Dillon 	while ((*p >= '0') && (*p <= '9')) {
3620e8ff41aSMatthew Dillon 		ret = ret * 10 + (*p - '0');
3630e8ff41aSMatthew Dillon 		p++;
3640e8ff41aSMatthew Dillon 	}
3650e8ff41aSMatthew Dillon 	*ptr = p;
3660e8ff41aSMatthew Dillon 	return ret;
3670e8ff41aSMatthew Dillon }
3680e8ff41aSMatthew Dillon 
3690e8ff41aSMatthew Dillon static char *
substr(char * a,char * b)3700e8ff41aSMatthew Dillon substr(char *a, char *b)
3710e8ff41aSMatthew Dillon {
3720e8ff41aSMatthew Dillon 	char *loc1;
3730e8ff41aSMatthew Dillon 	char *loc2;
3740e8ff41aSMatthew Dillon 
3750e8ff41aSMatthew Dillon         while (*a != '\0') {
3760e8ff41aSMatthew Dillon                 loc1 = a;
3770e8ff41aSMatthew Dillon                 loc2 = b;
3780e8ff41aSMatthew Dillon                 while (*loc1 == *loc2++) {
3790e8ff41aSMatthew Dillon                         if (*loc1 == '\0')
3800e8ff41aSMatthew Dillon 				return 0;
3810e8ff41aSMatthew Dillon                         loc1++;
3820e8ff41aSMatthew Dillon                         if (*loc2 == '\0')
3830e8ff41aSMatthew Dillon 				return loc1;
3840e8ff41aSMatthew Dillon                 }
3850e8ff41aSMatthew Dillon 		a++;
3860e8ff41aSMatthew Dillon         }
3870e8ff41aSMatthew Dillon         return 0;
3880e8ff41aSMatthew Dillon }
3890e8ff41aSMatthew Dillon 
3900e8ff41aSMatthew Dillon static int
xdr_opaque_decode(struct mbuf ** mptr,u_char * buf,int len)3910e8ff41aSMatthew Dillon xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
3920e8ff41aSMatthew Dillon {
3930e8ff41aSMatthew Dillon 	struct mbuf *m;
3940e8ff41aSMatthew Dillon 	int alignedlen;
3950e8ff41aSMatthew Dillon 
3960e8ff41aSMatthew Dillon 	m = *mptr;
3970e8ff41aSMatthew Dillon 	alignedlen = ( len + 3 ) & ~3;
3980e8ff41aSMatthew Dillon 
3990e8ff41aSMatthew Dillon 	if (m->m_len < alignedlen) {
4000e8ff41aSMatthew Dillon 		m = m_pullup(m, alignedlen);
4010e8ff41aSMatthew Dillon 		if (m == NULL) {
4020e8ff41aSMatthew Dillon 			*mptr = NULL;
4030e8ff41aSMatthew Dillon 			return EBADRPC;
4040e8ff41aSMatthew Dillon 		}
4050e8ff41aSMatthew Dillon 	}
4060e8ff41aSMatthew Dillon 	bcopy(mtod(m, u_char *), buf, len);
4070e8ff41aSMatthew Dillon 	m_adj(m, alignedlen);
4080e8ff41aSMatthew Dillon 	*mptr = m;
4090e8ff41aSMatthew Dillon 	return 0;
4100e8ff41aSMatthew Dillon }
4110e8ff41aSMatthew Dillon 
4120e8ff41aSMatthew Dillon static int
xdr_int_decode(struct mbuf ** mptr,int * iptr)4130e8ff41aSMatthew Dillon xdr_int_decode(struct mbuf **mptr, int *iptr)
4140e8ff41aSMatthew Dillon {
4150e8ff41aSMatthew Dillon 	u_int32_t i;
4160e8ff41aSMatthew Dillon 	if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
4170e8ff41aSMatthew Dillon 		return EBADRPC;
4180e8ff41aSMatthew Dillon 	*iptr = fxdr_unsigned(u_int32_t, i);
4190e8ff41aSMatthew Dillon 	return 0;
4200e8ff41aSMatthew Dillon }
4210e8ff41aSMatthew Dillon 
4220e8ff41aSMatthew Dillon #endif	/* BOOTP && NFS_ROOT */
4230e8ff41aSMatthew Dillon 
424