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