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 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; 105*39215f4cSSascha Wildner if ((tmp = substr(p, "rsize="))) 1060e8ff41aSMatthew Dillon args->rsize = getdec(&tmp); 107*39215f4cSSascha Wildner if ((tmp = substr(p, "wsize="))) 1080e8ff41aSMatthew Dillon args->wsize = getdec(&tmp); 109*39215f4cSSascha Wildner if ((tmp = substr(p, "intr"))) 1100e8ff41aSMatthew Dillon args->flags |= NFSMNT_INT; 111*39215f4cSSascha Wildner if ((tmp = substr(p, "soft"))) 1120e8ff41aSMatthew Dillon args->flags |= NFSMNT_SOFT; 113*39215f4cSSascha Wildner if ((tmp = substr(p, "noconn"))) 1140e8ff41aSMatthew Dillon args->flags |= NFSMNT_NOCONN; 115*39215f4cSSascha 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 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 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 2350e8ff41aSMatthew Dillon m = m_get(MB_WAIT,MT_DATA); 2360e8ff41aSMatthew Dillon if (m == NULL) 2370e8ff41aSMatthew Dillon return ENOBUFS; 2380e8ff41aSMatthew Dillon 2390e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2400e8ff41aSMatthew Dillon *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep); 2410e8ff41aSMatthew Dillon bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep); 2420e8ff41aSMatthew Dillon m->m_len = *fhsizep + sizeof(u_int32_t); 2430e8ff41aSMatthew Dillon } else { 2440e8ff41aSMatthew Dillon bcopy(fhp, mtod(m, u_char *), NFSX_V2FH); 2450e8ff41aSMatthew Dillon m->m_len = NFSX_V2FH; 2460e8ff41aSMatthew Dillon } 2470e8ff41aSMatthew Dillon 2480e8ff41aSMatthew Dillon m->m_next = xdr_string_encode(path, strlen(path)); 2490e8ff41aSMatthew Dillon if (m->m_next == NULL) { 2500e8ff41aSMatthew Dillon error = ENOBUFS; 2510e8ff41aSMatthew Dillon goto out; 2520e8ff41aSMatthew Dillon } 2530e8ff41aSMatthew Dillon 2540e8ff41aSMatthew Dillon /* Do RPC to nfsd. */ 2550e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) 2560e8ff41aSMatthew Dillon error = krpc_call(mdsin, NFS_PROG, NFS_VER3, 2570e8ff41aSMatthew Dillon NFSPROC_LOOKUP, &m, NULL, td); 2580e8ff41aSMatthew Dillon else 2590e8ff41aSMatthew Dillon error = krpc_call(mdsin, NFS_PROG, NFS_VER2, 2600e8ff41aSMatthew Dillon NFSV2PROC_LOOKUP, &m, NULL, td); 2610e8ff41aSMatthew Dillon if (error != 0) 2620e8ff41aSMatthew Dillon return error; /* message already freed */ 2630e8ff41aSMatthew Dillon 2640e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &status) != 0) 2650e8ff41aSMatthew Dillon goto bad; 2660e8ff41aSMatthew Dillon if (status != 0) { 2670e8ff41aSMatthew Dillon error = ENOENT; 2680e8ff41aSMatthew Dillon goto out; 2690e8ff41aSMatthew Dillon } 2700e8ff41aSMatthew Dillon 2710e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2720e8ff41aSMatthew Dillon if (xdr_int_decode(&m, fhsizep) != 0 || 2730e8ff41aSMatthew Dillon *fhsizep > NFSX_V3FHMAX || 2740e8ff41aSMatthew Dillon *fhsizep <= 0) 2750e8ff41aSMatthew Dillon goto bad; 2760e8ff41aSMatthew Dillon } else 2770e8ff41aSMatthew Dillon *fhsizep = NFSX_V2FH; 2780e8ff41aSMatthew Dillon 2790e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0) 2800e8ff41aSMatthew Dillon goto bad; 2810e8ff41aSMatthew Dillon 2820e8ff41aSMatthew Dillon if ((args->flags & NFSMNT_NFSV3) != 0) { 2830e8ff41aSMatthew Dillon if (xdr_int_decode(&m, &attribs_present) != 0) 2840e8ff41aSMatthew Dillon goto bad; 2850e8ff41aSMatthew Dillon if (attribs_present != 0) { 2860e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3, 2870e8ff41aSMatthew Dillon sizeof(u_int32_t) * 21) != 0) 2880e8ff41aSMatthew Dillon goto bad; 2890e8ff41aSMatthew Dillon size = fxdr_unsigned(u_int32_t, fattribs.v3[6]); 2900e8ff41aSMatthew Dillon } 2910e8ff41aSMatthew Dillon } else { 2920e8ff41aSMatthew Dillon if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2, 2930e8ff41aSMatthew Dillon sizeof(u_int32_t) * 17) != 0) 2940e8ff41aSMatthew Dillon goto bad; 2950e8ff41aSMatthew Dillon size = fxdr_unsigned(u_int32_t, fattribs.v2[5]); 2960e8ff41aSMatthew Dillon } 2970e8ff41aSMatthew Dillon 2980e8ff41aSMatthew Dillon if (nfsv3_diskless.swap_nblks == 0 && size != -1) { 2990e8ff41aSMatthew Dillon nfsv3_diskless.swap_nblks = size / 1024; 300086c1d7eSSascha Wildner kprintf("md_lookup_swap: Swap size is %d KB\n", 3010e8ff41aSMatthew Dillon nfsv3_diskless.swap_nblks); 3020e8ff41aSMatthew Dillon } 3030e8ff41aSMatthew Dillon 3040e8ff41aSMatthew Dillon goto out; 3050e8ff41aSMatthew Dillon 3060e8ff41aSMatthew Dillon bad: 3070e8ff41aSMatthew Dillon error = EBADRPC; 3080e8ff41aSMatthew Dillon 3090e8ff41aSMatthew Dillon out: 3100e8ff41aSMatthew Dillon m_freem(m); 3110e8ff41aSMatthew Dillon return error; 3120e8ff41aSMatthew Dillon } 3130e8ff41aSMatthew Dillon 3140e8ff41aSMatthew Dillon int 3150e8ff41aSMatthew Dillon setfs(struct sockaddr_in *addr, char *path, char *p) 3160e8ff41aSMatthew Dillon { 3170e8ff41aSMatthew Dillon unsigned int ip; 3180e8ff41aSMatthew Dillon int val; 3190e8ff41aSMatthew Dillon 3200e8ff41aSMatthew Dillon ip = 0; 3210e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3220e8ff41aSMatthew Dillon return 0; 3230e8ff41aSMatthew Dillon ip = val << 24; 3240e8ff41aSMatthew Dillon if (*p != '.') 3250e8ff41aSMatthew Dillon return 0; 3260e8ff41aSMatthew Dillon p++; 3270e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3280e8ff41aSMatthew Dillon return 0; 3290e8ff41aSMatthew Dillon ip |= (val << 16); 3300e8ff41aSMatthew Dillon if (*p != '.') 3310e8ff41aSMatthew Dillon return 0; 3320e8ff41aSMatthew Dillon p++; 3330e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3340e8ff41aSMatthew Dillon return 0; 3350e8ff41aSMatthew Dillon ip |= (val << 8); 3360e8ff41aSMatthew Dillon if (*p != '.') 3370e8ff41aSMatthew Dillon return 0; 3380e8ff41aSMatthew Dillon p++; 3390e8ff41aSMatthew Dillon if (((val = getdec(&p)) < 0) || (val > 255)) 3400e8ff41aSMatthew Dillon return 0; 3410e8ff41aSMatthew Dillon ip |= val; 3420e8ff41aSMatthew Dillon if (*p != ':') 3430e8ff41aSMatthew Dillon return 0; 3440e8ff41aSMatthew Dillon p++; 3450e8ff41aSMatthew Dillon 3460e8ff41aSMatthew Dillon addr->sin_addr.s_addr = htonl(ip); 3470e8ff41aSMatthew Dillon addr->sin_len = sizeof(struct sockaddr_in); 3480e8ff41aSMatthew Dillon addr->sin_family = AF_INET; 3490e8ff41aSMatthew Dillon 3500e8ff41aSMatthew Dillon strncpy(path, p, MNAMELEN - 1); 3510e8ff41aSMatthew Dillon return 1; 3520e8ff41aSMatthew Dillon } 3530e8ff41aSMatthew Dillon 3540e8ff41aSMatthew Dillon static int 3550e8ff41aSMatthew Dillon getdec(char **ptr) 3560e8ff41aSMatthew Dillon { 3570e8ff41aSMatthew Dillon char *p; 3580e8ff41aSMatthew Dillon int ret; 3590e8ff41aSMatthew Dillon 3600e8ff41aSMatthew Dillon p = *ptr; 3610e8ff41aSMatthew Dillon ret = 0; 3620e8ff41aSMatthew Dillon if ((*p < '0') || (*p > '9')) 3630e8ff41aSMatthew Dillon return -1; 3640e8ff41aSMatthew Dillon while ((*p >= '0') && (*p <= '9')) { 3650e8ff41aSMatthew Dillon ret = ret * 10 + (*p - '0'); 3660e8ff41aSMatthew Dillon p++; 3670e8ff41aSMatthew Dillon } 3680e8ff41aSMatthew Dillon *ptr = p; 3690e8ff41aSMatthew Dillon return ret; 3700e8ff41aSMatthew Dillon } 3710e8ff41aSMatthew Dillon 3720e8ff41aSMatthew Dillon static char * 3730e8ff41aSMatthew Dillon substr(char *a, char *b) 3740e8ff41aSMatthew Dillon { 3750e8ff41aSMatthew Dillon char *loc1; 3760e8ff41aSMatthew Dillon char *loc2; 3770e8ff41aSMatthew Dillon 3780e8ff41aSMatthew Dillon while (*a != '\0') { 3790e8ff41aSMatthew Dillon loc1 = a; 3800e8ff41aSMatthew Dillon loc2 = b; 3810e8ff41aSMatthew Dillon while (*loc1 == *loc2++) { 3820e8ff41aSMatthew Dillon if (*loc1 == '\0') 3830e8ff41aSMatthew Dillon return 0; 3840e8ff41aSMatthew Dillon loc1++; 3850e8ff41aSMatthew Dillon if (*loc2 == '\0') 3860e8ff41aSMatthew Dillon return loc1; 3870e8ff41aSMatthew Dillon } 3880e8ff41aSMatthew Dillon a++; 3890e8ff41aSMatthew Dillon } 3900e8ff41aSMatthew Dillon return 0; 3910e8ff41aSMatthew Dillon } 3920e8ff41aSMatthew Dillon 3930e8ff41aSMatthew Dillon static int 3940e8ff41aSMatthew Dillon xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len) 3950e8ff41aSMatthew Dillon { 3960e8ff41aSMatthew Dillon struct mbuf *m; 3970e8ff41aSMatthew Dillon int alignedlen; 3980e8ff41aSMatthew Dillon 3990e8ff41aSMatthew Dillon m = *mptr; 4000e8ff41aSMatthew Dillon alignedlen = ( len + 3 ) & ~3; 4010e8ff41aSMatthew Dillon 4020e8ff41aSMatthew Dillon if (m->m_len < alignedlen) { 4030e8ff41aSMatthew Dillon m = m_pullup(m, alignedlen); 4040e8ff41aSMatthew Dillon if (m == NULL) { 4050e8ff41aSMatthew Dillon *mptr = NULL; 4060e8ff41aSMatthew Dillon return EBADRPC; 4070e8ff41aSMatthew Dillon } 4080e8ff41aSMatthew Dillon } 4090e8ff41aSMatthew Dillon bcopy(mtod(m, u_char *), buf, len); 4100e8ff41aSMatthew Dillon m_adj(m, alignedlen); 4110e8ff41aSMatthew Dillon *mptr = m; 4120e8ff41aSMatthew Dillon return 0; 4130e8ff41aSMatthew Dillon } 4140e8ff41aSMatthew Dillon 4150e8ff41aSMatthew Dillon static int 4160e8ff41aSMatthew Dillon xdr_int_decode(struct mbuf **mptr, int *iptr) 4170e8ff41aSMatthew Dillon { 4180e8ff41aSMatthew Dillon u_int32_t i; 4190e8ff41aSMatthew Dillon if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0) 4200e8ff41aSMatthew Dillon return EBADRPC; 4210e8ff41aSMatthew Dillon *iptr = fxdr_unsigned(u_int32_t, i); 4220e8ff41aSMatthew Dillon return 0; 4230e8ff41aSMatthew Dillon } 4240e8ff41aSMatthew Dillon 4250e8ff41aSMatthew Dillon #endif /* BOOTP && NFS_ROOT */ 4260e8ff41aSMatthew Dillon 427