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