1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * 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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1992 The Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)mount_nfs.c 5.4 (Berkeley) 04/03/92"; 19 #endif /* not lint */ 20 21 #include <stdio.h> 22 #include <signal.h> 23 #include <strings.h> 24 #include <sys/syslog.h> 25 #include <sys/param.h> 26 #include <sys/file.h> 27 #include <sys/errno.h> 28 #include <sys/ucred.h> 29 #include <sys/mount.h> 30 #include <sys/socket.h> 31 #include <sys/socketvar.h> 32 #include <netdb.h> 33 #include <rpc/rpc.h> 34 #include <rpc/pmap_clnt.h> 35 #include <rpc/pmap_prot.h> 36 #ifdef ISO 37 #include <netiso/iso.h> 38 #endif 39 #ifdef KERBEROS 40 #include <kerberosIV/krb.h> 41 #endif 42 #include <nfs/rpcv2.h> 43 #include <nfs/nfsv2.h> 44 #include <nfs/nfs.h> 45 #include <nfs/nqnfs.h> 46 47 int xdr_dir(), xdr_fh(); 48 struct nfs_args nfsdefargs = { 49 (struct sockaddr *)0, 50 sizeof (struct sockaddr_in), 51 SOCK_DGRAM, 52 0, 53 (nfsv2fh_t *)0, 54 0, 55 NFS_WSIZE, 56 NFS_RSIZE, 57 NFS_TIMEO, 58 NFS_RETRANS, 59 NFS_MAXGRPS, 60 NFS_DEFRAHEAD, 61 NQ_DEFLEASE, 62 NQ_DEADTHRESH, 63 (char *)0, 64 }; 65 66 struct nfhret { 67 u_long stat; 68 nfsv2fh_t nfh; 69 }; 70 #define DEF_RETRY 10000 71 #define BGRND 1 72 #define ISBGRND 2 73 int retrycnt = DEF_RETRY; 74 int opflags = 0; 75 extern int errno; 76 77 #ifdef ISO 78 struct iso_addr *iso_addr(); 79 #endif 80 81 #ifdef KERBEROS 82 char inst[INST_SZ]; 83 char realm[REALM_SZ]; 84 KTEXT_ST kt; 85 #endif 86 87 main(argc, argv, arge) 88 int argc; 89 char **argv; 90 char **arge; 91 { 92 struct nfs_args nfsargs; 93 register int c; 94 register struct nfs_args *nfsargsp = &nfsargs; 95 struct nfsd_cargs ncd; 96 int num, flags = 0, match = 1, i, nfssvc_flag; 97 char *spec, *name; 98 uid_t last_ruid = -1; 99 extern int optind; 100 extern char *optarg; 101 102 #ifdef KERBEROS 103 strcpy(realm, KRB_REALM); 104 #endif 105 nfsargs = nfsdefargs; 106 retrycnt = DEF_RETRY; 107 if (argc <= 1) 108 Usage(argc, argv); 109 while ((c = getopt(argc, argv, "bsiTpMlqdckPF:R:r:w:t:x:g:a:L:D:Km:")) 110 != EOF) 111 switch (c) { 112 case 'b': 113 opflags |= BGRND; 114 break; 115 case 's': 116 nfsargsp->flags |= NFSMNT_SOFT; 117 break; 118 case 'i': 119 nfsargsp->flags |= NFSMNT_INT; 120 break; 121 case 'T': 122 nfsargsp->sotype = SOCK_STREAM; 123 break; 124 #ifdef ISO 125 case 'p': 126 nfsargsp->sotype = SOCK_SEQPACKET; 127 break; 128 #endif 129 case 'M': 130 nfsargsp->flags |= NFSMNT_MYWRITE; 131 break; 132 case 'l': 133 nfsargsp->flags |= NFSMNT_RDIRALOOK; 134 break; 135 case 'q': 136 nfsargsp->flags |= NFSMNT_NQNFS; 137 break; 138 case 'd': 139 nfsargsp->flags |= NFSMNT_DUMBTIMR; 140 break; 141 case 'c': 142 nfsargsp->flags |= NFSMNT_NOCONN; 143 break; 144 case 'k': 145 nfsargsp->flags |= NFSMNT_NQLOOKLEASE; 146 break; 147 case 'P': 148 nfsargsp->flags |= NFSMNT_RESVPORT; 149 break; 150 case 'F': 151 if ((num = atoi(optarg)) != 0) 152 flags = num; 153 break; 154 case 'R': 155 if ((num = atoi(optarg)) > 0) 156 retrycnt = num; 157 break; 158 case 'r': 159 if ((num = atoi(optarg)) > 0) { 160 nfsargsp->rsize = num; 161 nfsargsp->flags |= NFSMNT_RSIZE; 162 } 163 break; 164 case 'w': 165 if ((num = atoi(optarg)) > 0) { 166 nfsargsp->wsize = num; 167 nfsargsp->flags |= NFSMNT_WSIZE; 168 } 169 break; 170 case 't': 171 if ((num = atoi(optarg)) > 0) { 172 nfsargsp->timeo = num; 173 nfsargsp->flags |= NFSMNT_TIMEO; 174 } 175 break; 176 case 'x': 177 if ((num = atoi(optarg)) > 0) { 178 nfsargsp->retrans = num; 179 nfsargsp->flags |= NFSMNT_RETRANS; 180 } 181 break; 182 case 'g': 183 if ((num = atoi(optarg)) > 0) { 184 set_rpc_maxgrouplist(num); 185 nfsargsp->maxgrouplist = num; 186 nfsargsp->flags |= NFSMNT_MAXGRPS; 187 } 188 break; 189 case 'a': 190 if ((num = atoi(optarg)) >= 0) { 191 nfsargsp->readahead = num; 192 nfsargsp->flags |= NFSMNT_READAHEAD; 193 } 194 break; 195 case 'L': 196 if ((num = atoi(optarg)) >= 2) { 197 nfsargsp->leaseterm = num; 198 nfsargsp->flags |= NFSMNT_LEASETERM; 199 } 200 break; 201 case 'D': 202 if ((num = atoi(optarg)) > 0) { 203 nfsargsp->deadthresh = num; 204 nfsargsp->flags |= NFSMNT_DEADTHRESH; 205 } 206 break; 207 #ifdef KERBEROS 208 case 'K': 209 nfsargsp->flags |= NFSMNT_KERB; 210 break; 211 case 'm': 212 strncpy(realm, optarg, REALM_SZ - 1); 213 realm[REALM_SZ - 1] = '\0'; 214 break; 215 #endif /* KERBEROS */ 216 default: 217 Usage(argc, argv); 218 }; 219 if ((argc - optind) == 2) { 220 spec = argv[optind]; 221 name = argv[optind + 1]; 222 } else 223 Usage(argc, argv); 224 if (getnfsargs(spec, nfsargsp)) { 225 if (mount(MOUNT_NFS, name, flags, nfsargsp)) 226 exit(1); 227 if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 228 if ((opflags & ISBGRND) == 0) { 229 if (i = fork()) { 230 if (i == -1) { 231 perror("nqnfs"); 232 exit(1); 233 } 234 exit(0); 235 } 236 (void) setsid(); 237 (void) close(0); 238 (void) close(1); 239 (void) close(2); 240 (void) chdir("/"); 241 } 242 openlog("mount_nfs:", LOG_PID, LOG_DAEMON); 243 nfssvc_flag = NFSSVC_MNTD; 244 ncd.ncd_dirp = name; 245 while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 246 if (errno == ENEEDAUTH) { 247 syslog(LOG_ERR, "in eacces"); 248 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH | 249 NFSSVC_AUTHINFAIL; 250 #ifdef KERBEROS 251 syslog(LOG_ERR,"Callin krb uid=%d inst=%s realm=%s",ncd.ncd_authuid,inst,realm); 252 /* 253 * Set up as ncd_authuid for the kerberos call. 254 * Must set ruid to ncd_authuid and reset the 255 * ticket name iff ncd_authuid is not the same 256 * as last time, so that the right ticket file 257 * is found. 258 */ 259 if (ncd.ncd_authuid != last_ruid) { 260 krb_set_tkt_string(""); 261 last_ruid = ncd.ncd_authuid; 262 } 263 setreuid(ncd.ncd_authuid, 0); 264 if (krb_mk_req(&kt, "rcmd", inst, realm, 0) == 265 KSUCCESS && 266 kt.length <= (RPCAUTH_MAXSIZ - 2*NFSX_UNSIGNED)) { 267 syslog(LOG_ERR,"Got it\n"); 268 ncd.ncd_authtype = RPCAUTH_NQNFS; 269 ncd.ncd_authlen = kt.length; 270 ncd.ncd_authstr = (char *)kt.dat; 271 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 272 } 273 setreuid(0, 0); 274 syslog(LOG_ERR,"ktlen=%d\n", kt.length); 275 #endif /* KERBEROS */ 276 } else 277 syslog(LOG_ERR, "nfssvc err %m"); 278 } 279 } 280 exit(0); 281 } else 282 exit(1); 283 } 284 285 getnfsargs(spec, nfsargsp) 286 char *spec; 287 struct nfs_args *nfsargsp; 288 { 289 register CLIENT *clp; 290 struct hostent *hp; 291 static struct sockaddr_in saddr; 292 #ifdef ISO 293 static struct sockaddr_iso isoaddr; 294 struct iso_addr *isop; 295 #endif 296 struct timeval pertry, try; 297 enum clnt_stat clnt_stat; 298 int so = RPC_ANYSOCK, isoflag = 0, i; 299 char *hostp, *delimp, *cp; 300 u_short tport; 301 static struct nfhret nfhret; 302 static char nam[MNAMELEN + 1]; 303 304 strncpy(nam, spec, MNAMELEN); 305 nam[MNAMELEN] = '\0'; 306 if ((delimp = index(spec, '@')) != NULL) { 307 hostp = delimp + 1; 308 } else if ((delimp = index(spec, ':')) != NULL) { 309 hostp = spec; 310 spec = delimp + 1; 311 } else { 312 fprintf(stderr, 313 "No <host>:<dirpath> or <dirpath>@<host> spec\n"); 314 return (0); 315 } 316 *delimp = '\0'; 317 /* 318 * DUMB!! Until the mount protocol works on iso transport, we must 319 * supply both an iso and an inet address for the host. 320 */ 321 #ifdef ISO 322 if (!strncmp(hostp, "iso=", 4)) { 323 u_short isoport; 324 325 hostp += 4; 326 isoflag++; 327 if ((delimp = index(hostp, '+')) == NULL) { 328 fprintf(stderr, "No iso+inet address\n"); 329 return (0); 330 } 331 *delimp = '\0'; 332 if ((isop = iso_addr(hostp)) == NULL) { 333 fprintf(stderr, "Bad iso address\n"); 334 return (0); 335 } 336 bzero((caddr_t)&isoaddr, sizeof (isoaddr)); 337 bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr, 338 sizeof (struct iso_addr)); 339 isoaddr.siso_len = sizeof (isoaddr); 340 isoaddr.siso_family = AF_ISO; 341 isoaddr.siso_tlen = 2; 342 isoport = htons(NFS_PORT); 343 bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen); 344 hostp = delimp + 1; 345 } 346 #endif /* ISO */ 347 348 /* 349 * Handle an internet host address and reverse resolve it if 350 * doing Kerberos. 351 */ 352 if (isdigit(*hostp)) { 353 if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { 354 fprintf(stderr, "Bad net addr %s\n", hostp); 355 return (0); 356 } 357 if ((nfsargsp->flags & NFSMNT_KERB) && 358 (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, 359 sizeof (u_long), AF_INET)) == (struct hostent *)0) { 360 fprintf(stderr, "Can't reverse resolve net addr\n"); 361 return (0); 362 } 363 } else if ((hp = gethostbyname(hostp)) == NULL) { 364 fprintf(stderr, "Can't get net id for host\n"); 365 return (0); 366 } 367 #ifdef KERBEROS 368 if (nfsargsp->flags & NFSMNT_KERB) { 369 strncpy(inst, hp->h_name, INST_SZ); 370 inst[INST_SZ - 1] = '\0'; 371 if (cp = index(inst, '.')) 372 *cp = '\0'; 373 } 374 #endif /* KERBEROS */ 375 376 bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 377 nfhret.stat = EACCES; /* Mark not yet successful */ 378 while (retrycnt > 0) { 379 saddr.sin_family = AF_INET; 380 saddr.sin_port = htons(PMAPPORT); 381 if ((tport = pmap_getport(&saddr, RPCPROG_NFS, 382 NFS_VER2, IPPROTO_UDP)) == 0) { 383 if ((opflags & ISBGRND) == 0) 384 clnt_pcreateerror("NFS Portmap"); 385 } else { 386 saddr.sin_port = 0; 387 pertry.tv_sec = 10; 388 pertry.tv_usec = 0; 389 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, 390 RPCMNT_VER1, pertry, &so)) == NULL) { 391 if ((opflags & ISBGRND) == 0) 392 clnt_pcreateerror("Cannot MNT PRC"); 393 } else { 394 clp->cl_auth = authunix_create_default(); 395 try.tv_sec = 10; 396 try.tv_usec = 0; 397 clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 398 xdr_dir, spec, xdr_fh, &nfhret, try); 399 if (clnt_stat != RPC_SUCCESS) { 400 if ((opflags & ISBGRND) == 0) 401 clnt_perror(clp, "Bad MNT RPC"); 402 } else { 403 auth_destroy(clp->cl_auth); 404 clnt_destroy(clp); 405 retrycnt = 0; 406 } 407 } 408 } 409 if (--retrycnt > 0) { 410 if (opflags & BGRND) { 411 opflags &= ~BGRND; 412 if (i = fork()) { 413 if (i == -1) { 414 perror("nqnfs"); 415 exit(1); 416 } 417 exit(0); 418 } 419 (void) setsid(); 420 (void) close(0); 421 (void) close(1); 422 (void) close(2); 423 (void) chdir("/"); 424 opflags |= ISBGRND; 425 } 426 sleep(60); 427 } 428 } 429 if (nfhret.stat) { 430 if (opflags & ISBGRND) 431 exit(1); 432 fprintf(stderr, "Can't access %s: ", spec); 433 errno = nfhret.stat; 434 perror(NULL); 435 return (0); 436 } 437 saddr.sin_port = htons(tport); 438 #ifdef ISO 439 if (isoflag) { 440 nfsargsp->addr = (struct sockaddr *) &isoaddr; 441 nfsargsp->addrlen = sizeof (isoaddr); 442 } else 443 #endif /* ISO */ 444 { 445 nfsargsp->addr = (struct sockaddr *) &saddr; 446 nfsargsp->addrlen = sizeof (saddr); 447 } 448 nfsargsp->fh = &nfhret.nfh; 449 nfsargsp->hostname = nam; 450 return (1); 451 } 452 453 /* 454 * xdr routines for mount rpc's 455 */ 456 xdr_dir(xdrsp, dirp) 457 XDR *xdrsp; 458 char *dirp; 459 { 460 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 461 } 462 463 xdr_fh(xdrsp, np) 464 XDR *xdrsp; 465 struct nfhret *np; 466 { 467 if (!xdr_u_long(xdrsp, &(np->stat))) 468 return (0); 469 if (np->stat) 470 return (1); 471 return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 472 } 473 474 Usage(argc, argv) 475 int argc; 476 char *argv[]; 477 { 478 register int i; 479 480 for (i = 0; i < argc; i++) 481 fprintf(stderr, "%s ", argv[i]); 482 fprintf(stderr, "\nBad mount_nfs arg\n"); 483 exit(1); 484 } 485