Deleted Added
sdiff udiff text old ( 24495 ) new ( 24546 )
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 $";
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
195int
196main(argc, argv)
197 int argc;
198 char *argv[];
199{
200 register int c;
201 register struct nfs_args *nfsargsp;
202 struct nfs_args nfsargs;
203 struct nfsd_cargs ncd;
204 int mntflags, altflags, i, nfssvc_flag, num;
205 char *name, *p, *spec;
206 struct vfsconf vfc;
207 int error = 0;
208#ifdef NFSKERB
209 uid_t last_ruid;
210
211 last_ruid = -1;
212 (void)strcpy(realm, KRB_REALM);
213 if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
214 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
215 ((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
216 ((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
217 fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
218#endif /* NFSKERB */
219 retrycnt = DEF_RETRY;
220
221 mntflags = 0;
222 altflags = 0;
223 nfsargs = nfsdefargs;
224 nfsargsp = &nfsargs;
225 while ((c = getopt(argc, argv,
226 "3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != -1)
227 switch (c) {
228 case '3':
229 nfsargsp->flags |= NFSMNT_NFSV3;
230 break;
231 case 'a':
232 num = strtol(optarg, &p, 10);
233 if (*p || num < 0)
234 errx(1, "illegal -a value -- %s", optarg);
235 nfsargsp->readahead = num;
236 nfsargsp->flags |= NFSMNT_READAHEAD;
237 break;
238 case 'b':
239 opflags |= BGRND;
240 break;
241 case 'c':
242 nfsargsp->flags |= NFSMNT_NOCONN;
243 break;
244 case 'D':
245 num = strtol(optarg, &p, 10);
246 if (*p || num <= 0)
247 errx(1, "illegal -D value -- %s", optarg);
248 nfsargsp->deadthresh = num;
249 nfsargsp->flags |= NFSMNT_DEADTHRESH;
250 break;
251 case 'd':
252 nfsargsp->flags |= NFSMNT_DUMBTIMR;
253 break;
254 case 'g':
255 num = strtol(optarg, &p, 10);
256 if (*p || num <= 0)
257 errx(1, "illegal -g value -- %s", optarg);
258#ifdef __FreeBSD__
259 set_rpc_maxgrouplist(num);
260#endif
261 nfsargsp->maxgrouplist = num;
262 nfsargsp->flags |= NFSMNT_MAXGRPS;
263 break;
264 case 'I':
265 num = strtol(optarg, &p, 10);
266 if (*p || num <= 0)
267 errx(1, "illegal -I value -- %s", optarg);
268 nfsargsp->readdirsize = num;
269 nfsargsp->flags |= NFSMNT_READDIRSIZE;
270 break;
271 case 'i':
272 nfsargsp->flags |= NFSMNT_INT;
273 break;
274#ifdef NFSKERB
275 case 'K':
276 nfsargsp->flags |= NFSMNT_KERB;
277 break;
278#endif
279 case 'L':
280 num = strtol(optarg, &p, 10);
281 if (*p || num < 2)
282 errx(1, "illegal -L value -- %s", optarg);
283 nfsargsp->leaseterm = num;
284 nfsargsp->flags |= NFSMNT_LEASETERM;
285 break;
286 case 'l':
287 nfsargsp->flags |= NFSMNT_RDIRPLUS;
288 break;
289#ifdef NFSKERB
290 case 'm':
291 (void)strncpy(realm, optarg, REALM_SZ - 1);
292 realm[REALM_SZ - 1] = '\0';
293 break;
294#endif
295 case 'o':
296 getmntopts(optarg, mopts, &mntflags, &altflags);
297 if(altflags & ALTF_BG)
298 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;
313 if(altflags & ALTF_MNTUDP)
314 mnttcp_ok = 0;
315 if(altflags & ALTF_RESVPORT)
316 nfsargsp->flags |= NFSMNT_RESVPORT;
317#ifdef ISO
318 if(altflags & ALTF_SEQPACKET)
319 nfsargsp->sotype = SOCK_SEQPACKET;
320#endif
321 if(altflags & ALTF_NQNFS)
322 nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
323 if(altflags & ALTF_SOFT)
324 nfsargsp->flags |= NFSMNT_SOFT;
325 if(altflags & ALTF_TCP) {
326 nfsargsp->sotype = SOCK_STREAM;
327 nfsproto = IPPROTO_TCP;
328 }
329 if(altflags & ALTF_PORT)
330 port_no = atoi(strstr(optarg, "port=") + 5);
331 altflags = 0;
332 break;
333 case 'P':
334 nfsargsp->flags |= NFSMNT_RESVPORT;
335 break;
336#ifdef ISO
337 case 'p':
338 nfsargsp->sotype = SOCK_SEQPACKET;
339 break;
340#endif
341 case 'q':
342 nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
343 break;
344 case 'R':
345 num = strtol(optarg, &p, 10);
346 if (*p || num <= 0)
347 errx(1, "illegal -R value -- %s", optarg);
348 retrycnt = num;
349 break;
350 case 'r':
351 num = strtol(optarg, &p, 10);
352 if (*p || num <= 0)
353 errx(1, "illegal -r value -- %s", optarg);
354 nfsargsp->rsize = num;
355 nfsargsp->flags |= NFSMNT_RSIZE;
356 break;
357 case 's':
358 nfsargsp->flags |= NFSMNT_SOFT;
359 break;
360 case 'T':
361 nfsargsp->sotype = SOCK_STREAM;
362 nfsproto = IPPROTO_TCP;
363 break;
364 case 't':
365 num = strtol(optarg, &p, 10);
366 if (*p || num <= 0)
367 errx(1, "illegal -t value -- %s", optarg);
368 nfsargsp->timeo = num;
369 nfsargsp->flags |= NFSMNT_TIMEO;
370 break;
371 case 'w':
372 num = strtol(optarg, &p, 10);
373 if (*p || num <= 0)
374 errx(1, "illegal -w value -- %s", optarg);
375 nfsargsp->wsize = num;
376 nfsargsp->flags |= NFSMNT_WSIZE;
377 break;
378 case 'x':
379 num = strtol(optarg, &p, 10);
380 if (*p || num <= 0)
381 errx(1, "illegal -x value -- %s", optarg);
382 nfsargsp->retrans = num;
383 nfsargsp->flags |= NFSMNT_RETRANS;
384 break;
385 case 'U':
386 mnttcp_ok = 0;
387 break;
388 default:
389 usage();
390 break;
391 }
392 argc -= optind;
393 argv += optind;
394
395 if (argc != 2) {
396 usage();
397 /* NOTREACHED */
398 }
399
400 spec = *argv++;
401 name = *argv;
402
403 if (!getnfsargs(spec, nfsargsp))
404 exit(1);
405
406#ifdef __FreeBSD__
407 error = getvfsbyname("nfs", &vfc);
408 if (error && vfsisloadable("nfs")) {
409 if(vfsload("nfs"))
410 err(EX_OSERR, "vfsload(nfs)");
411 endvfsent(); /* clear cache */
412 error = getvfsbyname("nfs", &vfc);
413 }
414 if (error)
415 errx(EX_OSERR, "nfs filesystem is not available");
416
417 if (mount(vfc.vfc_name, name, mntflags, nfsargsp))
418 err(1, "%s", name);
419#else
420 if (mount("nfs", name, mntflags, nfsargsp))
421 err(1, "%s", name);
422#endif
423 if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
424 if ((opflags & ISBGRND) == 0) {
425 if (i = fork()) {
426 if (i == -1)
427 err(1, "nqnfs 1");
428 exit(0);
429 }
430 (void) setsid();
431 (void) close(STDIN_FILENO);
432 (void) close(STDOUT_FILENO);
433 (void) close(STDERR_FILENO);
434 (void) chdir("/");
435 }
436 openlog("mount_nfs:", LOG_PID, LOG_DAEMON);
437 nfssvc_flag = NFSSVC_MNTD;
438 ncd.ncd_dirp = name;
439 while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) {
440 if (errno != ENEEDAUTH) {
441 syslog(LOG_ERR, "nfssvc err %m");
442 continue;
443 }
444 nfssvc_flag =
445 NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
446#ifdef NFSKERB
447 /*
448 * Set up as ncd_authuid for the kerberos call.
449 * Must set ruid to ncd_authuid and reset the
450 * ticket name iff ncd_authuid is not the same
451 * as last time, so that the right ticket file
452 * is found.
453 * Get the Kerberos credential structure so that
454 * we have the seesion key and get a ticket for
455 * this uid.
456 * For more info see the IETF Draft "Authentication
457 * in ONC RPC".
458 */
459 if (ncd.ncd_authuid != last_ruid) {
460 char buf[512];
461 (void)sprintf(buf, "%s%d",
462 TKT_ROOT, ncd.ncd_authuid);
463 krb_set_tkt_string(buf);
464 last_ruid = ncd.ncd_authuid;
465 }
466 setreuid(ncd.ncd_authuid, 0);
467 kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
468 if (kret == RET_NOTKT) {
469 kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
470 DEFAULT_TKT_LIFE);
471 if (kret == KSUCCESS)
472 kret = krb_get_cred(NFS_KERBSRV, inst, realm,
473 &kcr);
474 }
475 if (kret == KSUCCESS)
476 kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
477 realm, 0);
478
479 /*
480 * Fill in the AKN_FULLNAME authenticator and verfier.
481 * Along with the Kerberos ticket, we need to build
482 * the timestamp verifier and encrypt it in CBC mode.
483 */
484 if (kret == KSUCCESS &&
485 ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
486 && gettimeofday(&ktv, (struct timezone *)0) == 0) {
487 ncd.ncd_authtype = RPCAUTH_KERB4;
488 ncd.ncd_authstr = (u_char *)&ktick;
489 ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
490 3 * NFSX_UNSIGNED;
491 ncd.ncd_verfstr = (u_char *)&kverf;
492 ncd.ncd_verflen = sizeof (kverf);
493 memmove(ncd.ncd_key, kcr.session,
494 sizeof (kcr.session));
495 kin.t1 = htonl(ktv.tv_sec);
496 kin.t2 = htonl(ktv.tv_usec);
497 kin.w1 = htonl(NFS_KERBTTL);
498 kin.w2 = htonl(NFS_KERBTTL - 1);
499 bzero((caddr_t)kivec, sizeof (kivec));
500
501 /*
502 * Encrypt kin in CBC mode using the session
503 * key in kcr.
504 */
505 XXX
506
507 /*
508 * Finally, fill the timestamp verifier into the
509 * authenticator and verifier.
510 */
511 ktick.kind = htonl(RPCAKN_FULLNAME);
512 kverf.kind = htonl(RPCAKN_FULLNAME);
513 NFS_KERBW1(ktick.kt) = kout.w1;
514 ktick.kt.length = htonl(ktick.kt.length);
515 kverf.verf.t1 = kout.t1;
516 kverf.verf.t2 = kout.t2;
517 kverf.verf.w2 = kout.w2;
518 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
519 }
520 setreuid(0, 0);
521#endif /* NFSKERB */
522 }
523 }
524 exit(0);
525}
526
527int
528getnfsargs(spec, nfsargsp)
529 char *spec;
530 struct nfs_args *nfsargsp;
531{
532 register CLIENT *clp;
533 struct hostent *hp;
534 static struct sockaddr_in saddr;
535#ifdef ISO
536 static struct sockaddr_iso isoaddr;
537 struct iso_addr *isop;
538 int isoflag = 0;
539#endif
540 struct timeval pertry, try;
541 enum clnt_stat clnt_stat;
542 int so = RPC_ANYSOCK, i, nfsvers, mntvers;
543 char *hostp, *delimp;
544#ifdef NFSKERB
545 char *cp;
546#endif
547 u_short tport;
548 static struct nfhret nfhret;
549 static char nam[MNAMELEN + 1];
550
551 strncpy(nam, spec, MNAMELEN);
552 nam[MNAMELEN] = '\0';
553 if ((delimp = strchr(spec, '@')) != NULL) {
554 hostp = delimp + 1;
555 } else if ((delimp = strchr(spec, ':')) != NULL) {
556 hostp = spec;
557 spec = delimp + 1;
558 } else {
559 warnx("no <host>:<dirpath> or <dirpath>@<host> spec");
560 return (0);
561 }
562 *delimp = '\0';
563 /*
564 * DUMB!! Until the mount protocol works on iso transport, we must
565 * supply both an iso and an inet address for the host.
566 */
567#ifdef ISO
568 if (!strncmp(hostp, "iso=", 4)) {
569 u_short isoport;
570
571 hostp += 4;
572 isoflag++;
573 if ((delimp = strchr(hostp, '+')) == NULL) {
574 warnx("no iso+inet address");
575 return (0);
576 }
577 *delimp = '\0';
578 if ((isop = iso_addr(hostp)) == NULL) {
579 warnx("bad ISO address");
580 return (0);
581 }
582 memset(&isoaddr, 0, sizeof (isoaddr));
583 memmove(&isoaddr.siso_addr, isop, sizeof (struct iso_addr));
584 isoaddr.siso_len = sizeof (isoaddr);
585 isoaddr.siso_family = AF_ISO;
586 isoaddr.siso_tlen = 2;
587 isoport = htons(NFS_PORT);
588 memmove(TSEL(&isoaddr), &isoport, isoaddr.siso_tlen);
589 hostp = delimp + 1;
590 }
591#endif /* ISO */
592
593 /*
594 * Handle an internet host address and reverse resolve it if
595 * doing Kerberos.
596 */
597 if (isdigit(*hostp)) {
598 if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) {
599 warnx("bad net address %s", hostp);
600 return (0);
601 }
602 } else if ((hp = gethostbyname(hostp)) != NULL)
603 memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
604 else {
605 warnx("can't get net id for host");
606 return (0);
607 }
608#ifdef NFSKERB
609 if ((nfsargsp->flags & NFSMNT_KERB)) {
610 if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
611 sizeof (u_long), AF_INET)) == (struct hostent *)0) {
612 warnx("can't reverse resolve net address");
613 return (0);
614 }
615 memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
616 strncpy(inst, hp->h_name, INST_SZ);
617 inst[INST_SZ - 1] = '\0';
618 if (cp = strchr(inst, '.'))
619 *cp = '\0';
620 }
621#endif /* NFSKERB */
622
623 if (nfsargsp->flags & NFSMNT_NFSV3) {
624 nfsvers = 3;
625 mntvers = 3;
626 } else {
627 nfsvers = 2;
628 mntvers = 1;
629 }
630 nfhret.stat = EACCES; /* Mark not yet successful */
631 while (retrycnt > 0) {
632 saddr.sin_family = AF_INET;
633 saddr.sin_port = htons(PMAPPORT);
634 if ((tport = port_no ? port_no :
635 pmap_getport(&saddr, RPCPROG_NFS,
636 nfsvers, nfsproto)) == 0) {
637 if ((opflags & ISBGRND) == 0)
638 clnt_pcreateerror("NFS Portmap");
639 } else {
640 saddr.sin_port = 0;
641 pertry.tv_sec = 10;
642 pertry.tv_usec = 0;
643 if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
644 clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
645 &so, 0, 0);
646 else
647 clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
648 pertry, &so);
649 if (clp == NULL) {
650 if ((opflags & ISBGRND) == 0)
651 clnt_pcreateerror("Cannot MNT RPC");
652 } else {
653 clp->cl_auth = authunix_create_default();
654 try.tv_sec = 10;
655 try.tv_usec = 0;
656 if (nfsargsp->flags & NFSMNT_KERB)
657 nfhret.auth = RPCAUTH_KERB4;
658 else
659 nfhret.auth = RPCAUTH_UNIX;
660 nfhret.vers = mntvers;
661 clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
662 xdr_dir, spec, xdr_fh, &nfhret, try);
663 if (clnt_stat != RPC_SUCCESS) {
664 if ((opflags & ISBGRND) == 0)
665 warnx("%s", clnt_sperror(clp,
666 "bad MNT RPC"));
667 } else {
668 auth_destroy(clp->cl_auth);
669 clnt_destroy(clp);
670 retrycnt = 0;
671 }
672 }
673 }
674 if (--retrycnt > 0) {
675 if (opflags & BGRND) {
676 opflags &= ~BGRND;
677 if (i = fork()) {
678 if (i == -1)
679 err(1, "nqnfs 2");
680 exit(0);
681 }
682 (void) setsid();
683 (void) close(STDIN_FILENO);
684 (void) close(STDOUT_FILENO);
685 (void) close(STDERR_FILENO);
686 (void) chdir("/");
687 opflags |= ISBGRND;
688 }
689 sleep(60);
690 }
691 }
692 if (nfhret.stat) {
693 if (opflags & ISBGRND)
694 exit(1);
695 warnx("can't access %s: %s", spec, strerror(nfhret.stat));
696 return (0);
697 }
698 saddr.sin_port = htons(tport);
699#ifdef ISO
700 if (isoflag) {
701 nfsargsp->addr = (struct sockaddr *) &isoaddr;
702 nfsargsp->addrlen = sizeof (isoaddr);
703 } else
704#endif /* ISO */
705 {
706 nfsargsp->addr = (struct sockaddr *) &saddr;
707 nfsargsp->addrlen = sizeof (saddr);
708 }
709 nfsargsp->fh = nfhret.nfh;
710 nfsargsp->fhsize = nfhret.fhsize;
711 nfsargsp->hostname = nam;
712 return (1);
713}
714
715/*
716 * xdr routines for mount rpc's
717 */
718int
719xdr_dir(xdrsp, dirp)
720 XDR *xdrsp;
721 char *dirp;
722{
723 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
724}
725
726int
727xdr_fh(xdrsp, np)
728 XDR *xdrsp;
729 register struct nfhret *np;
730{
731 register int i;
732 long auth, authcnt, authfnd = 0;
733
734 if (!xdr_u_long(xdrsp, &np->stat))
735 return (0);
736 if (np->stat)
737 return (1);
738 switch (np->vers) {
739 case 1:
740 np->fhsize = NFSX_V2FH;
741 return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
742 case 3:
743 if (!xdr_long(xdrsp, &np->fhsize))
744 return (0);
745 if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
746 return (0);
747 if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
748 return (0);
749 if (!xdr_long(xdrsp, &authcnt))
750 return (0);
751 for (i = 0; i < authcnt; i++) {
752 if (!xdr_long(xdrsp, &auth))
753 return (0);
754 if (auth == np->auth)
755 authfnd++;
756 }
757 /*
758 * Some servers, such as DEC's OSF/1 return a nil authenticator
759 * list to indicate RPCAUTH_UNIX.
760 */
761 if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
762 np->stat = EAUTH;
763 return (1);
764 };
765 return (0);
766}
767
768void
769usage()
770{
771 (void)fprintf(stderr, "\
772usage: mount_nfs [-3KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\
773 [-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\
774 [-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\
775 [-x retrans] rhost:path node\n");
776 exit(1);
777}