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