Deleted Added
full compact
1/*
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1992, 1993, 1994\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44/*
45static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95";
46*/
47static const char rcsid[] =
48 "$Id: mount_nfs.c,v 1.18 1997/03/29 03:32:39 imp Exp $";
48 "$Id: mount_nfs.c,v 1.19 1997/04/01 17:20:17 guido Exp $";
49#endif /* not lint */
50
51#include <sys/param.h>
52#include <sys/mount.h>
53#include <sys/socket.h>
54#include <sys/socketvar.h>
55#include <sys/stat.h>
56#include <sys/syslog.h>
57
58#include <rpc/rpc.h>
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61
62#ifdef ISO
63#include <netiso/iso.h>
64#endif
65
66#ifdef NFSKERB
67#include <kerberosIV/des.h>
68#include <kerberosIV/krb.h>
69#endif
70
71#include <nfs/rpcv2.h>
72#include <nfs/nfsproto.h>
73#define KERNEL
74#include <nfs/nfs.h>
75#undef KERNEL
76#include <nfs/nqnfs.h>
77
78#include <arpa/inet.h>
79
80#include <ctype.h>
81#include <err.h>
82#include <errno.h>
83#include <fcntl.h>
84#include <netdb.h>
85#include <signal.h>
86#include <stdio.h>
87#include <stdlib.h>
88#include <strings.h>
89#include <sysexits.h>
90#include <unistd.h>
91
92#include "mntopts.h"
93
94#define ALTF_BG 0x1
95#define ALTF_NOCONN 0x2
96#define ALTF_DUMBTIMR 0x4
97#define ALTF_INTR 0x8
98#define ALTF_KERB 0x10
99#define ALTF_NFSV3 0x20
100#define ALTF_RDIRPLUS 0x40
101#define ALTF_MNTUDP 0x80
102#define ALTF_RESVPORT 0x100
103#define ALTF_SEQPACKET 0x200
104#define ALTF_NQNFS 0x400
105#define ALTF_SOFT 0x800
106#define ALTF_TCP 0x1000
107#define ALTF_PORT 0x2000
108
109struct mntopt mopts[] = {
110 MOPT_STDOPTS,
111 MOPT_FORCE,
112 MOPT_UPDATE,
113 { "bg", 0, ALTF_BG, 1 },
114 { "conn", 1, ALTF_NOCONN, 1 },
115 { "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
116 { "intr", 0, ALTF_INTR, 1 },
117#ifdef NFSKERB
118 { "kerb", 0, ALTF_KERB, 1 },
119#endif
120 { "nfsv3", 0, ALTF_NFSV3, 1 },
121 { "rdirplus", 0, ALTF_RDIRPLUS, 1 },
122 { "mntudp", 0, ALTF_MNTUDP, 1 },
123 { "resvport", 0, ALTF_RESVPORT, 1 },
124#ifdef ISO
125 { "seqpacket", 0, ALTF_SEQPACKET, 1 },
126#endif
127 { "nqnfs", 0, ALTF_NQNFS, 1 },
128 { "soft", 0, ALTF_SOFT, 1 },
129 { "tcp", 0, ALTF_TCP, 1 },
130 { "port=", 0, ALTF_PORT, 1 },
131 { NULL }
132};
133
134struct nfs_args nfsdefargs = {
135 NFS_ARGSVERSION,
136 (struct sockaddr *)0,
137 sizeof (struct sockaddr_in),
138 SOCK_DGRAM,
139 0,
140 (u_char *)0,
141 0,
142 NFSMNT_RESVPORT,
143 NFS_WSIZE,
144 NFS_RSIZE,
145 NFS_READDIRSIZE,
146 10,
147 NFS_RETRANS,
148 NFS_MAXGRPS,
149 NFS_DEFRAHEAD,
150 NQ_DEFLEASE,
151 NQ_DEADTHRESH,
152 (char *)0,
153};
154
155struct nfhret {
156 u_long stat;
157 long vers;
158 long auth;
159 long fhsize;
160 u_char nfh[NFSX_V3FHMAX];
161};
162#define DEF_RETRY 10000
163#define BGRND 1
164#define ISBGRND 2
165int retrycnt = DEF_RETRY;
166int opflags = 0;
167int nfsproto = IPPROTO_UDP;
168int mnttcp_ok = 1;
169u_short port_no = 0;
170
171#ifdef NFSKERB
172char inst[INST_SZ];
173char realm[REALM_SZ];
174struct {
175 u_long kind;
176 KTEXT_ST kt;
177} ktick;
178struct nfsrpc_nickverf kverf;
179struct nfsrpc_fullblock kin, kout;
180NFSKERBKEY_T kivec;
181CREDENTIALS kcr;
182struct timeval ktv;
183NFSKERBKEYSCHED_T kerb_keysched;
184#endif
185
186int getnfsargs __P((char *, struct nfs_args *));
187#ifdef ISO
188struct iso_addr *iso_addr __P((const char *));
189#endif
190void set_rpc_maxgrouplist __P((int));
191void usage __P((void)) __dead2;
192int xdr_dir __P((XDR *, char *));
193int xdr_fh __P((XDR *, struct nfhret *));
194
195/*
196 * Used to set mount flags with getmntopts. Call with dir=TRUE to
197 * initialise altflags from the current mount flags. Call with
198 * dir=FALSE to update mount flags with the new value of altflags after
199 * the call to getmntopts.
200 */
201static void
202setflags(int* altflags, int* nfsflags, int dir)
203{
204#define F2(af, nf) \
205 if (dir) { \
206 if (*nfsflags & NFSMNT_##nf) \
207 *altflags |= ALTF_##af; \
208 else \
209 *altflags &= ~ALTF_##af; \
210 } else { \
211 if (*altflags & ALTF_##af) \
212 *nfsflags |= NFSMNT_##nf; \
213 else \
214 *nfsflags &= ~NFSMNT_##nf; \
215 }
216#define F(f) F2(f,f)
217
218 F(NOCONN);
219 F(DUMBTIMR);
220 F2(INTR, INT);
221#ifdef NFSKERB
222 F(KERB);
223#endif
224 F(NFSV3);
225 F(RDIRPLUS);
226 F(RESVPORT);
227 F(NQNFS);
228 F(SOFT);
229
230#undef F
231#undef F2
232}
233
234int
235main(argc, argv)
236 int argc;
237 char *argv[];
238{
239 register int c;
240 register struct nfs_args *nfsargsp;
241 struct nfs_args nfsargs;
242 struct nfsd_cargs ncd;
243 int mntflags, altflags, i, nfssvc_flag, num;
244 char *name, *p, *spec;
245 struct vfsconf vfc;
246 int error = 0;
247#ifdef NFSKERB
248 uid_t last_ruid;
249
250 last_ruid = -1;
251 (void)strcpy(realm, KRB_REALM);
252 if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
253 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
254 ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
255 ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
256 fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
257#endif /* NFSKERB */
258 retrycnt = DEF_RETRY;
259
260 mntflags = 0;
261 altflags = 0;
262 nfsargs = nfsdefargs;
263 nfsargsp = &nfsargs;
264 while ((c = getopt(argc, argv,
265 "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != -1)
266 switch (c) {
267 case '3':
268 nfsargsp->flags |= NFSMNT_NFSV3;
269 break;
270 case 'a':
271 num = strtol(optarg, &p, 10);
272 if (*p || num < 0)
273 errx(1, "illegal -a value -- %s", optarg);
274 nfsargsp->readahead = num;
275 nfsargsp->flags |= NFSMNT_READAHEAD;
276 break;
277 case 'b':
278 opflags |= BGRND;
279 break;
280 case 'c':
281 nfsargsp->flags |= NFSMNT_NOCONN;
282 break;
283 case 'D':
284 num = strtol(optarg, &p, 10);
285 if (*p || num <= 0)
286 errx(1, "illegal -D value -- %s", optarg);
287 nfsargsp->deadthresh = num;
288 nfsargsp->flags |= NFSMNT_DEADTHRESH;
289 break;
290 case 'd':
291 nfsargsp->flags |= NFSMNT_DUMBTIMR;
292 break;
293 case 'g':
294 num = strtol(optarg, &p, 10);
295 if (*p || num <= 0)
296 errx(1, "illegal -g value -- %s", optarg);
297#ifdef __FreeBSD__
298 set_rpc_maxgrouplist(num);
299#endif
300 nfsargsp->maxgrouplist = num;
301 nfsargsp->flags |= NFSMNT_MAXGRPS;
302 break;
303 case 'I':
304 num = strtol(optarg, &p, 10);
305 if (*p || num <= 0)
306 errx(1, "illegal -I value -- %s", optarg);
307 nfsargsp->readdirsize = num;
308 nfsargsp->flags |= NFSMNT_READDIRSIZE;
309 break;
310 case 'i':
311 nfsargsp->flags |= NFSMNT_INT;
312 break;
313#ifdef NFSKERB
314 case 'K':
315 nfsargsp->flags |= NFSMNT_KERB;
316 break;
317#endif
318 case 'L':
319 num = strtol(optarg, &p, 10);
320 if (*p || num < 2)
321 errx(1, "illegal -L value -- %s", optarg);
322 nfsargsp->leaseterm = num;
323 nfsargsp->flags |= NFSMNT_LEASETERM;
324 break;
325 case 'l':
326 nfsargsp->flags |= NFSMNT_RDIRPLUS;
327 break;
328#ifdef NFSKERB
329 case 'm':
330 (void)strncpy(realm, optarg, REALM_SZ - 1);
331 realm[REALM_SZ - 1] = '\0';
332 break;
333#endif
334 case 'o':
335 altflags = 0;
336 setflags(&altflags, &nfsargsp->flags, TRUE);
337 getmntopts(optarg, mopts, &mntflags, &altflags);
338 setflags(&altflags, &nfsargsp->flags, FALSE);
339 /*
340 * Handle altflags which don't map directly to
341 * mount flags.
342 */
343 if(altflags & ALTF_BG)
344 opflags |= BGRND;
299 if(altflags & ALTF_NOCONN)
300 nfsargsp->flags |= NFSMNT_NOCONN;
301 if(altflags & ALTF_DUMBTIMR)
302 nfsargsp->flags |= NFSMNT_DUMBTIMR;
303 if(altflags & ALTF_INTR)
304 nfsargsp->flags |= NFSMNT_INT;
305#ifdef NFSKERB
306 if(altflags & ALTF_KERB)
307 nfsargsp->flags |= NFSMNT_KERB;
308#endif
309 if(altflags & ALTF_NFSV3)
310 nfsargsp->flags |= NFSMNT_NFSV3;
311 if(altflags & ALTF_RDIRPLUS)
312 nfsargsp->flags |= NFSMNT_RDIRPLUS;
345 if(altflags & ALTF_MNTUDP)
346 mnttcp_ok = 0;
315 if(altflags & ALTF_RESVPORT)
316 nfsargsp->flags |= NFSMNT_RESVPORT;
347#ifdef ISO
348 if(altflags & ALTF_SEQPACKET)
349 nfsargsp->sotype = SOCK_SEQPACKET;
350#endif
321 if(altflags & ALTF_NQNFS)
322 nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
323 if(altflags & ALTF_SOFT)
324 nfsargsp->flags |= NFSMNT_SOFT;
351 if(altflags & ALTF_TCP) {
352 nfsargsp->sotype = SOCK_STREAM;
353 nfsproto = IPPROTO_TCP;
354 }
355 if(altflags & ALTF_PORT)
356 port_no = atoi(strstr(optarg, "port=") + 5);
331 altflags = 0;
357 break;
358 case 'P':
359 nfsargsp->flags |= NFSMNT_RESVPORT;
360 break;
361#ifdef ISO
362 case 'p':
363 nfsargsp->sotype = SOCK_SEQPACKET;
364 break;
365#endif
366 case 'q':
367 nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
368 break;
369 case 'R':
370 num = strtol(optarg, &p, 10);
371 if (*p || num <= 0)
372 errx(1, "illegal -R value -- %s", optarg);
373 retrycnt = num;
374 break;
375 case 'r':
376 num = strtol(optarg, &p, 10);
377 if (*p || num <= 0)
378 errx(1, "illegal -r value -- %s", optarg);
379 nfsargsp->rsize = num;
380 nfsargsp->flags |= NFSMNT_RSIZE;
381 break;
382 case 's':
383 nfsargsp->flags |= NFSMNT_SOFT;
384 break;
385 case 'T':
386 nfsargsp->sotype = SOCK_STREAM;
387 nfsproto = IPPROTO_TCP;
388 break;
389 case 't':
390 num = strtol(optarg, &p, 10);
391 if (*p || num <= 0)
392 errx(1, "illegal -t value -- %s", optarg);
393 nfsargsp->timeo = num;
394 nfsargsp->flags |= NFSMNT_TIMEO;
395 break;
396 case 'w':
397 num = strtol(optarg, &p, 10);
398 if (*p || num <= 0)
399 errx(1, "illegal -w value -- %s", optarg);
400 nfsargsp->wsize = num;
401 nfsargsp->flags |= NFSMNT_WSIZE;
402 break;
403 case 'x':
404 num = strtol(optarg, &p, 10);
405 if (*p || num <= 0)
406 errx(1, "illegal -x value -- %s", optarg);
407 nfsargsp->retrans = num;
408 nfsargsp->flags |= NFSMNT_RETRANS;
409 break;
410 case 'U':
411 mnttcp_ok = 0;
412 break;
413 default:
414 usage();
415 break;
416 }
417 argc -= optind;
418 argv += optind;
419
420 if (argc != 2) {
421 usage();
422 /* NOTREACHED */
423 }
424
425 spec = *argv++;
426 name = *argv;
427
428 if (!getnfsargs(spec, nfsargsp))
429 exit(1);
430
431#ifdef __FreeBSD__
432 error = getvfsbyname("nfs", &vfc);
433 if (error && vfsisloadable("nfs")) {
434 if(vfsload("nfs"))
435 err(EX_OSERR, "vfsload(nfs)");
436 endvfsent(); /* clear cache */
437 error = getvfsbyname("nfs", &vfc);
438 }
439 if (error)
440 errx(EX_OSERR, "nfs filesystem is not available");
441
442 if (mount(vfc.vfc_name, name, mntflags, nfsargsp))
443 err(1, "%s", name);
444#else
445 if (mount("nfs", name, mntflags, nfsargsp))
446 err(1, "%s", name);
447#endif
448 if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
449 if ((opflags & ISBGRND) == 0) {
450 if (i = fork()) {
451 if (i == -1)
452 err(1, "nqnfs 1");
453 exit(0);
454 }
455 (void) setsid();
456 (void) close(STDIN_FILENO);
457 (void) close(STDOUT_FILENO);
458 (void) close(STDERR_FILENO);
459 (void) chdir("/");
460 }
461 openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
462 nfssvc_flag = NFSSVC_MNTD;
463 ncd.ncd_dirp = name;
464 while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
465 if (errno != ENEEDAUTH) {
466 syslog(LOG_ERR, "nfssvc err %m");
467 continue;
468 }
469 nfssvc_flag =
470 NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
471#ifdef NFSKERB
472 /*
473 * Set up as ncd_authuid for the kerberos call.
474 * Must set ruid to ncd_authuid and reset the
475 * ticket name iff ncd_authuid is not the same
476 * as last time, so that the right ticket file
477 * is found.
478 * Get the Kerberos credential structure so that
479 * we have the seesion key and get a ticket for
480 * this uid.
481 * For more info see the IETF Draft "Authentication
482 * in ONC RPC".
483 */
484 if (ncd.ncd_authuid != last_ruid) {
485 char buf[512];
486 (void)sprintf(buf, "%s%d",
487 TKT_ROOT, ncd.ncd_authuid);
488 krb_set_tkt_string(buf);
489 last_ruid = ncd.ncd_authuid;
490 }
491 setreuid(ncd.ncd_authuid, 0);
492 kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
493 if (kret == RET_NOTKT) {
494 kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
495 DEFAULT_TKT_LIFE);
496 if (kret == KSUCCESS)
497 kret = krb_get_cred(NFS_KERBSRV, inst, realm,
498 &kcr);
499 }
500 if (kret == KSUCCESS)
501 kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
502 realm, 0);
503
504 /*
505 * Fill in the AKN_FULLNAME authenticator and verfier.
506 * Along with the Kerberos ticket, we need to build
507 * the timestamp verifier and encrypt it in CBC mode.
508 */
509 if (kret == KSUCCESS &&
510 ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
511 && gettimeofday(&ktv, (struct timezone *)0) == 0) {
512 ncd.ncd_authtype = RPCAUTH_KERB4;
513 ncd.ncd_authstr = (u_char *)&ktick;
514 ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
515 3 * NFSX_UNSIGNED;
516 ncd.ncd_verfstr = (u_char *)&kverf;
517 ncd.ncd_verflen = sizeof (kverf);
518 memmove(ncd.ncd_key, kcr.session,
519 sizeof (kcr.session));
520 kin.t1 = htonl(ktv.tv_sec);
521 kin.t2 = htonl(ktv.tv_usec);
522 kin.w1 = htonl(NFS_KERBTTL);
523 kin.w2 = htonl(NFS_KERBTTL - 1);
524 bzero((caddr_t)kivec, sizeof (kivec));
525
526 /*
527 * Encrypt kin in CBC mode using the session
528 * key in kcr.
529 */
530 XXX
531
532 /*
533 * Finally, fill the timestamp verifier into the
534 * authenticator and verifier.
535 */
536 ktick.kind = htonl(RPCAKN_FULLNAME);
537 kverf.kind = htonl(RPCAKN_FULLNAME);
538 NFS_KERBW1(ktick.kt) = kout.w1;
539 ktick.kt.length = htonl(ktick.kt.length);
540 kverf.verf.t1 = kout.t1;
541 kverf.verf.t2 = kout.t2;
542 kverf.verf.w2 = kout.w2;
543 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
544 }
545 setreuid(0, 0);
546#endif /* NFSKERB */
547 }
548 }
549 exit(0);
550}
551
552int
553getnfsargs(spec, nfsargsp)
554 char *spec;
555 struct nfs_args *nfsargsp;
556{
557 register CLIENT *clp;
558 struct hostent *hp;
559 static struct sockaddr_in saddr;
560#ifdef ISO
561 static struct sockaddr_iso isoaddr;
562 struct iso_addr *isop;
563 int isoflag = 0;
564#endif
565 struct timeval pertry, try;
566 enum clnt_stat clnt_stat;
567 int so = RPC_ANYSOCK, i, nfsvers, mntvers;
568 char *hostp, *delimp;
569#ifdef NFSKERB
570 char *cp;
571#endif
572 u_short tport;
573 static struct nfhret nfhret;
574 static char nam[MNAMELEN + 1];
575
576 strncpy(nam, spec, MNAMELEN);
577 nam[MNAMELEN] = '\0';
578 if ((delimp = strchr(spec, '@')) != NULL) {
579 hostp = delimp + 1;
580 } else if ((delimp = strchr(spec, ':')) != NULL) {
581 hostp = spec;
582 spec = delimp + 1;
583 } else {
584 warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
585 return (0);
586 }
587 *delimp = '\0';
588 /*
589 * DUMB!! Until the mount protocol works on iso transport, we must
590 * supply both an iso and an inet address for the host.
591 */
592#ifdef ISO
593 if (!strncmp(hostp, "iso=", 4)) {
594 u_short isoport;
595
596 hostp += 4;
597 isoflag++;
598 if ((delimp = strchr(hostp, '+')) == NULL) {
599 warnx("no iso+inet address");
600 return (0);
601 }
602 *delimp = '\0';
603 if ((isop = iso_addr(hostp)) == NULL) {
604 warnx("bad ISO address");
605 return (0);
606 }
607 memset(&isoaddr, 0, sizeof (isoaddr));
608 memmove(&isoaddr.siso_addr, isop, sizeof (struct iso_addr));
609 isoaddr.siso_len = sizeof (isoaddr);
610 isoaddr.siso_family = AF_ISO;
611 isoaddr.siso_tlen = 2;
612 isoport = htons(NFS_PORT);
613 memmove(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen);
614 hostp = delimp + 1;
615 }
616#endif /* ISO */
617
618 /*
619 * Handle an internet host address and reverse resolve it if
620 * doing Kerberos.
621 */
622 if (isdigit(*hostp)) {
623 if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
624 warnx("bad net address %s", hostp);
625 return (0);
626 }
627 } else if ((hp = gethostbyname(hostp)) != NULL)
628 memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
629 else {
630 warnx("can't get net id for host");
631 return (0);
632 }
633#ifdef NFSKERB
634 if ((nfsargsp->flags & NFSMNT_KERB)) {
635 if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
636 sizeof (u_long), AF_INET)) == (struct hostent *)0) {
637 warnx("can't reverse resolve net address");
638 return (0);
639 }
640 memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
641 strncpy(inst, hp->h_name, INST_SZ);
642 inst[INST_SZ - 1] = '\0';
643 if (cp = strchr(inst, '.'))
644 *cp = '\0';
645 }
646#endif /* NFSKERB */
647
648 if (nfsargsp->flags & NFSMNT_NFSV3) {
649 nfsvers = 3;
650 mntvers = 3;
651 } else {
652 nfsvers = 2;
653 mntvers = 1;
654 }
655 nfhret.stat = EACCES; /* Mark not yet successful */
656 while (retrycnt > 0) {
657 saddr.sin_family = AF_INET;
658 saddr.sin_port = htons(PMAPPORT);
659 if ((tport = port_no ? port_no :
660 pmap_getport(&saddr, RPCPROG_NFS,
661 nfsvers, nfsproto)) == 0) {
662 if ((opflags & ISBGRND) == 0)
663 clnt_pcreateerror("NFS Portmap");
664 } else {
665 saddr.sin_port = 0;
666 pertry.tv_sec = 10;
667 pertry.tv_usec = 0;
668 if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
669 clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
670 &so, 0, 0);
671 else
672 clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
673 pertry, &so);
674 if (clp == NULL) {
675 if ((opflags & ISBGRND) == 0)
676 clnt_pcreateerror("Cannot MNT RPC");
677 } else {
678 clp->cl_auth = authunix_create_default();
679 try.tv_sec = 10;
680 try.tv_usec = 0;
681 if (nfsargsp->flags & NFSMNT_KERB)
682 nfhret.auth = RPCAUTH_KERB4;
683 else
684 nfhret.auth = RPCAUTH_UNIX;
685 nfhret.vers = mntvers;
686 clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
687 xdr_dir, spec, xdr_fh, &nfhret, try);
688 if (clnt_stat != RPC_SUCCESS) {
689 if ((opflags & ISBGRND) == 0)
690 warnx("%s", clnt_sperror(clp,
691 "bad MNT RPC"));
692 } else {
693 auth_destroy(clp->cl_auth);
694 clnt_destroy(clp);
695 retrycnt = 0;
696 }
697 }
698 }
699 if (--retrycnt > 0) {
700 if (opflags & BGRND) {
701 opflags &= ~BGRND;
702 if (i = fork()) {
703 if (i == -1)
704 err(1, "nqnfs 2");
705 exit(0);
706 }
707 (void) setsid();
708 (void) close(STDIN_FILENO);
709 (void) close(STDOUT_FILENO);
710 (void) close(STDERR_FILENO);
711 (void) chdir("/");
712 opflags |= ISBGRND;
713 }
714 sleep(60);
715 }
716 }
717 if (nfhret.stat) {
718 if (opflags & ISBGRND)
719 exit(1);
720 warnx("can't access %s: %s", spec, strerror(nfhret.stat));
721 return (0);
722 }
723 saddr.sin_port = htons(tport);
724#ifdef ISO
725 if (isoflag) {
726 nfsargsp->addr = (struct sockaddr *) &isoaddr;
727 nfsargsp->addrlen = sizeof (isoaddr);
728 } else
729#endif /* ISO */
730 {
731 nfsargsp->addr = (struct sockaddr *) &saddr;
732 nfsargsp->addrlen = sizeof (saddr);
733 }
734 nfsargsp->fh = nfhret.nfh;
735 nfsargsp->fhsize = nfhret.fhsize;
736 nfsargsp->hostname = nam;
737 return (1);
738}
739
740/*
741 * xdr routines for mount rpc's
742 */
743int
744xdr_dir(xdrsp, dirp)
745 XDR *xdrsp;
746 char *dirp;
747{
748 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
749}
750
751int
752xdr_fh(xdrsp, np)
753 XDR *xdrsp;
754 register struct nfhret *np;
755{
756 register int i;
757 long auth, authcnt, authfnd = 0;
758
759 if (!xdr_u_long(xdrsp, &np->stat))
760 return (0);
761 if (np->stat)
762 return (1);
763 switch (np->vers) {
764 case 1:
765 np->fhsize = NFSX_V2FH;
766 return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
767 case 3:
768 if (!xdr_long(xdrsp, &np->fhsize))
769 return (0);
770 if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
771 return (0);
772 if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
773 return (0);
774 if (!xdr_long(xdrsp, &authcnt))
775 return (0);
776 for (i = 0; i < authcnt; i++) {
777 if (!xdr_long(xdrsp, &auth))
778 return (0);
779 if (auth == np->auth)
780 authfnd++;
781 }
782 /*
783 * Some servers, such as DEC's OSF/1 return a nil authenticator
784 * list to indicate RPCAUTH_UNIX.
785 */
786 if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
787 np->stat = EAUTH;
788 return (1);
789 };
790 return (0);
791}
792
793void
794usage()
795{
796 (void)fprintf(stderr, "\
797usage: mount_nfs [-3KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\
798 [-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\
799 [-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\
800 [-x retrans] rhost:path node\n");
801 exit(1);
802}