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.1 (Berkeley) 01/06/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, "bsiTpMlqdckF: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 'F': 148 if ((num = atoi(optarg)) != 0) 149 flags = num; 150 break; 151 case 'R': 152 if ((num = atoi(optarg)) > 0) 153 retrycnt = num; 154 break; 155 case 'r': 156 if ((num = atoi(optarg)) > 0) { 157 nfsargsp->rsize = num; 158 nfsargsp->flags |= NFSMNT_RSIZE; 159 } 160 break; 161 case 'w': 162 if ((num = atoi(optarg)) > 0) { 163 nfsargsp->wsize = num; 164 nfsargsp->flags |= NFSMNT_WSIZE; 165 } 166 break; 167 case 't': 168 if ((num = atoi(optarg)) > 0) { 169 nfsargsp->timeo = num; 170 nfsargsp->flags |= NFSMNT_TIMEO; 171 } 172 break; 173 case 'x': 174 if ((num = atoi(optarg)) > 0) { 175 nfsargsp->retrans = num; 176 nfsargsp->flags |= NFSMNT_RETRANS; 177 } 178 break; 179 case 'g': 180 if ((num = atoi(optarg)) > 0) { 181 nfsargsp->maxgrouplist = num; 182 nfsargsp->flags |= NFSMNT_MAXGRPS; 183 } 184 break; 185 case 'a': 186 if ((num = atoi(optarg)) >= 0) { 187 nfsargsp->readahead = num; 188 nfsargsp->flags |= NFSMNT_READAHEAD; 189 } 190 break; 191 case 'L': 192 if ((num = atoi(optarg)) >= 2) { 193 nfsargsp->leaseterm = num; 194 nfsargsp->flags |= NFSMNT_LEASETERM; 195 } 196 break; 197 case 'D': 198 if ((num = atoi(optarg)) > 0) { 199 nfsargsp->deadthresh = num; 200 nfsargsp->flags |= NFSMNT_DEADTHRESH; 201 } 202 break; 203 #ifdef KERBEROS 204 case 'K': 205 nfsargsp->flags |= NFSMNT_KERB; 206 break; 207 case 'm': 208 strncpy(realm, optarg, REALM_SZ - 1); 209 realm[REALM_SZ - 1] = '\0'; 210 break; 211 #endif /* KERBEROS */ 212 default: 213 Usage(argc, argv); 214 }; 215 if ((argc - optind) == 2) { 216 spec = argv[optind]; 217 name = argv[optind + 1]; 218 } else 219 Usage(argc, argv); 220 if (getnfsargs(spec, nfsargsp)) { 221 if (mount(MOUNT_NFS, name, flags, nfsargsp)) 222 exit(1); 223 if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) { 224 if ((opflags & ISBGRND) == 0) { 225 if (i = fork()) { 226 if (i == -1) { 227 perror("nqnfs"); 228 exit(1); 229 } 230 exit(); 231 } 232 (void) setsid(); 233 (void) close(0); 234 (void) close(1); 235 (void) close(2); 236 (void) chdir("/"); 237 } 238 openlog("mount_nfs:", LOG_PID, LOG_DAEMON); 239 nfssvc_flag = NFSSVC_MNTD; 240 ncd.ncd_dirp = name; 241 while (nfssvc(nfssvc_flag, (caddr_t)&ncd) < 0) { 242 if (errno == ENEEDAUTH) { 243 syslog(LOG_ERR, "in eacces"); 244 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH | 245 NFSSVC_AUTHINFAIL; 246 #ifdef KERBEROS 247 syslog(LOG_ERR,"Callin krb uid=%d inst=%s realm=%s",ncd.ncd_authuid,inst,realm); 248 /* 249 * Set up as ncd_authuid for the kerberos call. 250 * Must set ruid to ncd_authuid and reset the 251 * ticket name iff ncd_authuid is not the same 252 * as last time, so that the right ticket file 253 * is found. 254 */ 255 if (ncd.ncd_authuid != last_ruid) { 256 krb_set_tkt_string(""); 257 last_ruid = ncd.ncd_authuid; 258 } 259 setreuid(ncd.ncd_authuid, 0); 260 if (krb_mk_req(&kt, "rcmd", inst, realm, 0) == 261 KSUCCESS && 262 kt.length <= (RPCAUTH_MAXSIZ - 2*NFSX_UNSIGNED)) { 263 syslog(LOG_ERR,"Got it\n"); 264 ncd.ncd_authtype = RPCAUTH_NQNFS; 265 ncd.ncd_authlen = kt.length; 266 ncd.ncd_authstr = (char *)kt.dat; 267 nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH; 268 } 269 setreuid(0, 0); 270 syslog(LOG_ERR,"ktlen=%d\n", kt.length); 271 #endif /* KERBEROS */ 272 } else 273 syslog(LOG_ERR, "nfssvc err %m"); 274 } 275 } 276 exit(); 277 } else 278 exit(1); 279 } 280 281 getnfsargs(spec, nfsargsp) 282 char *spec; 283 struct nfs_args *nfsargsp; 284 { 285 register CLIENT *clp; 286 struct hostent *hp; 287 static struct sockaddr_in saddr; 288 #ifdef ISO 289 static struct sockaddr_iso isoaddr; 290 struct iso_addr *isop; 291 #endif 292 struct timeval pertry, try; 293 enum clnt_stat clnt_stat; 294 int so = RPC_ANYSOCK, isoflag = 0, i; 295 char *hostp, *delimp, *cp; 296 u_short tport; 297 static struct nfhret nfhret; 298 static char nam[MNAMELEN + 1]; 299 300 strncpy(nam, spec, MNAMELEN); 301 nam[MNAMELEN] = '\0'; 302 if ((delimp = index(spec, '@')) != NULL) { 303 hostp = delimp + 1; 304 } else if ((delimp = index(spec, ':')) != NULL) { 305 hostp = spec; 306 spec = delimp + 1; 307 } else { 308 fprintf(stderr, 309 "No <host>:<dirpath> or <dirpath>@<host> spec\n"); 310 return (0); 311 } 312 *delimp = '\0'; 313 /* 314 * DUMB!! Until the mount protocol works on iso transport, we must 315 * supply both an iso and an inet address for the host. 316 */ 317 #ifdef ISO 318 if (!strncmp(hostp, "iso=", 4)) { 319 u_short isoport; 320 321 hostp += 4; 322 isoflag++; 323 if ((delimp = index(hostp, '+')) == NULL) { 324 fprintf(stderr, "No iso+inet address\n"); 325 return (0); 326 } 327 *delimp = '\0'; 328 if ((isop = iso_addr(hostp)) == NULL) { 329 fprintf(stderr, "Bad iso address\n"); 330 return (0); 331 } 332 bzero((caddr_t)&isoaddr, sizeof (isoaddr)); 333 bcopy((caddr_t)isop, (caddr_t)&isoaddr.siso_addr, 334 sizeof (struct iso_addr)); 335 isoaddr.siso_len = sizeof (isoaddr); 336 isoaddr.siso_family = AF_ISO; 337 isoaddr.siso_tlen = 2; 338 isoport = htons(NFS_PORT); 339 bcopy((caddr_t)&isoport, TSEL(&isoaddr), isoaddr.siso_tlen); 340 hostp = delimp + 1; 341 } 342 #endif /* ISO */ 343 344 /* 345 * Handle an internet host address and reverse resolve it if 346 * doing Kerberos. 347 */ 348 if (isdigit(*hostp)) { 349 if ((saddr.sin_addr.s_addr = inet_addr(hostp)) == -1) { 350 fprintf(stderr, "Bad net addr %s\n", hostp); 351 return (0); 352 } 353 if ((nfsargsp->flags & NFSMNT_KERB) && 354 (hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr, 355 sizeof (u_long), AF_INET)) == (struct hostent *)0) { 356 fprintf(stderr, "Can't reverse resolve net addr\n"); 357 return (0); 358 } 359 } else if ((hp = gethostbyname(hostp)) == NULL) { 360 fprintf(stderr, "Can't get net id for host\n"); 361 return (0); 362 } 363 #ifdef KERBEROS 364 if (nfsargsp->flags & NFSMNT_KERB) { 365 strncpy(inst, hp->h_name, INST_SZ); 366 inst[INST_SZ - 1] = '\0'; 367 if (cp = index(inst, '.')) 368 *cp = '\0'; 369 } 370 #endif /* KERBEROS */ 371 372 bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 373 nfhret.stat = EACCES; /* Mark not yet successful */ 374 while (retrycnt > 0) { 375 saddr.sin_family = AF_INET; 376 saddr.sin_port = htons(PMAPPORT); 377 if ((tport = pmap_getport(&saddr, RPCPROG_NFS, 378 NFS_VER2, IPPROTO_UDP)) == 0) { 379 if ((opflags & ISBGRND) == 0) 380 clnt_pcreateerror("NFS Portmap"); 381 } else { 382 saddr.sin_port = 0; 383 pertry.tv_sec = 10; 384 pertry.tv_usec = 0; 385 if ((clp = clntudp_create(&saddr, RPCPROG_MNT, 386 RPCMNT_VER1, pertry, &so)) == NULL) { 387 if ((opflags & ISBGRND) == 0) 388 clnt_pcreateerror("Cannot MNT PRC"); 389 } else { 390 clp->cl_auth = authunix_create_default(); 391 try.tv_sec = 10; 392 try.tv_usec = 0; 393 clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 394 xdr_dir, spec, xdr_fh, &nfhret, try); 395 if (clnt_stat != RPC_SUCCESS) { 396 if ((opflags & ISBGRND) == 0) 397 clnt_perror(clp, "Bad MNT RPC"); 398 } else { 399 auth_destroy(clp->cl_auth); 400 clnt_destroy(clp); 401 retrycnt = 0; 402 } 403 } 404 } 405 if (--retrycnt > 0) { 406 if (opflags & BGRND) { 407 opflags &= ~BGRND; 408 if (i = fork()) { 409 if (i == -1) { 410 perror("nqnfs"); 411 exit(1); 412 } 413 exit(); 414 } 415 (void) setsid(); 416 (void) close(0); 417 (void) close(1); 418 (void) close(2); 419 (void) chdir("/"); 420 opflags |= ISBGRND; 421 } 422 sleep(60); 423 } 424 } 425 if (nfhret.stat) { 426 if (opflags & ISBGRND) 427 exit(1); 428 fprintf(stderr, "Can't access %s: ", spec); 429 errno = nfhret.stat; 430 perror(NULL); 431 return (0); 432 } 433 saddr.sin_port = htons(tport); 434 #ifdef ISO 435 if (isoflag) { 436 nfsargsp->addr = (struct sockaddr *) &isoaddr; 437 nfsargsp->addrlen = sizeof (isoaddr); 438 } else 439 #endif /* ISO */ 440 { 441 nfsargsp->addr = (struct sockaddr *) &saddr; 442 nfsargsp->addrlen = sizeof (saddr); 443 } 444 nfsargsp->fh = &nfhret.nfh; 445 nfsargsp->hostname = nam; 446 return (1); 447 } 448 449 /* 450 * xdr routines for mount rpc's 451 */ 452 xdr_dir(xdrsp, dirp) 453 XDR *xdrsp; 454 char *dirp; 455 { 456 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 457 } 458 459 xdr_fh(xdrsp, np) 460 XDR *xdrsp; 461 struct nfhret *np; 462 { 463 if (!xdr_u_long(xdrsp, &(np->stat))) 464 return (0); 465 if (np->stat) 466 return (1); 467 return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 468 } 469 470 Usage(argc, argv) 471 int argc; 472 char *argv[]; 473 { 474 register int i; 475 476 for (i = 0; i < argc; i++) 477 fprintf(stderr, "%s ", argv[i]); 478 fprintf(stderr, "\nBad mount_nfs arg\n"); 479 exit(1); 480 } 481