nfsuserd.c revision 223382
159191Skris/*- 2296465Sdelphij * Copyright (c) 2009 Rick Macklem, University of Guelph 3296465Sdelphij * All rights reserved. 4296465Sdelphij * 559191Skris * Redistribution and use in source and binary forms, with or without 659191Skris * modification, are permitted provided that the following conditions 759191Skris * are met: 859191Skris * 1. Redistributions of source code must retain the above copyright 959191Skris * notice, this list of conditions and the following disclaimer. 1059191Skris * 2. Redistributions in binary form must reproduce the above copyright 1159191Skris * notice, this list of conditions and the following disclaimer in the 1259191Skris * documentation and/or other materials provided with the distribution. 1359191Skris * 14296465Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1559191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1659191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1759191Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1859191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1959191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2059191Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2159191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2259191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2359191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2459191Skris * SUCH DAMAGE. 2559191Skris * 2659191Skris */ 2759191Skris 2859191Skris#include <sys/cdefs.h> 2959191Skris__FBSDID("$FreeBSD: head/usr.sbin/nfsuserd/nfsuserd.c 223382 2011-06-21 21:07:33Z rmacklem $"); 3059191Skris 3159191Skris#include <sys/param.h> 3259191Skris#include <sys/errno.h> 3359191Skris#include <sys/linker.h> 3459191Skris#include <sys/module.h> 3559191Skris#include <sys/mount.h> 3659191Skris#include <sys/socket.h> 3759191Skris#include <sys/socketvar.h> 3859191Skris#include <sys/time.h> 3959191Skris#include <sys/ucred.h> 4059191Skris#include <sys/vnode.h> 4159191Skris#include <sys/wait.h> 4259191Skris 4359191Skris#include <nfs/nfssvc.h> 4459191Skris 4559191Skris#include <rpc/rpc.h> 4659191Skris 4759191Skris#include <fs/nfs/rpcv2.h> 4859191Skris#include <fs/nfs/nfsproto.h> 4959191Skris#include <fs/nfs/nfskpiport.h> 5059191Skris#include <fs/nfs/nfs.h> 5159191Skris 5259191Skris#include <ctype.h> 5359191Skris#include <err.h> 5459191Skris#include <grp.h> 5559191Skris#include <netdb.h> 5659191Skris#include <pwd.h> 5759191Skris#include <signal.h> 5859191Skris#include <stdio.h> 5959191Skris#include <stdlib.h> 6059191Skris#include <string.h> 6159191Skris#include <syslog.h> 6259191Skris#include <unistd.h> 6359191Skris 6459191Skris/* 6559191Skris * This program loads the password and group databases into the kernel 6659191Skris * for NFS V4. 6759191Skris */ 6859191Skris 6959191Skrisstatic void cleanup_term(int); 7068651Skrisstatic void usage(void); 71296465Sdelphijstatic void nfsuserdsrv(struct svc_req *, SVCXPRT *); 7259191Skrisstatic bool_t xdr_getid(XDR *, caddr_t); 7359191Skrisstatic bool_t xdr_getname(XDR *, caddr_t); 7459191Skrisstatic bool_t xdr_retval(XDR *, caddr_t); 75296465Sdelphij 7659191Skris#define MAXNAME 1024 7759191Skris#define MAXNFSUSERD 20 7859191Skris#define DEFNFSUSERD 4 7959191Skris#define MAXUSERMAX 100000 8059191Skris#define MINUSERMAX 10 81296465Sdelphij#define DEFUSERMAX 200 8259191Skris#define DEFUSERTIMEOUT (1 * 60) 83296465Sdelphijstruct info { 84296465Sdelphij long id; 85296465Sdelphij long retval; 86296465Sdelphij char name[MAXNAME + 1]; 87296465Sdelphij}; 8859191Skris 89296465Sdelphiju_char *dnsname = "default.domain"; 9059191Skrisu_char *defaultuser = "nobody"; 91296465Sdelphijuid_t defaultuid = (uid_t)32767; 92296465Sdelphiju_char *defaultgroup = "nogroup"; 93296465Sdelphijgid_t defaultgid = (gid_t)32767; 94296465Sdelphijint verbose = 0, im_a_slave = 0, nfsuserdcnt = -1, forcestart = 0; 9559191Skrisint defusertimeout = DEFUSERTIMEOUT; 96296465Sdelphijpid_t slaves[MAXNFSUSERD]; 97296465Sdelphij 98296465Sdelphijint 99296465Sdelphijmain(int argc, char *argv[]) 100296465Sdelphij{ 101296465Sdelphij int i, j; 10259191Skris int error, fnd_dup, len, mustfreeai = 0, start_uidpos; 10359191Skris struct nfsd_idargs nid; 10459191Skris struct passwd *pwd; 10559191Skris struct group *grp; 10659191Skris int sock, one = 1; 10759191Skris SVCXPRT *udptransp; 108296465Sdelphij u_short portnum; 109296465Sdelphij sigset_t signew; 110296465Sdelphij char hostname[MAXHOSTNAMELEN + 1], *cp; 111296465Sdelphij struct addrinfo *aip, hints; 112296465Sdelphij static uid_t check_dups[MAXUSERMAX]; 113296465Sdelphij 114296465Sdelphij if (modfind("nfscommon") < 0) { 11568651Skris /* Not present in kernel, try loading it */ 116296465Sdelphij if (kldload("nfscommon") < 0 || 117296465Sdelphij modfind("nfscommon") < 0) 118296465Sdelphij errx(1, "Experimental nfs subsystem is not available"); 119296465Sdelphij } 120296465Sdelphij 121296465Sdelphij /* 122296465Sdelphij * First, figure out what our domain name and Kerberos Realm 123296465Sdelphij * seem to be. Command line args may override these later. 124296465Sdelphij */ 125296465Sdelphij if (gethostname(hostname, MAXHOSTNAMELEN) == 0) { 126296465Sdelphij if ((cp = strchr(hostname, '.')) != NULL && 127296465Sdelphij *(cp + 1) != '\0') { 128296465Sdelphij dnsname = cp + 1; 129296465Sdelphij } else { 130296465Sdelphij memset((void *)&hints, 0, sizeof (hints)); 131296465Sdelphij hints.ai_flags = AI_CANONNAME; 132296465Sdelphij error = getaddrinfo(hostname, NULL, &hints, &aip); 133296465Sdelphij if (error == 0) { 134296465Sdelphij if (aip->ai_canonname != NULL && 135296465Sdelphij (cp = strchr(aip->ai_canonname, '.')) != NULL 136296465Sdelphij && *(cp + 1) != '\0') { 137296465Sdelphij dnsname = cp + 1; 138296465Sdelphij mustfreeai = 1; 139296465Sdelphij } else { 140296465Sdelphij freeaddrinfo(aip); 141296465Sdelphij } 142296465Sdelphij } 143296465Sdelphij } 144296465Sdelphij } 145296465Sdelphij nid.nid_usermax = DEFUSERMAX; 146296465Sdelphij nid.nid_usertimeout = defusertimeout; 147296465Sdelphij 148296465Sdelphij argc--; 149296465Sdelphij argv++; 150296465Sdelphij while (argc >= 1) { 151296465Sdelphij if (!strcmp(*argv, "-domain")) { 152296465Sdelphij if (argc == 1) 153296465Sdelphij usage(); 154296465Sdelphij argc--; 155296465Sdelphij argv++; 156296465Sdelphij strncpy(hostname, *argv, MAXHOSTNAMELEN); 15759191Skris hostname[MAXHOSTNAMELEN] = '\0'; 158296465Sdelphij dnsname = hostname; 15959191Skris } else if (!strcmp(*argv, "-verbose")) { 160296465Sdelphij verbose = 1; 161296465Sdelphij } else if (!strcmp(*argv, "-force")) { 162296465Sdelphij forcestart = 1; 163296465Sdelphij } else if (!strcmp(*argv, "-usermax")) { 164296465Sdelphij if (argc == 1) 16559191Skris usage(); 166296465Sdelphij argc--; 167296465Sdelphij argv++; 168296465Sdelphij i = atoi(*argv); 169296465Sdelphij if (i < MINUSERMAX || i > MAXUSERMAX) { 170296465Sdelphij fprintf(stderr, 171296465Sdelphij "usermax %d out of range %d<->%d\n", i, 172296465Sdelphij MINUSERMAX, MAXUSERMAX); 173296465Sdelphij usage(); 174296465Sdelphij } 17559191Skris nid.nid_usermax = i; 176296465Sdelphij } else if (!strcmp(*argv, "-usertimeout")) { 17759191Skris if (argc == 1) 178296465Sdelphij usage(); 179296465Sdelphij argc--; 180296465Sdelphij argv++; 181296465Sdelphij i = atoi(*argv); 182296465Sdelphij if (i < 0 || i > 100000) { 183296465Sdelphij fprintf(stderr, 18459191Skris "usertimeout %d out of range 0<->100000\n", 18559191Skris i); 18659191Skris usage(); 18768651Skris } 188296465Sdelphij nid.nid_usertimeout = defusertimeout = i * 60; 18959191Skris } else if (nfsuserdcnt == -1) { 190296465Sdelphij nfsuserdcnt = atoi(*argv); 191296465Sdelphij if (nfsuserdcnt < 1) 192296465Sdelphij usage(); 193296465Sdelphij if (nfsuserdcnt > MAXNFSUSERD) { 194296465Sdelphij warnx("nfsuserd count %d; reset to %d", 195296465Sdelphij nfsuserdcnt, DEFNFSUSERD); 19659191Skris nfsuserdcnt = DEFNFSUSERD; 19759191Skris } 19859191Skris } else { 19959191Skris usage(); 20059191Skris } 20159191Skris argc--; 202296465Sdelphij argv++; 203296465Sdelphij } 204296465Sdelphij if (nfsuserdcnt < 1) 20559191Skris nfsuserdcnt = DEFNFSUSERD; 206296465Sdelphij 207296465Sdelphij /* 20859191Skris * Strip off leading and trailing '.'s in domain name and map 209296465Sdelphij * alphabetics to lower case. 210296465Sdelphij */ 211296465Sdelphij while (*dnsname == '.') 212296465Sdelphij dnsname++; 213296465Sdelphij if (*dnsname == '\0') 214296465Sdelphij errx(1, "Domain name all '.'"); 215296465Sdelphij len = strlen(dnsname); 216296465Sdelphij cp = dnsname + len - 1; 217296465Sdelphij while (*cp == '.') { 218296465Sdelphij *cp = '\0'; 21959191Skris len--; 22059191Skris cp--; 22159191Skris } 22259191Skris for (i = 0; i < len; i++) { 223296465Sdelphij if (!isascii(dnsname[i])) 224296465Sdelphij errx(1, "Domain name has non-ascii char"); 225160814Ssimon if (isupper(dnsname[i])) 226296465Sdelphij dnsname[i] = tolower(dnsname[i]); 227296465Sdelphij } 228296465Sdelphij 229296465Sdelphij /* 230296465Sdelphij * If the nfsuserd died off ungracefully, this is necessary to 231296465Sdelphij * get them to start again. 232296465Sdelphij */ 233296465Sdelphij if (forcestart && nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) 234296465Sdelphij errx(1, "Can't do nfssvc() to delete the port"); 23559191Skris 236 if (verbose) 237 fprintf(stderr, 238 "nfsuserd: domain=%s usermax=%d usertimeout=%d\n", 239 dnsname, nid.nid_usermax, nid.nid_usertimeout); 240 241 for (i = 0; i < nfsuserdcnt; i++) 242 slaves[i] = (pid_t)-1; 243 244 /* 245 * Set up the service port to accept requests via UDP from 246 * localhost (127.0.0.1). 247 */ 248 if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 249 err(1, "cannot create udp socket"); 250 251 /* 252 * Not sure what this does, so I'll leave it here for now. 253 */ 254 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 255 256 if ((udptransp = svcudp_create(sock)) == NULL) 257 err(1, "Can't set up socket"); 258 259 /* 260 * By not specifying a protocol, it is linked into the 261 * dispatch queue, but not registered with portmapper, 262 * which is just what I want. 263 */ 264 if (!svc_register(udptransp, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, 265 nfsuserdsrv, 0)) 266 err(1, "Can't register nfsuserd"); 267 268 /* 269 * Tell the kernel what my port# is. 270 */ 271 portnum = htons(udptransp->xp_port); 272#ifdef DEBUG 273 printf("portnum=0x%x\n", portnum); 274#else 275 if (nfssvc(NFSSVC_NFSUSERDPORT, (caddr_t)&portnum) < 0) { 276 if (errno == EPERM) { 277 fprintf(stderr, 278 "Can't start nfsuserd when already running"); 279 fprintf(stderr, 280 " If not running, use the -force option.\n"); 281 } else { 282 fprintf(stderr, "Can't do nfssvc() to add port\n"); 283 } 284 exit(1); 285 } 286#endif 287 288 pwd = getpwnam(defaultuser); 289 if (pwd) 290 nid.nid_uid = pwd->pw_uid; 291 else 292 nid.nid_uid = defaultuid; 293 grp = getgrnam(defaultgroup); 294 if (grp) 295 nid.nid_gid = grp->gr_gid; 296 else 297 nid.nid_gid = defaultgid; 298 nid.nid_name = dnsname; 299 nid.nid_namelen = strlen(nid.nid_name); 300 nid.nid_flag = NFSID_INITIALIZE; 301#ifdef DEBUG 302 printf("Initialize uid=%d gid=%d dns=%s\n", nid.nid_uid, nid.nid_gid, 303 nid.nid_name); 304#else 305 error = nfssvc(NFSSVC_IDNAME, &nid); 306 if (error) 307 errx(1, "Can't initialize nfs user/groups"); 308#endif 309 310 i = 0; 311 /* 312 * Loop around adding all groups. 313 */ 314 setgrent(); 315 while (i < nid.nid_usermax && (grp = getgrent())) { 316 nid.nid_gid = grp->gr_gid; 317 nid.nid_name = grp->gr_name; 318 nid.nid_namelen = strlen(grp->gr_name); 319 nid.nid_flag = NFSID_ADDGID; 320#ifdef DEBUG 321 printf("add gid=%d name=%s\n", nid.nid_gid, nid.nid_name); 322#else 323 error = nfssvc(NFSSVC_IDNAME, &nid); 324 if (error) 325 errx(1, "Can't add group %s", grp->gr_name); 326#endif 327 i++; 328 } 329 330 /* 331 * Loop around adding all users. 332 */ 333 start_uidpos = i; 334 setpwent(); 335 while (i < nid.nid_usermax && (pwd = getpwent())) { 336 fnd_dup = 0; 337 /* 338 * Yes, this is inefficient, but it is only done once when 339 * the daemon is started and will run in a fraction of a second 340 * for nid_usermax at 10000. If nid_usermax is cranked up to 341 * 100000, it will take several seconds, depending on the CPU. 342 */ 343 for (j = 0; j < (i - start_uidpos); j++) 344 if (check_dups[j] == pwd->pw_uid) { 345 /* Found another entry for uid, so skip it */ 346 fnd_dup = 1; 347 break; 348 } 349 if (fnd_dup != 0) 350 continue; 351 check_dups[i - start_uidpos] = pwd->pw_uid; 352 nid.nid_uid = pwd->pw_uid; 353 nid.nid_name = pwd->pw_name; 354 nid.nid_namelen = strlen(pwd->pw_name); 355 nid.nid_flag = NFSID_ADDUID; 356#ifdef DEBUG 357 printf("add uid=%d name=%s\n", nid.nid_uid, nid.nid_name); 358#else 359 error = nfssvc(NFSSVC_IDNAME, &nid); 360 if (error) 361 errx(1, "Can't add user %s", pwd->pw_name); 362#endif 363 i++; 364 } 365 366 /* 367 * I should feel guilty for not calling this for all the above exit() 368 * upon error cases, but I don't. 369 */ 370 if (mustfreeai) 371 freeaddrinfo(aip); 372 373#ifdef DEBUG 374 exit(0); 375#endif 376 /* 377 * Temporarily block SIGUSR1 and SIGCHLD, so slaves[] can't 378 * end up bogus. 379 */ 380 sigemptyset(&signew); 381 sigaddset(&signew, SIGUSR1); 382 sigaddset(&signew, SIGCHLD); 383 sigprocmask(SIG_BLOCK, &signew, NULL); 384 385 daemon(0, 0); 386 (void)signal(SIGHUP, SIG_IGN); 387 (void)signal(SIGINT, SIG_IGN); 388 (void)signal(SIGQUIT, SIG_IGN); 389 (void)signal(SIGTERM, SIG_IGN); 390 (void)signal(SIGUSR1, cleanup_term); 391 (void)signal(SIGCHLD, cleanup_term); 392 393 openlog("nfsuserd:", LOG_PID, LOG_DAEMON); 394 395 /* 396 * Fork off the slave daemons that do the work. All the master 397 * does is kill them off and cleanup. 398 */ 399 for (i = 0; i < nfsuserdcnt; i++) { 400 slaves[i] = fork(); 401 if (slaves[i] == 0) { 402 im_a_slave = 1; 403 setproctitle("slave"); 404 sigemptyset(&signew); 405 sigaddset(&signew, SIGUSR1); 406 sigprocmask(SIG_UNBLOCK, &signew, NULL); 407 408 /* 409 * and away we go. 410 */ 411 svc_run(); 412 syslog(LOG_ERR, "nfsuserd died: %m"); 413 exit(1); 414 } else if (slaves[i] < 0) { 415 syslog(LOG_ERR, "fork: %m"); 416 } 417 } 418 419 /* 420 * Just wait for SIGUSR1 or a child to die and then... 421 * As the Governor of California would say, "Terminate them". 422 */ 423 setproctitle("master"); 424 sigemptyset(&signew); 425 while (1) 426 sigsuspend(&signew); 427} 428 429/* 430 * The nfsuserd rpc service 431 */ 432static void 433nfsuserdsrv(struct svc_req *rqstp, SVCXPRT *transp) 434{ 435 struct passwd *pwd; 436 struct group *grp; 437 int error; 438 u_short sport; 439 struct info info; 440 struct nfsd_idargs nid; 441 u_int32_t saddr; 442 443 /* 444 * Only handle requests from 127.0.0.1 on a reserved port number. 445 * (Since a reserved port # at localhost implies a client with 446 * local root, there won't be a security breach. This is about 447 * the only case I can think of where a reserved port # means 448 * something.) 449 */ 450 sport = ntohs(transp->xp_raddr.sin_port); 451 saddr = ntohl(transp->xp_raddr.sin_addr.s_addr); 452 if ((rqstp->rq_proc != NULLPROC && sport >= IPPORT_RESERVED) || 453 saddr != 0x7f000001) { 454 syslog(LOG_ERR, "req from ip=0x%x port=%d\n", saddr, sport); 455 svcerr_weakauth(transp); 456 return; 457 } 458 switch (rqstp->rq_proc) { 459 case NULLPROC: 460 if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 461 syslog(LOG_ERR, "Can't send reply"); 462 return; 463 case RPCNFSUSERD_GETUID: 464 if (!svc_getargs(transp, (xdrproc_t)xdr_getid, 465 (caddr_t)&info)) { 466 svcerr_decode(transp); 467 return; 468 } 469 pwd = getpwuid((uid_t)info.id); 470 info.retval = 0; 471 if (pwd != NULL) { 472 nid.nid_usertimeout = defusertimeout; 473 nid.nid_uid = pwd->pw_uid; 474 nid.nid_name = pwd->pw_name; 475 } else { 476 nid.nid_usertimeout = 5; 477 nid.nid_uid = (uid_t)info.id; 478 nid.nid_name = defaultuser; 479 } 480 nid.nid_namelen = strlen(nid.nid_name); 481 nid.nid_flag = NFSID_ADDUID; 482 error = nfssvc(NFSSVC_IDNAME, &nid); 483 if (error) { 484 info.retval = error; 485 syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); 486 } else if (verbose) { 487 syslog(LOG_ERR,"Added uid=%d name=%s\n", 488 nid.nid_uid, nid.nid_name); 489 } 490 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 491 (caddr_t)&info)) 492 syslog(LOG_ERR, "Can't send reply"); 493 return; 494 case RPCNFSUSERD_GETGID: 495 if (!svc_getargs(transp, (xdrproc_t)xdr_getid, 496 (caddr_t)&info)) { 497 svcerr_decode(transp); 498 return; 499 } 500 grp = getgrgid((gid_t)info.id); 501 info.retval = 0; 502 if (grp != NULL) { 503 nid.nid_usertimeout = defusertimeout; 504 nid.nid_gid = grp->gr_gid; 505 nid.nid_name = grp->gr_name; 506 } else { 507 nid.nid_usertimeout = 5; 508 nid.nid_gid = (gid_t)info.id; 509 nid.nid_name = defaultgroup; 510 } 511 nid.nid_namelen = strlen(nid.nid_name); 512 nid.nid_flag = NFSID_ADDGID; 513 error = nfssvc(NFSSVC_IDNAME, &nid); 514 if (error) { 515 info.retval = error; 516 syslog(LOG_ERR, "Can't add group %s\n", 517 grp->gr_name); 518 } else if (verbose) { 519 syslog(LOG_ERR,"Added gid=%d name=%s\n", 520 nid.nid_gid, nid.nid_name); 521 } 522 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 523 (caddr_t)&info)) 524 syslog(LOG_ERR, "Can't send reply"); 525 return; 526 case RPCNFSUSERD_GETUSER: 527 if (!svc_getargs(transp, (xdrproc_t)xdr_getname, 528 (caddr_t)&info)) { 529 svcerr_decode(transp); 530 return; 531 } 532 pwd = getpwnam(info.name); 533 info.retval = 0; 534 if (pwd != NULL) { 535 nid.nid_usertimeout = defusertimeout; 536 nid.nid_uid = pwd->pw_uid; 537 nid.nid_name = pwd->pw_name; 538 } else { 539 nid.nid_usertimeout = 5; 540 nid.nid_uid = defaultuid; 541 nid.nid_name = info.name; 542 } 543 nid.nid_namelen = strlen(nid.nid_name); 544 nid.nid_flag = NFSID_ADDUSERNAME; 545 error = nfssvc(NFSSVC_IDNAME, &nid); 546 if (error) { 547 info.retval = error; 548 syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name); 549 } else if (verbose) { 550 syslog(LOG_ERR,"Added uid=%d name=%s\n", 551 nid.nid_uid, nid.nid_name); 552 } 553 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 554 (caddr_t)&info)) 555 syslog(LOG_ERR, "Can't send reply"); 556 return; 557 case RPCNFSUSERD_GETGROUP: 558 if (!svc_getargs(transp, (xdrproc_t)xdr_getname, 559 (caddr_t)&info)) { 560 svcerr_decode(transp); 561 return; 562 } 563 grp = getgrnam(info.name); 564 info.retval = 0; 565 if (grp != NULL) { 566 nid.nid_usertimeout = defusertimeout; 567 nid.nid_gid = grp->gr_gid; 568 nid.nid_name = grp->gr_name; 569 } else { 570 nid.nid_usertimeout = 5; 571 nid.nid_gid = defaultgid; 572 nid.nid_name = info.name; 573 } 574 nid.nid_namelen = strlen(nid.nid_name); 575 nid.nid_flag = NFSID_ADDGROUPNAME; 576 error = nfssvc(NFSSVC_IDNAME, &nid); 577 if (error) { 578 info.retval = error; 579 syslog(LOG_ERR, "Can't add group %s\n", 580 grp->gr_name); 581 } else if (verbose) { 582 syslog(LOG_ERR,"Added gid=%d name=%s\n", 583 nid.nid_gid, nid.nid_name); 584 } 585 if (!svc_sendreply(transp, (xdrproc_t)xdr_retval, 586 (caddr_t)&info)) 587 syslog(LOG_ERR, "Can't send reply"); 588 return; 589 default: 590 svcerr_noproc(transp); 591 return; 592 }; 593} 594 595/* 596 * Xdr routine to get an id number 597 */ 598static bool_t 599xdr_getid(XDR *xdrsp, caddr_t cp) 600{ 601 struct info *ifp = (struct info *)cp; 602 603 return (xdr_long(xdrsp, &ifp->id)); 604} 605 606/* 607 * Xdr routine to get a user name 608 */ 609static bool_t 610xdr_getname(XDR *xdrsp, caddr_t cp) 611{ 612 struct info *ifp = (struct info *)cp; 613 long len; 614 615 if (!xdr_long(xdrsp, &len)) 616 return (0); 617 if (len > MAXNAME) 618 return (0); 619 if (!xdr_opaque(xdrsp, ifp->name, len)) 620 return (0); 621 ifp->name[len] = '\0'; 622 return (1); 623} 624 625/* 626 * Xdr routine to return the value. 627 */ 628static bool_t 629xdr_retval(XDR *xdrsp, caddr_t cp) 630{ 631 struct info *ifp = (struct info *)cp; 632 long val; 633 634 val = ifp->retval; 635 return (xdr_long(xdrsp, &val)); 636} 637 638/* 639 * cleanup_term() called via SIGUSR1. 640 */ 641static void 642cleanup_term(int signo __unused) 643{ 644 int i, cnt; 645 646 if (im_a_slave) 647 exit(0); 648 649 /* 650 * Ok, so I'm the master. 651 * As the Governor of California might say, "Terminate them". 652 */ 653 cnt = 0; 654 for (i = 0; i < nfsuserdcnt; i++) { 655 if (slaves[i] != (pid_t)-1) { 656 cnt++; 657 kill(slaves[i], SIGUSR1); 658 } 659 } 660 661 /* 662 * and wait for them to die 663 */ 664 for (i = 0; i < cnt; i++) 665 wait3(NULL, 0, NULL); 666 667 /* 668 * Finally, get rid of the socket 669 */ 670 if (nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) { 671 syslog(LOG_ERR, "Can't do nfssvc() to delete the port\n"); 672 exit(1); 673 } 674 exit(0); 675} 676 677static void 678usage(void) 679{ 680 681 errx(1, 682 "usage: nfsuserd [-usermax cache_size] [-usertimeout minutes] [-verbose] [-domain domain_name] [n]"); 683} 684