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 $ 41*086c1d7eSSascha Wildner * $DragonFly: src/sys/vfs/nfs/nfs_mountrpc.c,v 1.2 2006/12/23 00:41:29 swildner Exp $ 420e8ff41aSMatthew Dillon */ 430e8ff41aSMatthew Dillon /* 440e8ff41aSMatthew Dillon * Procedures used by NFS_ROOT and BOOTP to do an NFS mount rpc to obtain 450e8ff41aSMatthew Dillon * the nfs root file handle for a NFS-based root mount point. This module 460e8ff41aSMatthew Dillon * is not used by normal operating code because the 'mount' command has a 470e8ff41aSMatthew Dillon * far more sophisticated implementation. 480e8ff41aSMatthew Dillon */ 490e8ff41aSMatthew Dillon #include "opt_bootp.h" 500e8ff41aSMatthew Dillon #include "opt_nfsroot.h" 510e8ff41aSMatthew Dillon 520e8ff41aSMatthew Dillon #if defined(BOOTP) || defined(NFS_ROOT) 530e8ff41aSMatthew Dillon 540e8ff41aSMatthew Dillon #include <sys/param.h> 550e8ff41aSMatthew Dillon #include <sys/systm.h> 560e8ff41aSMatthew Dillon #include <sys/kernel.h> 570e8ff41aSMatthew Dillon #include <sys/sockio.h> 580e8ff41aSMatthew Dillon #include <sys/proc.h> 590e8ff41aSMatthew Dillon #include <sys/malloc.h> 600e8ff41aSMatthew Dillon #include <sys/mount.h> 610e8ff41aSMatthew Dillon #include <sys/mbuf.h> 620e8ff41aSMatthew Dillon #include <sys/socket.h> 630e8ff41aSMatthew Dillon #include <sys/socketvar.h> 640e8ff41aSMatthew Dillon #include <sys/sysctl.h> 650e8ff41aSMatthew Dillon #include <sys/uio.h> 660e8ff41aSMatthew Dillon 670e8ff41aSMatthew Dillon #include <net/if.h> 680e8ff41aSMatthew Dillon #include <net/route.h> 690e8ff41aSMatthew Dillon 700e8ff41aSMatthew Dillon #include <netinet/in.h> 710e8ff41aSMatthew Dillon #include <net/if_types.h> 720e8ff41aSMatthew Dillon #include <net/if_dl.h> 730e8ff41aSMatthew Dillon 740e8ff41aSMatthew Dillon #include "rpcv2.h" 750e8ff41aSMatthew Dillon #include "nfsproto.h" 760e8ff41aSMatthew Dillon #include "nfs.h" 770e8ff41aSMatthew Dillon #include "nfsdiskless.h" 780e8ff41aSMatthew Dillon #include "krpc.h" 790e8ff41aSMatthew Dillon #include "xdr_subs.h" 800e8ff41aSMatthew Dillon #include "nfsmountrpc.h" 810e8ff41aSMatthew Dillon 820e8ff41aSMatthew Dillon /* 830e8ff41aSMatthew Dillon * What is the longest we will wait before re-sending a request? 840e8ff41aSMatthew Dillon * Note this is also the frequency of "RPC timeout" messages. 850e8ff41aSMatthew Dillon * The re-send loop count sup linearly to this maximum, so the 860e8ff41aSMatthew Dillon * first complaint will happen after (1+2+3+4+5)=15 seconds. 870e8ff41aSMatthew Dillon */ 880e8ff41aSMatthew Dillon 890e8ff41aSMatthew Dillon extern struct nfsv3_diskless nfsv3_diskless; 900e8ff41aSMatthew Dillon 910e8ff41aSMatthew Dillon static int getdec(char **ptr); 920e8ff41aSMatthew Dillon static char *substr(char *a,char *b); 930e8ff41aSMatthew Dillon static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len); 940e8ff41aSMatthew Dillon static int xdr_int_decode(struct mbuf **ptr, int *iptr); 950e8ff41aSMatthew Dillon 960e8ff41aSMatthew Dillon void 970e8ff41aSMatthew Dillon mountopts(struct nfs_args *args, char *p) 980e8ff41aSMatthew Dillon { 990e8ff41aSMatthew Dillon char *tmp; 1000e8ff41aSMatthew Dillon 1010e8ff41aSMatthew Dillon args->version = NFS_ARGSVERSION; 1020e8ff41aSMatthew Dillon args->rsize = 8192; 1030e8ff41aSMatthew Dillon args->wsize = 8192; 1040e8ff41aSMatthew Dillon args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT; 1050e8ff41aSMatthew Dillon args->sotype = SOCK_DGRAM; 1060e8ff41aSMatthew Dillon if (p == NULL) 1070e8ff41aSMatthew Dillon return; 1080e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "rsize="))) 1090e8ff41aSMatthew Dillon args->rsize = getdec(&tmp); 1100e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "wsize="))) 1110e8ff41aSMatthew Dillon args->wsize = getdec(&tmp); 1120e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "intr"))) 1130e8ff41aSMatthew Dillon args->flags |= NFSMNT_INT; 1140e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "soft"))) 1150e8ff41aSMatthew Dillon args->flags |= NFSMNT_SOFT; 1160e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "noconn"))) 1170e8ff41aSMatthew Dillon args->flags |= NFSMNT_NOCONN; 1180e8ff41aSMatthew Dillon if ((tmp = (char *)substr(p, "tcp"))) 1190e8ff41aSMatthew Dillon args->sotype = SOCK_STREAM; 1200e8ff41aSMatthew Dillon } 1210e8ff41aSMatthew Dillon 1220e8ff41aSMatthew Dillon /* 1230e8ff41aSMatthew Dillon * RPC: mountd/mount 1240e8ff41aSMatthew Dillon * Given a server pathname, get an NFS file handle. 1250e8ff41aSMatthew Dillon * Also, sets sin->sin_port to the NFS service port. 1260e8ff41aSMatthew Dillon */ 1270e8ff41aSMatthew Dillon int 1280e8ff41aSMatthew Dillon md_mount(struct sockaddr_in *mdsin, /* mountd server address */ 1290e8ff41aSMatthew Dillon char *path, 1300e8ff41aSMatthew Dillon u_char *fhp, 1310e8ff41aSMatthew Dillon int *fhsizep, 1320e8ff41aSMatthew Dillon struct nfs_args *args, 1330e8ff41aSMatthew Dillon struct thread *td) 1340e8ff41aSMatthew Dillon { 1350e8ff41aSMatthew Dillon struct mbuf *m; 1360e8ff41aSMatthew Dillon int error; 1370e8ff41aSMatthew Dillon int authunixok; 1380e8ff41aSMatthew Dillon int authcount; 1390e8ff41aSMatthew Dillon int authver; 1400e8ff41aSMatthew Dillon 1410e8ff41aSMatthew Dillon #ifdef BOOTP_NFSV3 1420e8ff41aSMatthew Dillon /* First try NFS v3 */ 1430e8ff41aSMatthew Dillon /* Get port number for MOUNTD. */ 1440e8ff41aSMatthew Dillon error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1450e8ff41aSMatthew Dillon &mdsin->sin_port, td); 1460e8ff41aSMatthew Dillon if (error == 0) { 1470e8ff41aSMatthew Dillon m = xdr_string_encode(path, strlen(path)); 1480e8ff41aSMatthew Dillon 1490e8ff41aSMatthew Dillon /* Do RPC to mountd. */ 1500e8ff41aSMatthew Dillon error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, 1510e8ff41aSMatthew Dillon RPCMNT_MOUNT, &m, NULL, td); 1520e8ff41aSMatthew Dillon } 1530e8ff41aSMatthew Dillon if (error == 0) { 1540e8ff41aSMatthew Dillon args->flags |= NFSMNT_NFSV3; 1550e8ff41aSMatthew Dillon } else { 1560e8ff41aSMatthew Dillon #endif 1570e8ff41aSMatthew Dillon /* Fallback to NFS v2 */ 1580e8ff41aSMatthew Dillon 1590e8ff41aSMatthew Dillon /* Get port number for MOUNTD. */ 1600e8ff41aSMatthew Dillon error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1610e8ff41aSMatthew Dillon &mdsin->sin_port, td); 1620e8ff41aSMatthew Dillon if (error != 0) 1630e8ff41aSMatthew Dillon return error; 1640e8ff41aSMatthew Dillon 1650e8ff41aSMatthew Dillon m = xdr_string_encode(path, strlen(path)); 1660e8ff41aSMatthew Dillon 1670e8ff41aSMatthew Dillon /* Do RPC to mountd. */ 1680e8ff41aSMatthew Dillon error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, 1690e8ff41aSMatthew Dillon RPCMNT_MOUNT, &m, NULL, td); 1700e8ff41aSMatthew Dillon if (error != 0) 1710e8ff41aSMatthew Dillon return error; /* message already freed */ 1720e8ff41aSMatthew Dillon 1730e8ff41aSMatthew Dillon #ifdef BOOTP_NFSV3 1740e8ff41aSMatthew Dillon } 1750e8ff41aSMatthew Dillon #endif 1760e8ff41aSMatthew Dillon 1770e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &error) != 0 || error != 0) 1780e8ff41aSMatthew Dillon goto bad; 1790e8ff41aSMatthew Dillon 1800e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 1810e8ff41aSMatthew Dillon if (xdr_int_decode(&m, fhsizep) != 0 || 1820e8ff41aSMatthew Dillon *fhsizep > NFSX_V3FHMAX || 1830e8ff41aSMatthew Dillon *fhsizep <= 0) 1840e8ff41aSMatthew Dillon goto bad; 1850e8ff41aSMatthew Dillon } else 1860e8ff41aSMatthew Dillon *fhsizep = NFSX_V2FH; 1870e8ff41aSMatthew Dillon 1880e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 1890e8ff41aSMatthew Dillon goto bad; 1900e8ff41aSMatthew Dillon 1910e8ff41aSMatthew Dillon if (args->flags & NFSMNT_NFSV3) { 1920e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &authcount) != 0) 1930e8ff41aSMatthew Dillon goto bad; 1940e8ff41aSMatthew Dillon authunixok = 0; 1950e8ff41aSMatthew Dillon if (authcount < 0 || authcount > 100) 1960e8ff41aSMatthew Dillon goto bad; 1970e8ff41aSMatthew Dillon while (authcount > 0) { 1980e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &authver) != 0) 1990e8ff41aSMatthew Dillon goto bad; 2000e8ff41aSMatthew Dillon if (authver == RPCAUTH_UNIX) 2010e8ff41aSMatthew Dillon authunixok = 1; 2020e8ff41aSMatthew Dillon authcount--; 2030e8ff41aSMatthew Dillon } 2040e8ff41aSMatthew Dillon if (authunixok == 0) 2050e8ff41aSMatthew Dillon goto bad; 2060e8ff41aSMatthew Dillon } 2070e8ff41aSMatthew Dillon 2080e8ff41aSMatthew Dillon /* Set port number for NFS use. */ 2090e8ff41aSMatthew Dillon error = krpc_portmap(mdsin, NFS_PROG, 2100e8ff41aSMatthew Dillon (args->flags & 2110e8ff41aSMatthew Dillon NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2, 2120e8ff41aSMatthew Dillon &mdsin->sin_port, td); 2130e8ff41aSMatthew Dillon 2140e8ff41aSMatthew Dillon goto out; 2150e8ff41aSMatthew Dillon 2160e8ff41aSMatthew Dillon bad: 2170e8ff41aSMatthew Dillon error = EBADRPC; 2180e8ff41aSMatthew Dillon 2190e8ff41aSMatthew Dillon out: 2200e8ff41aSMatthew Dillon m_freem(m); 2210e8ff41aSMatthew Dillon return error; 2220e8ff41aSMatthew Dillon } 2230e8ff41aSMatthew Dillon 2240e8ff41aSMatthew Dillon int 2250e8ff41aSMatthew Dillon md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */ 2260e8ff41aSMatthew Dillon char *path, 2270e8ff41aSMatthew Dillon u_char *fhp, 2280e8ff41aSMatthew Dillon int *fhsizep, 2290e8ff41aSMatthew Dillon struct nfs_args *args, 2300e8ff41aSMatthew Dillon struct thread *td) 2310e8ff41aSMatthew Dillon { 2320e8ff41aSMatthew Dillon struct mbuf *m; 2330e8ff41aSMatthew Dillon int error; 2340e8ff41aSMatthew Dillon int size = -1; 2350e8ff41aSMatthew Dillon int attribs_present; 2360e8ff41aSMatthew Dillon int status; 2370e8ff41aSMatthew Dillon union { 2380e8ff41aSMatthew Dillon u_int32_t v2[17]; 2390e8ff41aSMatthew Dillon u_int32_t v3[21]; 2400e8ff41aSMatthew Dillon } fattribs; 2410e8ff41aSMatthew Dillon 2420e8ff41aSMatthew Dillon m = m_get(MB_WAIT,MT_DATA); 2430e8ff41aSMatthew Dillon if (m == NULL) 2440e8ff41aSMatthew Dillon return ENOBUFS; 2450e8ff41aSMatthew Dillon 2460e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2470e8ff41aSMatthew Dillon *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); 2480e8ff41aSMatthew Dillon bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); 2490e8ff41aSMatthew Dillon m->m_len = *fhsizep + sizeof(u_int32_t); 2500e8ff41aSMatthew Dillon } else { 2510e8ff41aSMatthew Dillon bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); 2520e8ff41aSMatthew Dillon m->m_len = NFSX_V2FH; 2530e8ff41aSMatthew Dillon } 2540e8ff41aSMatthew Dillon 2550e8ff41aSMatthew Dillon m->m_next = xdr_string_encode(path, strlen(path)); 2560e8ff41aSMatthew Dillon if (m->m_next == NULL) { 2570e8ff41aSMatthew Dillon error = ENOBUFS; 2580e8ff41aSMatthew Dillon goto out; 2590e8ff41aSMatthew Dillon } 2600e8ff41aSMatthew Dillon 2610e8ff41aSMatthew Dillon /* Do RPC to nfsd. */ 2620e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) 2630e8ff41aSMatthew Dillon error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 2640e8ff41aSMatthew Dillon NFSPROC_LOOKUP, &m, NULL, td); 2650e8ff41aSMatthew Dillon else 2660e8ff41aSMatthew Dillon error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 2670e8ff41aSMatthew Dillon NFSV2PROC_LOOKUP, &m, NULL, td); 2680e8ff41aSMatthew Dillon if (error != 0) 2690e8ff41aSMatthew Dillon return error; /* message already freed */ 2700e8ff41aSMatthew Dillon 2710e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &status) != 0) 2720e8ff41aSMatthew Dillon goto bad; 2730e8ff41aSMatthew Dillon if (status != 0) { 2740e8ff41aSMatthew Dillon error = ENOENT; 2750e8ff41aSMatthew Dillon goto out; 2760e8ff41aSMatthew Dillon } 2770e8ff41aSMatthew Dillon 2780e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2790e8ff41aSMatthew Dillon if (xdr_int_decode(&m, fhsizep) != 0 || 2800e8ff41aSMatthew Dillon *fhsizep > NFSX_V3FHMAX || 2810e8ff41aSMatthew Dillon *fhsizep <= 0) 2820e8ff41aSMatthew Dillon goto bad; 2830e8ff41aSMatthew Dillon } else 2840e8ff41aSMatthew Dillon *fhsizep = NFSX_V2FH; 2850e8ff41aSMatthew Dillon 2860e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 2870e8ff41aSMatthew Dillon goto bad; 2880e8ff41aSMatthew Dillon 2890e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2900e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &attribs_present) != 0) 2910e8ff41aSMatthew Dillon goto bad; 2920e8ff41aSMatthew Dillon if (attribs_present != 0) { 2930e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, 2940e8ff41aSMatthew Dillon sizeof(u_int32_t) * 21) != 0) 2950e8ff41aSMatthew Dillon goto bad; 2960e8ff41aSMatthew Dillon size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 2970e8ff41aSMatthew Dillon } 2980e8ff41aSMatthew Dillon } else { 2990e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 3000e8ff41aSMatthew Dillon sizeof(u_int32_t) * 17) != 0) 3010e8ff41aSMatthew Dillon goto bad; 3020e8ff41aSMatthew Dillon size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 3030e8ff41aSMatthew Dillon } 3040e8ff41aSMatthew Dillon 3050e8ff41aSMatthew Dillon if (nfsv3_diskless.swap_nblks == 0 && size != -1) { 3060e8ff41aSMatthew Dillon nfsv3_diskless.swap_nblks = size / 1024; 307*086c1d7eSSascha Wildner kprintf("md_lookup_swap: Swap size is %d KB\n", 3080e8ff41aSMatthew Dillon nfsv3_diskless.swap_nblks); 3090e8ff41aSMatthew Dillon } 3100e8ff41aSMatthew Dillon 3110e8ff41aSMatthew Dillon goto out; 3120e8ff41aSMatthew Dillon 3130e8ff41aSMatthew Dillon bad: 3140e8ff41aSMatthew Dillon error = EBADRPC; 3150e8ff41aSMatthew Dillon 3160e8ff41aSMatthew Dillon out: 3170e8ff41aSMatthew Dillon m_freem(m); 3180e8ff41aSMatthew Dillon return error; 3190e8ff41aSMatthew Dillon } 3200e8ff41aSMatthew Dillon 3210e8ff41aSMatthew Dillon int 3220e8ff41aSMatthew Dillon setfs(struct sockaddr_in *addr, char *path, char *p) 3230e8ff41aSMatthew Dillon { 3240e8ff41aSMatthew Dillon unsigned int ip; 3250e8ff41aSMatthew Dillon int val; 3260e8ff41aSMatthew Dillon 3270e8ff41aSMatthew Dillon ip = 0; 3280e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3290e8ff41aSMatthew Dillon return 0; 3300e8ff41aSMatthew Dillon ip = val << 24; 3310e8ff41aSMatthew Dillon if (*p != '.') 3320e8ff41aSMatthew Dillon return 0; 3330e8ff41aSMatthew Dillon p++; 3340e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3350e8ff41aSMatthew Dillon return 0; 3360e8ff41aSMatthew Dillon ip |= (val << 16); 3370e8ff41aSMatthew Dillon if (*p != '.') 3380e8ff41aSMatthew Dillon return 0; 3390e8ff41aSMatthew Dillon p++; 3400e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3410e8ff41aSMatthew Dillon return 0; 3420e8ff41aSMatthew Dillon ip |= (val << 8); 3430e8ff41aSMatthew Dillon if (*p != '.') 3440e8ff41aSMatthew Dillon return 0; 3450e8ff41aSMatthew Dillon p++; 3460e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3470e8ff41aSMatthew Dillon return 0; 3480e8ff41aSMatthew Dillon ip |= val; 3490e8ff41aSMatthew Dillon if (*p != ':') 3500e8ff41aSMatthew Dillon return 0; 3510e8ff41aSMatthew Dillon p++; 3520e8ff41aSMatthew Dillon 3530e8ff41aSMatthew Dillon addr->sin_addr.s_addr = htonl(ip); 3540e8ff41aSMatthew Dillon addr->sin_len = sizeof(struct sockaddr_in); 3550e8ff41aSMatthew Dillon addr->sin_family = AF_INET; 3560e8ff41aSMatthew Dillon 3570e8ff41aSMatthew Dillon strncpy(path, p, MNAMELEN - 1); 3580e8ff41aSMatthew Dillon return 1; 3590e8ff41aSMatthew Dillon } 3600e8ff41aSMatthew Dillon 3610e8ff41aSMatthew Dillon static int 3620e8ff41aSMatthew Dillon getdec(char **ptr) 3630e8ff41aSMatthew Dillon { 3640e8ff41aSMatthew Dillon char *p; 3650e8ff41aSMatthew Dillon int ret; 3660e8ff41aSMatthew Dillon 3670e8ff41aSMatthew Dillon p = *ptr; 3680e8ff41aSMatthew Dillon ret = 0; 3690e8ff41aSMatthew Dillon if ((*p < '0') || (*p > '9')) 3700e8ff41aSMatthew Dillon return -1; 3710e8ff41aSMatthew Dillon while ((*p >= '0') && (*p <= '9')) { 3720e8ff41aSMatthew Dillon ret = ret * 10 + (*p - '0'); 3730e8ff41aSMatthew Dillon p++; 3740e8ff41aSMatthew Dillon } 3750e8ff41aSMatthew Dillon *ptr = p; 3760e8ff41aSMatthew Dillon return ret; 3770e8ff41aSMatthew Dillon } 3780e8ff41aSMatthew Dillon 3790e8ff41aSMatthew Dillon static char * 3800e8ff41aSMatthew Dillon substr(char *a, char *b) 3810e8ff41aSMatthew Dillon { 3820e8ff41aSMatthew Dillon char *loc1; 3830e8ff41aSMatthew Dillon char *loc2; 3840e8ff41aSMatthew Dillon 3850e8ff41aSMatthew Dillon while (*a != '\0') { 3860e8ff41aSMatthew Dillon loc1 = a; 3870e8ff41aSMatthew Dillon loc2 = b; 3880e8ff41aSMatthew Dillon while (*loc1 == *loc2++) { 3890e8ff41aSMatthew Dillon if (*loc1 == '\0') 3900e8ff41aSMatthew Dillon return 0; 3910e8ff41aSMatthew Dillon loc1++; 3920e8ff41aSMatthew Dillon if (*loc2 == '\0') 3930e8ff41aSMatthew Dillon return loc1; 3940e8ff41aSMatthew Dillon } 3950e8ff41aSMatthew Dillon a++; 3960e8ff41aSMatthew Dillon } 3970e8ff41aSMatthew Dillon return 0; 3980e8ff41aSMatthew Dillon } 3990e8ff41aSMatthew Dillon 4000e8ff41aSMatthew Dillon static int 4010e8ff41aSMatthew Dillon xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 4020e8ff41aSMatthew Dillon { 4030e8ff41aSMatthew Dillon struct mbuf *m; 4040e8ff41aSMatthew Dillon int alignedlen; 4050e8ff41aSMatthew Dillon 4060e8ff41aSMatthew Dillon m = *mptr; 4070e8ff41aSMatthew Dillon alignedlen = ( len + 3 ) & ~3; 4080e8ff41aSMatthew Dillon 4090e8ff41aSMatthew Dillon if (m->m_len < alignedlen) { 4100e8ff41aSMatthew Dillon m = m_pullup(m, alignedlen); 4110e8ff41aSMatthew Dillon if (m == NULL) { 4120e8ff41aSMatthew Dillon *mptr = NULL; 4130e8ff41aSMatthew Dillon return EBADRPC; 4140e8ff41aSMatthew Dillon } 4150e8ff41aSMatthew Dillon } 4160e8ff41aSMatthew Dillon bcopy(mtod(m, u_char *), buf, len); 4170e8ff41aSMatthew Dillon m_adj(m, alignedlen); 4180e8ff41aSMatthew Dillon *mptr = m; 4190e8ff41aSMatthew Dillon return 0; 4200e8ff41aSMatthew Dillon } 4210e8ff41aSMatthew Dillon 4220e8ff41aSMatthew Dillon static int 4230e8ff41aSMatthew Dillon xdr_int_decode(struct mbuf **mptr, int *iptr) 4240e8ff41aSMatthew Dillon { 4250e8ff41aSMatthew Dillon u_int32_t i; 4260e8ff41aSMatthew Dillon if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 4270e8ff41aSMatthew Dillon return EBADRPC; 4280e8ff41aSMatthew Dillon *iptr = fxdr_unsigned(u_int32_t, i); 4290e8ff41aSMatthew Dillon return 0; 4300e8ff41aSMatthew Dillon } 4310e8ff41aSMatthew Dillon 4320e8ff41aSMatthew Dillon #endif /* BOOTP && NFS_ROOT */ 4330e8ff41aSMatthew Dillon 434