1/* $NetBSD: getnfsargs_small.c,v 1.8 2008/04/29 06:53:01 martin Exp $ */ 2 3/*- 4 * Copyright (c) 2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by David Laight. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/*- 33 * Copyright (c) 1993 John Brezak 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. The name of the author may not be used to endorse or promote products 45 * derived from this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 49 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 51 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 55 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 56 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 * POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60/* 61 * Copyright (c) 1992, 1993, 1994 62 * The Regents of the University of California. All rights reserved. 63 * 64 * This code is derived from software contributed to Berkeley by 65 * Rick Macklem at The University of Guelph. 66 * 67 * Redistribution and use in source and binary forms, with or without 68 * modification, are permitted provided that the following conditions 69 * are met: 70 * 1. Redistributions of source code must retain the above copyright 71 * notice, this list of conditions and the following disclaimer. 72 * 2. Redistributions in binary form must reproduce the above copyright 73 * notice, this list of conditions and the following disclaimer in the 74 * documentation and/or other materials provided with the distribution. 75 * 3. Neither the name of the University nor the names of its contributors 76 * may be used to endorse or promote products derived from this software 77 * without specific prior written permission. 78 * 79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 82 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 89 * SUCH DAMAGE. 90 */ 91 92#include <sys/cdefs.h> 93__RCSID("$NetBSD: getnfsargs_small.c,v 1.8 2008/04/29 06:53:01 martin Exp $"); 94 95#include <sys/param.h> 96#include <sys/mount.h> 97#include <sys/socket.h> 98#include <sys/stat.h> 99#include <syslog.h> 100 101#include <nfs/rpcv2.h> 102#include <nfs/nfsproto.h> 103#include <nfs/nfs.h> 104#include <nfs/nfsmount.h> 105 106#include <arpa/inet.h> 107 108#include <err.h> 109#include <errno.h> 110#include <fcntl.h> 111#include <netdb.h> 112#include <signal.h> 113#include <stdio.h> 114#include <stdlib.h> 115#include <string.h> 116#include <unistd.h> 117#include <util.h> 118 119#include "mount_nfs.h" 120 121#include "iodesc.h" 122typedef int32_t n_long; 123#include "rpc.h" 124 125#define RPC_HEADER_WORDS 28 /* more than enough */ 126#define FNAME_SIZE 512 127 128struct nfhret { 129 long fhsize; 130 u_char nfh[NFSX_V3FHMAX]; 131}; 132 133/* Ripped from src/sys/arch/i386/stand/libsa/nfs.c */ 134static int 135nfs_getrootfh(struct iodesc *d, const char *path, int mntvers, struct nfhret *nfhret) 136{ 137 size_t len; 138 struct args { 139 uint32_t len; 140 char path[FNAME_SIZE]; 141 } *args; 142 struct repl { 143 uint32_t errval; 144 u_char fh[NFSX_V3FHMAX]; 145 } *repl; 146 struct { 147 uint32_t h[RPC_HEADER_WORDS]; 148 struct args d; 149 } sdata; 150 struct { 151 uint32_t h[RPC_HEADER_WORDS]; 152 struct repl d; 153 } rdata; 154 ssize_t cc; 155 156 args = &sdata.d; 157 repl = &rdata.d; 158 159 memset(args, 0, sizeof(*args)); 160 len = strlen(path); 161 if (len > sizeof(args->path)) 162 len = sizeof(args->path); 163 args->len = htonl(len); 164 memcpy(args->path, path, len); 165 len = 4 + roundup(len, 4); 166 167 cc = rpc_call(d, RPCPROG_MNT, mntvers, RPCMNT_MOUNT, 168 args, len, repl, sizeof(*repl)); 169 if (cc == -1) { 170 /* errno was set by rpc_call */ 171 return errno; 172 } 173 if (cc < 4) 174 return EBADRPC; 175 if (repl->errval) 176 return ntohl(repl->errval); 177 nfhret->fhsize = cc; 178 memcpy(nfhret->nfh, repl->fh, sizeof(repl->fh)); 179 return 0; 180} 181 182int 183getnfsargs(char *spec, struct nfs_args *nfsargsp) 184{ 185 struct addrinfo hints, *ai_nfs; 186 int ecode; 187 int nfsvers, mntvers; 188 char *hostp, *delimp; 189 static struct nfhret nfhret; 190 static char nam[MNAMELEN + 1]; 191 struct iodesc d; 192 int nfs_port; 193 194 strlcpy(nam, spec, sizeof(nam)); 195 if ((delimp = strchr(spec, '@')) != NULL) { 196 hostp = delimp + 1; 197 } else if ((delimp = strrchr(spec, ':')) != NULL) { 198 hostp = spec; 199 spec = delimp + 1; 200 } else { 201 warnx("no <host>:<dirpath> or <dirpath>@<host> spec"); 202 return 0; 203 } 204 *delimp = '\0'; 205 206 memset(&hints, 0, sizeof hints); 207 hints.ai_socktype = nfsargsp->sotype; 208 209 if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) { 210 warnx("can't get net id for host \"%s\": %s", hostp, 211 gai_strerror(ecode)); 212 return 0; 213 } 214 215 if ((nfsargsp->flags & NFSMNT_NFSV3) != 0) { 216 nfsvers = NFS_VER3; 217 mntvers = RPCMNT_VER3; 218 } else { 219 nfsvers = NFS_VER2; 220 mntvers = RPCMNT_VER1; 221 } 222 223 d.socket = -1; 224 for (d.ai = ai_nfs; ; d.ai = d.ai->ai_next) { 225 if (d.ai == NULL) { 226 if (nfsvers == NFS_VER3 && !force3) { 227 nfsvers = NFS_VER2; 228 mntvers = RPCMNT_VER1; 229 d.ai = ai_nfs; 230 continue; 231 } 232 return 0; 233 } 234 nfs_port = rpc_getport(&d, RPCPROG_NFS, nfsvers); 235 if (nfs_port == -1) 236 continue; 237 if (nfs_getrootfh(&d, spec, mntvers, &nfhret) == 0) 238 break; 239 } 240 241 if (port != 0) 242 nfs_port = port; 243 set_port(d.ai->ai_addr, htons(nfs_port)); 244 245 nfsargsp->hostname = nam; 246 nfsargsp->addr = d.ai->ai_addr; 247 nfsargsp->addrlen = d.ai->ai_addrlen; 248 249 nfsargsp->fh = nfhret.nfh; 250 if (nfsvers == NFS_VER3) { 251 nfsargsp->fhsize = be32dec(nfhret.nfh); 252 nfsargsp->fh += sizeof(uint32_t); 253 } else { 254 nfsargsp->fhsize = NFSX_V2FH; 255 nfsargsp->flags &= ~NFSMNT_NFSV3; 256 } 257 return 1; 258} 259