dma: add DragonFly compat files
[dragonfly.git] / sys / vfs / nfs / nfs_mountrpc.c
blob233cbc93e92128a01dee1bec6510091962b01ded
1 /*
2 * Copyright (c) 1995 Gordon Ross, Adam Glass
3 * Copyright (c) 1992 Regents of the University of California.
4 * All rights reserved.
6 * This software was developed by the Computer Systems Engineering group
7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8 * contributed to Berkeley.
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. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Lawrence Berkeley Laboratory and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
38 * nfs/krpc_subr.c
39 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
40 * $FreeBSD: src/sys/nfs/bootp_subr.c,v 1.20.2.9 2003/04/24 16:51:08 ambrisko Exp $
41 * $DragonFly: src/sys/vfs/nfs/nfs_mountrpc.c,v 1.2 2006/12/23 00:41:29 swildner Exp $
44 * Procedures used by NFS_ROOT and BOOTP to do an NFS mount rpc to obtain
45 * the nfs root file handle for a NFS-based root mount point. This module
46 * is not used by normal operating code because the 'mount' command has a
47 * far more sophisticated implementation.
49 #include "opt_bootp.h"
50 #include "opt_nfsroot.h"
52 #if defined(BOOTP) || defined(NFS_ROOT)
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/sockio.h>
58 #include <sys/proc.h>
59 #include <sys/malloc.h>
60 #include <sys/mount.h>
61 #include <sys/mbuf.h>
62 #include <sys/socket.h>
63 #include <sys/socketvar.h>
64 #include <sys/sysctl.h>
65 #include <sys/uio.h>
67 #include <net/if.h>
68 #include <net/route.h>
70 #include <netinet/in.h>
71 #include <net/if_types.h>
72 #include <net/if_dl.h>
74 #include "rpcv2.h"
75 #include "nfsproto.h"
76 #include "nfs.h"
77 #include "nfsdiskless.h"
78 #include "krpc.h"
79 #include "xdr_subs.h"
80 #include "nfsmountrpc.h"
83 * What is the longest we will wait before re-sending a request?
84 * Note this is also the frequency of "RPC timeout" messages.
85 * The re-send loop count sup linearly to this maximum, so the
86 * first complaint will happen after (1+2+3+4+5)=15 seconds.
89 static int getdec(char **ptr);
90 static char *substr(char *a,char *b);
91 static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
92 static int xdr_int_decode(struct mbuf **ptr, int *iptr);
94 void
95 mountopts(struct nfs_args *args, char *p)
97 char *tmp;
99 args->version = NFS_ARGSVERSION;
100 args->rsize = 8192;
101 args->wsize = 8192;
102 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
103 args->sotype = SOCK_DGRAM;
104 if (p == NULL)
105 return;
106 if ((tmp = (char *)substr(p, "rsize=")))
107 args->rsize = getdec(&tmp);
108 if ((tmp = (char *)substr(p, "wsize=")))
109 args->wsize = getdec(&tmp);
110 if ((tmp = (char *)substr(p, "intr")))
111 args->flags |= NFSMNT_INT;
112 if ((tmp = (char *)substr(p, "soft")))
113 args->flags |= NFSMNT_SOFT;
114 if ((tmp = (char *)substr(p, "noconn")))
115 args->flags |= NFSMNT_NOCONN;
116 if ((tmp = (char *)substr(p, "tcp")))
117 args->sotype = SOCK_STREAM;
121 * RPC: mountd/mount
122 * Given a server pathname, get an NFS file handle.
123 * Also, sets sin->sin_port to the NFS service port.
126 md_mount(struct sockaddr_in *mdsin, /* mountd server address */
127 char *path,
128 u_char *fhp,
129 int *fhsizep,
130 struct nfs_args *args,
131 struct thread *td)
133 struct mbuf *m;
134 int error;
135 int authunixok;
136 int authcount;
137 int authver;
139 #ifdef BOOTP_NFSV3
140 /* First try NFS v3 */
141 /* Get port number for MOUNTD. */
142 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
143 &mdsin->sin_port, td);
144 if (error == 0) {
145 m = xdr_string_encode(path, strlen(path));
147 /* Do RPC to mountd. */
148 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
149 RPCMNT_MOUNT, &m, NULL, td);
151 if (error == 0) {
152 args->flags |= NFSMNT_NFSV3;
153 } else {
154 #endif
155 /* Fallback to NFS v2 */
157 /* Get port number for MOUNTD. */
158 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
159 &mdsin->sin_port, td);
160 if (error != 0)
161 return error;
163 m = xdr_string_encode(path, strlen(path));
165 /* Do RPC to mountd. */
166 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
167 RPCMNT_MOUNT, &m, NULL, td);
168 if (error != 0)
169 return error; /* message already freed */
171 #ifdef BOOTP_NFSV3
173 #endif
175 if (xdr_int_decode(&m, &error) != 0 || error != 0)
176 goto bad;
178 if ((args->flags & NFSMNT_NFSV3) != 0) {
179 if (xdr_int_decode(&m, fhsizep) != 0 ||
180 *fhsizep > NFSX_V3FHMAX ||
181 *fhsizep <= 0)
182 goto bad;
183 } else
184 *fhsizep = NFSX_V2FH;
186 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
187 goto bad;
189 if (args->flags & NFSMNT_NFSV3) {
190 if (xdr_int_decode(&m, &authcount) != 0)
191 goto bad;
192 authunixok = 0;
193 if (authcount < 0 || authcount > 100)
194 goto bad;
195 while (authcount > 0) {
196 if (xdr_int_decode(&m, &authver) != 0)
197 goto bad;
198 if (authver == RPCAUTH_UNIX)
199 authunixok = 1;
200 authcount--;
202 if (authunixok == 0)
203 goto bad;
206 /* Set port number for NFS use. */
207 error = krpc_portmap(mdsin, NFS_PROG,
208 (args->flags &
209 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
210 &mdsin->sin_port, td);
212 goto out;
214 bad:
215 error = EBADRPC;
217 out:
218 m_freem(m);
219 return error;
223 md_lookup_swap(struct sockaddr_in *mdsin, /* mountd server address */
224 char *path,
225 u_char *fhp,
226 int *fhsizep,
227 struct nfs_args *args,
228 struct thread *td)
230 struct mbuf *m;
231 int error;
232 int size = -1;
233 int attribs_present;
234 int status;
235 union {
236 u_int32_t v2[17];
237 u_int32_t v3[21];
238 } fattribs;
240 m = m_get(MB_WAIT,MT_DATA);
241 if (m == NULL)
242 return ENOBUFS;
244 if ((args->flags & NFSMNT_NFSV3) != 0) {
245 *mtod(m, u_int32_t *) = txdr_unsigned(*fhsizep);
246 bcopy(fhp, mtod(m, u_char *) + sizeof(u_int32_t), *fhsizep);
247 m->m_len = *fhsizep + sizeof(u_int32_t);
248 } else {
249 bcopy(fhp, mtod(m, u_char *), NFSX_V2FH);
250 m->m_len = NFSX_V2FH;
253 m->m_next = xdr_string_encode(path, strlen(path));
254 if (m->m_next == NULL) {
255 error = ENOBUFS;
256 goto out;
259 /* Do RPC to nfsd. */
260 if ((args->flags & NFSMNT_NFSV3) != 0)
261 error = krpc_call(mdsin, NFS_PROG, NFS_VER3,
262 NFSPROC_LOOKUP, &m, NULL, td);
263 else
264 error = krpc_call(mdsin, NFS_PROG, NFS_VER2,
265 NFSV2PROC_LOOKUP, &m, NULL, td);
266 if (error != 0)
267 return error; /* message already freed */
269 if (xdr_int_decode(&m, &status) != 0)
270 goto bad;
271 if (status != 0) {
272 error = ENOENT;
273 goto out;
276 if ((args->flags & NFSMNT_NFSV3) != 0) {
277 if (xdr_int_decode(&m, fhsizep) != 0 ||
278 *fhsizep > NFSX_V3FHMAX ||
279 *fhsizep <= 0)
280 goto bad;
281 } else
282 *fhsizep = NFSX_V2FH;
284 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
285 goto bad;
287 if ((args->flags & NFSMNT_NFSV3) != 0) {
288 if (xdr_int_decode(&m, &attribs_present) != 0)
289 goto bad;
290 if (attribs_present != 0) {
291 if (xdr_opaque_decode(&m, (u_char *) &fattribs.v3,
292 sizeof(u_int32_t) * 21) != 0)
293 goto bad;
294 size = fxdr_unsigned(u_int32_t, fattribs.v3[6]);
296 } else {
297 if (xdr_opaque_decode(&m,(u_char *) &fattribs.v2,
298 sizeof(u_int32_t) * 17) != 0)
299 goto bad;
300 size = fxdr_unsigned(u_int32_t, fattribs.v2[5]);
303 if (nfsv3_diskless.swap_nblks == 0 && size != -1) {
304 nfsv3_diskless.swap_nblks = size / 1024;
305 kprintf("md_lookup_swap: Swap size is %d KB\n",
306 nfsv3_diskless.swap_nblks);
309 goto out;
311 bad:
312 error = EBADRPC;
314 out:
315 m_freem(m);
316 return error;
320 setfs(struct sockaddr_in *addr, char *path, char *p)
322 unsigned int ip;
323 int val;
325 ip = 0;
326 if (((val = getdec(&p)) < 0) || (val > 255))
327 return 0;
328 ip = val << 24;
329 if (*p != '.')
330 return 0;
331 p++;
332 if (((val = getdec(&p)) < 0) || (val > 255))
333 return 0;
334 ip |= (val << 16);
335 if (*p != '.')
336 return 0;
337 p++;
338 if (((val = getdec(&p)) < 0) || (val > 255))
339 return 0;
340 ip |= (val << 8);
341 if (*p != '.')
342 return 0;
343 p++;
344 if (((val = getdec(&p)) < 0) || (val > 255))
345 return 0;
346 ip |= val;
347 if (*p != ':')
348 return 0;
349 p++;
351 addr->sin_addr.s_addr = htonl(ip);
352 addr->sin_len = sizeof(struct sockaddr_in);
353 addr->sin_family = AF_INET;
355 strncpy(path, p, MNAMELEN - 1);
356 return 1;
359 static int
360 getdec(char **ptr)
362 char *p;
363 int ret;
365 p = *ptr;
366 ret = 0;
367 if ((*p < '0') || (*p > '9'))
368 return -1;
369 while ((*p >= '0') && (*p <= '9')) {
370 ret = ret * 10 + (*p - '0');
371 p++;
373 *ptr = p;
374 return ret;
377 static char *
378 substr(char *a, char *b)
380 char *loc1;
381 char *loc2;
383 while (*a != '\0') {
384 loc1 = a;
385 loc2 = b;
386 while (*loc1 == *loc2++) {
387 if (*loc1 == '\0')
388 return 0;
389 loc1++;
390 if (*loc2 == '\0')
391 return loc1;
393 a++;
395 return 0;
398 static int
399 xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
401 struct mbuf *m;
402 int alignedlen;
404 m = *mptr;
405 alignedlen = ( len + 3 ) & ~3;
407 if (m->m_len < alignedlen) {
408 m = m_pullup(m, alignedlen);
409 if (m == NULL) {
410 *mptr = NULL;
411 return EBADRPC;
414 bcopy(mtod(m, u_char *), buf, len);
415 m_adj(m, alignedlen);
416 *mptr = m;
417 return 0;
420 static int
421 xdr_int_decode(struct mbuf **mptr, int *iptr)
423 u_int32_t i;
424 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
425 return EBADRPC;
426 *iptr = fxdr_unsigned(u_int32_t, i);
427 return 0;
430 #endif /* BOOTP && NFS_ROOT */