getnfsargs_small.c revision 1.1 1 /* $NetBSD: getnfsargs_small.c,v 1.1 2006/01/21 10:32:23 dsl 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 * 3. Neither the name of The NetBSD Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: getnfsargs_small.c,v 1.1 2006/01/21 10:32:23 dsl Exp $");
37
38 #include <sys/param.h>
39 #include <sys/mount.h>
40 #include <sys/socket.h>
41 #include <sys/stat.h>
42 #include <syslog.h>
43
44 #include <nfs/rpcv2.h>
45 #include <nfs/nfsproto.h>
46 #include <nfs/nfs.h>
47 #include <nfs/nqnfs.h>
48 #include <nfs/nfsmount.h>
49
50 #include <arpa/inet.h>
51
52 #include <ctype.h>
53 #include <err.h>
54 #include <errno.h>
55 #include <fcntl.h>
56 #include <netdb.h>
57 #include <signal.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62 #include <util.h>
63
64 #include "mount_nfs.h"
65
66 #include "iodesc.h"
67 typedef int32_t n_long;
68 #include "rpc.h"
69
70 #define RPC_HEADER_WORDS 28 /* more than enough */
71 #define FNAME_SIZE 512
72
73 struct nfhret {
74 long fhsize;
75 u_char nfh[NFSX_V3FHMAX];
76 };
77
78 /* Ripped from src/sys/arch/i386/stand/libsa/nfs.c */
79 static int
80 nfs_getrootfh(struct iodesc *d, const char *path, int mntvers, struct nfhret *nfhret)
81 {
82 size_t len;
83 struct args {
84 uint32_t len;
85 char path[FNAME_SIZE];
86 } *args;
87 struct repl {
88 uint32_t errval;
89 u_char fh[NFSX_V3FHMAX];
90 } *repl;
91 struct {
92 uint32_t h[RPC_HEADER_WORDS];
93 struct args d;
94 } sdata;
95 struct {
96 uint32_t h[RPC_HEADER_WORDS];
97 struct repl d;
98 } rdata;
99 ssize_t cc;
100
101 args = &sdata.d;
102 repl = &rdata.d;
103
104 memset(args, 0, sizeof(*args));
105 len = strlen(path);
106 if (len > sizeof(args->path))
107 len = sizeof(args->path);
108 args->len = htonl(len);
109 memcpy(args->path, path, len);
110 len = 4 + roundup(len, 4);
111
112 cc = rpc_call(d, RPCPROG_MNT, mntvers, RPCMNT_MOUNT,
113 args, len, repl, sizeof(*repl));
114 if (cc == -1) {
115 /* errno was set by rpc_call */
116 return errno;
117 }
118 if (cc < 4)
119 return EBADRPC;
120 if (repl->errval)
121 return ntohl(repl->errval);
122 nfhret->fhsize = cc;
123 memcpy(nfhret->nfh, repl->fh, sizeof(repl->fh));
124 return 0;
125 }
126
127 int
128 getnfsargs(char *spec, struct nfs_args *nfsargsp)
129 {
130 struct addrinfo hints, *ai_nfs;
131 int ecode;
132 int nfsvers, mntvers;
133 char *hostp, *delimp;
134 static struct nfhret nfhret;
135 static char nam[MNAMELEN + 1];
136 struct iodesc d;
137 int nfs_port;
138
139 strncpy(nam, spec, MNAMELEN);
140 nam[MNAMELEN] = '\0';
141 if ((delimp = strchr(spec, '@')) != NULL) {
142 hostp = delimp + 1;
143 } else if ((delimp = strrchr(spec, ':')) != NULL) {
144 hostp = spec;
145 spec = delimp + 1;
146 } else {
147 warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
148 return 0;
149 }
150 *delimp = '\0';
151
152 memset(&hints, 0, sizeof hints);
153 hints.ai_socktype = nfsargsp->sotype;
154
155 if ((ecode = getaddrinfo(hostp, "nfs", &hints, &ai_nfs)) != 0) {
156 warnx("can't get net id for host \"%s\": %s", hostp,
157 gai_strerror(ecode));
158 return 0;
159 }
160
161 if (force2) {
162 nfsvers = NFS_VER2;
163 mntvers = RPCMNT_VER1;
164 } else {
165 nfsvers = NFS_VER3;
166 mntvers = RPCMNT_VER3;
167 }
168
169 d.socket = -1;
170 for (d.ai = ai_nfs; ; d.ai = d.ai->ai_next) {
171 if (d.ai == NULL) {
172 if (nfsvers == NFS_VER3 && !force3) {
173 nfsvers = NFS_VER2;
174 mntvers = RPCMNT_VER1;
175 d.ai = ai_nfs;
176 continue;
177 }
178 return 0;
179 }
180 nfs_port = rpc_getport(&d, RPCPROG_NFS, nfsvers);
181 if (nfs_port == -1)
182 continue;
183 if (nfs_getrootfh(&d, spec, mntvers, &nfhret) == 0)
184 break;
185 }
186
187 if (port != 0)
188 nfs_port = port;
189 set_port(d.ai->ai_addr, htons(nfs_port));
190
191 nfsargsp->hostname = nam;
192 nfsargsp->addr = d.ai->ai_addr;
193 nfsargsp->addrlen = d.ai->ai_addrlen;
194
195 nfsargsp->fh = nfhret.nfh;
196 if (nfsvers == NFS_VER3) {
197 nfsargsp->fhsize = ntohl(*(uint32_t *)nfhret.nfh);
198 nfsargsp->fh += 4;
199 } else {
200 nfsargsp->fhsize = 32; /* NFS_FHSIZE */
201 nfsargsp->flags &= ~NFSMNT_NFSV3;
202 }
203 return 1;
204 }
205