nfsd.c revision 74800
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1989, 1993, 1994 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Rick Macklem at The University of Guelph. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 191558Srgrimes * California, Berkeley and its contributors. 201558Srgrimes * 4. Neither the name of the University nor the names of its contributors 211558Srgrimes * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 231558Srgrimes * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341558Srgrimes * SUCH DAMAGE. 351558Srgrimes */ 361558Srgrimes 371558Srgrimes#ifndef lint 3837666Scharnierstatic const char copyright[] = 391558Srgrimes"@(#) Copyright (c) 1989, 1993, 1994\n\ 401558Srgrimes The Regents of the University of California. All rights reserved.\n"; 411558Srgrimes#endif not lint 421558Srgrimes 431558Srgrimes#ifndef lint 4437666Scharnier#if 0 4523684Speterstatic char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 4637666Scharnier#endif 4737666Scharnierstatic const char rcsid[] = 4850476Speter "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 74800 2001-03-25 23:32:55Z alfred $"; 491558Srgrimes#endif not lint 501558Srgrimes 511558Srgrimes#include <sys/param.h> 521558Srgrimes#include <sys/syslog.h> 531558Srgrimes#include <sys/wait.h> 541558Srgrimes#include <sys/mount.h> 551558Srgrimes 561558Srgrimes#include <rpc/rpc.h> 571558Srgrimes#include <rpc/pmap_clnt.h> 581558Srgrimes 5953096Sdillon#include <netdb.h> 6053096Sdillon#include <arpa/inet.h> 611558Srgrimes#include <nfs/rpcv2.h> 629336Sdfr#include <nfs/nfsproto.h> 631558Srgrimes#include <nfs/nfs.h> 641558Srgrimes 659336Sdfr#ifdef NFSKERB 6623684Speter#include <kerberosIV/des.h> 671558Srgrimes#include <kerberosIV/krb.h> 681558Srgrimes#endif 691558Srgrimes 701558Srgrimes#include <err.h> 711558Srgrimes#include <errno.h> 721558Srgrimes#include <stdio.h> 731558Srgrimes#include <stdlib.h> 741558Srgrimes#include <strings.h> 751558Srgrimes#include <unistd.h> 7674462Salfred#include <netdb.h> 771558Srgrimes 781558Srgrimes/* Global defs */ 791558Srgrimes#ifdef DEBUG 801558Srgrimes#define syslog(e, s) fprintf(stderr,(s)) 811558Srgrimesint debug = 1; 821558Srgrimes#else 831558Srgrimesint debug = 0; 841558Srgrimes#endif 851558Srgrimes 861558Srgrimesstruct nfsd_srvargs nsd; 8713141Speter#ifdef OLD_SETPROCTITLE 881558Srgrimeschar **Argv = NULL; /* pointer to argument vector */ 891558Srgrimeschar *LastArg = NULL; /* end of argv */ 9013141Speter#endif 911558Srgrimes 929336Sdfr#ifdef NFSKERB 931558Srgrimeschar lnam[ANAME_SZ]; 941558SrgrimesKTEXT_ST kt; 959336SdfrAUTH_DAT kauth; 961558Srgrimeschar inst[INST_SZ]; 979336Sdfrstruct nfsrpc_fullblock kin, kout; 989336Sdfrstruct nfsrpc_fullverf kverf; 999336SdfrNFSKERBKEY_T kivec; 1009336Sdfrstruct timeval ktv; 1019336SdfrNFSKERBKEYSCHED_T kerb_keysched; 1021558Srgrimes#endif 1031558Srgrimes 10474462Salfred#define MAXNFSDCNT 20 10574462Salfred#define DEFNFSDCNT 4 10674462Salfredpid_t children[MAXNFSDCNT]; /* PIDs of children */ 10774462Salfredint nfsdcnt; /* number of children */ 10874462Salfred 10974462Salfredvoid cleanup(int); 11074462Salfredvoid killchildren(void); 11174462Salfredvoid nonfs (int); 11274462Salfredvoid reapchild (int); 11374462Salfredint setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints); 11413141Speter#ifdef OLD_SETPROCTITLE 1159336Sdfr#ifdef __FreeBSD__ 11674462Salfredvoid setproctitle (char *); 1179336Sdfr#endif 11813141Speter#endif 11974462Salfredvoid unregistration (void); 12074462Salfredvoid usage (void); 1211558Srgrimes 1221558Srgrimes/* 1231558Srgrimes * Nfs server daemon mostly just a user context for nfssvc() 1241558Srgrimes * 1251558Srgrimes * 1 - do file descriptor and signal cleanup 1261558Srgrimes * 2 - fork the nfsd(s) 1271558Srgrimes * 3 - create server socket(s) 12874462Salfred * 4 - register socket with rpcbind 1291558Srgrimes * 1301558Srgrimes * For connectionless protocols, just pass the socket into the kernel via. 1311558Srgrimes * nfssvc(). 1321558Srgrimes * For connection based sockets, loop doing accepts. When you get a new 1331558Srgrimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1341558Srgrimes * The arguments are: 1351558Srgrimes * -c - support iso cltp clients 13674462Salfred * -r - reregister with rpcbind 13774462Salfred * -d - unregister with rpcbind 1381558Srgrimes * -t - support tcp nfs clients 1391558Srgrimes * -u - support udp nfs clients 1401558Srgrimes * followed by "n" which is the number of nfsds' to fork off 1411558Srgrimes */ 1421558Srgrimesint 1431558Srgrimesmain(argc, argv, envp) 1441558Srgrimes int argc; 1451558Srgrimes char *argv[], *envp[]; 1461558Srgrimes{ 1471558Srgrimes struct nfsd_args nfsdargs; 14874462Salfred struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 14974462Salfred struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 15074462Salfred struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 15174462Salfred struct sockaddr_in inetpeer; 15274462Salfred struct sockaddr_in6 inet6peer; 1531558Srgrimes fd_set ready, sockbits; 15474462Salfred fd_set v4bits, v6bits; 1551558Srgrimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 15674462Salfred int nfssvc_flag, on = 1, unregister, reregister, sock; 15774462Salfred int tcp6sock, ip6flag, tcpflag, tcpsock; 15874462Salfred int udpflag, ecode, s; 15974462Salfred int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt; 16053096Sdillon char **bindhost = NULL; 16174462Salfred pid_t pid; 16237666Scharnier#ifdef NFSKERB 16337666Scharnier struct group *grp; 16437666Scharnier struct passwd *pwd; 16537666Scharnier struct ucred *cr; 16637666Scharnier struct timeval ktv; 16737666Scharnier char **cpp; 16837666Scharnier#endif 1699336Sdfr#ifdef __FreeBSD__ 17023684Speter struct vfsconf vfc; 17123684Speter int error; 1721558Srgrimes 17323684Speter error = getvfsbyname("nfs", &vfc); 17423684Speter if (error && vfsisloadable("nfs")) { 17523684Speter if (vfsload("nfs")) 1762999Swollman err(1, "vfsload(nfs)"); 1772999Swollman endvfsent(); /* flush cache */ 17823684Speter error = getvfsbyname("nfs", &vfc); 1792999Swollman } 18023684Speter if (error) 1812999Swollman errx(1, "NFS is not available in the running kernel"); 1829336Sdfr#endif 1832999Swollman 18413141Speter#ifdef OLD_SETPROCTITLE 1851558Srgrimes /* Save start and extent of argv for setproctitle. */ 1861558Srgrimes Argv = argv; 1871558Srgrimes if (envp == 0 || *envp == 0) 1881558Srgrimes envp = argv; 1891558Srgrimes while (*envp) 1901558Srgrimes envp++; 1911558Srgrimes LastArg = envp[-1] + strlen(envp[-1]); 19213141Speter#endif 1931558Srgrimes 1941558Srgrimes nfsdcnt = DEFNFSDCNT; 19574462Salfred cltpflag = unregister = reregister = tcpflag = 0; 19674800Salfred bindanyflag = udpflag; 19774462Salfred#define GETOPT "ah:n:rdtu" 19874462Salfred#define USAGE "[-ardtu] [-n num_servers] [-h bindip]" 19924359Simp while ((ch = getopt(argc, argv, GETOPT)) != -1) 2001558Srgrimes switch (ch) { 20153096Sdillon case 'a': 20253096Sdillon bindanyflag = 1; 20353096Sdillon break; 2041558Srgrimes case 'n': 2051558Srgrimes nfsdcnt = atoi(optarg); 2061558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 20731206Sjdp warnx("nfsd count %d; reset to %d", nfsdcnt, 20831206Sjdp DEFNFSDCNT); 2091558Srgrimes nfsdcnt = DEFNFSDCNT; 2101558Srgrimes } 2111558Srgrimes break; 21253096Sdillon case 'h': 21353096Sdillon bindhostc++; 21453096Sdillon bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 21553096Sdillon if (bindhost == NULL) 21653096Sdillon errx(1, "Out of memory"); 21753096Sdillon bindhost[bindhostc-1] = strdup(optarg); 21853096Sdillon if (bindhost[bindhostc-1] == NULL) 21953096Sdillon errx(1, "Out of memory"); 22053096Sdillon break; 2211558Srgrimes case 'r': 2221558Srgrimes reregister = 1; 2231558Srgrimes break; 22474462Salfred case 'd': 22574462Salfred unregister = 1; 22674462Salfred break; 2271558Srgrimes case 't': 2281558Srgrimes tcpflag = 1; 2291558Srgrimes break; 2301558Srgrimes case 'u': 2311558Srgrimes udpflag = 1; 2321558Srgrimes break; 2331558Srgrimes default: 2341558Srgrimes case '?': 2351558Srgrimes usage(); 2361558Srgrimes }; 23715496Sbde if (!tcpflag && !udpflag) 23815496Sbde udpflag = 1; 2391558Srgrimes argv += optind; 2401558Srgrimes argc -= optind; 2411558Srgrimes 2421558Srgrimes /* 2431558Srgrimes * XXX 2441558Srgrimes * Backward compatibility, trailing number is the count of daemons. 2451558Srgrimes */ 2461558Srgrimes if (argc > 1) 2471558Srgrimes usage(); 2481558Srgrimes if (argc == 1) { 2491558Srgrimes nfsdcnt = atoi(argv[0]); 2501558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 25131206Sjdp warnx("nfsd count %d; reset to %d", nfsdcnt, 25231206Sjdp DEFNFSDCNT); 2531558Srgrimes nfsdcnt = DEFNFSDCNT; 2541558Srgrimes } 2551558Srgrimes } 25674800Salfred 25774462Salfred ip6flag = 1; 25874462Salfred s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 25974800Salfred if (s == -1) { 26074800Salfred if (errno != EPROTONOSUPPORT) 26174800Salfred err(1, "socket"); 26274462Salfred ip6flag = 0; 26374800Salfred } else if (getnetconfigent("udp6") == NULL || 26474800Salfred getnetconfigent("tcp6") == NULL) { 26574800Salfred ip6flag = 0; 26674800Salfred } 26774800Salfred if (s != -1) 26874462Salfred close(s); 2691558Srgrimes 27053096Sdillon if (bindhostc == 0 || bindanyflag) { 27153096Sdillon bindhostc++; 27253096Sdillon bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 27353096Sdillon if (bindhost == NULL) 27453096Sdillon errx(1, "Out of memory"); 27553096Sdillon bindhost[bindhostc-1] = strdup("*"); 27653096Sdillon if (bindhost[bindhostc-1] == NULL) 27753096Sdillon errx(1, "Out of memory"); 27853096Sdillon } 27953096Sdillon 28074462Salfred if (unregister) { 28174462Salfred unregistration(); 28274462Salfred exit (0); 28374462Salfred } 2841558Srgrimes if (reregister) { 28574462Salfred if (udpflag) { 28674462Salfred memset(&hints, 0, sizeof hints); 28774462Salfred hints.ai_flags = AI_PASSIVE; 28874462Salfred hints.ai_family = AF_INET; 28974462Salfred hints.ai_socktype = SOCK_DGRAM; 29074462Salfred hints.ai_protocol = IPPROTO_UDP; 29174462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 29274800Salfred if (ecode != 0) 29374800Salfred err(1, "getaddrinfo udp: %s", gai_strerror(ecode)); 29474462Salfred nconf_udp = getnetconfigent("udp"); 29574462Salfred if (nconf_udp == NULL) 29674462Salfred err(1, "getnetconfigent udp failed"); 29774462Salfred nb_udp.buf = ai_udp->ai_addr; 29874462Salfred nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 29974462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 30074462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 30174462Salfred err(1, "rpcb_set udp failed"); 30274462Salfred freeaddrinfo(ai_udp); 30374462Salfred } 30474462Salfred if (udpflag && ip6flag) { 30574462Salfred memset(&hints, 0, sizeof hints); 30674462Salfred hints.ai_flags = AI_PASSIVE; 30774462Salfred hints.ai_family = AF_INET6; 30874462Salfred hints.ai_socktype = SOCK_DGRAM; 30974462Salfred hints.ai_protocol = IPPROTO_UDP; 31074462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 31174800Salfred if (ecode != 0) 31274800Salfred err(1, "getaddrinfo udp6: %s", gai_strerror(ecode)); 31374462Salfred nconf_udp6 = getnetconfigent("udp6"); 31474462Salfred if (nconf_udp6 == NULL) 31574462Salfred err(1, "getnetconfigent udp6 failed"); 31674462Salfred nb_udp6.buf = ai_udp6->ai_addr; 31774462Salfred nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 31874462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 31974462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 32074462Salfred err(1, "rpcb_set udp6 failed"); 32174462Salfred freeaddrinfo(ai_udp6); 32274462Salfred } 32374462Salfred if (tcpflag) { 32474462Salfred memset(&hints, 0, sizeof hints); 32574462Salfred hints.ai_flags = AI_PASSIVE; 32674462Salfred hints.ai_family = AF_INET; 32774462Salfred hints.ai_socktype = SOCK_STREAM; 32874462Salfred hints.ai_protocol = IPPROTO_TCP; 32974462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); 33074800Salfred if (ecode != 0) 33174800Salfred err(1, "getaddrinfo tcp: %s", gai_strerror(ecode)); 33274462Salfred nconf_tcp = getnetconfigent("tcp"); 33374462Salfred if (nconf_tcp == NULL) 33474462Salfred err(1, "getnetconfigent tcp failed"); 33574462Salfred nb_tcp.buf = ai_tcp->ai_addr; 33674462Salfred nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 33774462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || 33874462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) 33974462Salfred err(1, "rpcb_set tcp failed"); 34074462Salfred freeaddrinfo(ai_tcp); 34174462Salfred } 34274462Salfred if (tcpflag && ip6flag) { 34374462Salfred memset(&hints, 0, sizeof hints); 34474462Salfred hints.ai_flags = AI_PASSIVE; 34574462Salfred hints.ai_family = AF_INET6; 34674462Salfred hints.ai_socktype = SOCK_STREAM; 34774462Salfred hints.ai_protocol = IPPROTO_TCP; 34874462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 34974800Salfred if (ecode != 0) 35074800Salfred err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode)); 35174462Salfred nconf_tcp6 = getnetconfigent("tcp6"); 35274462Salfred if (nconf_tcp6 == NULL) 35374462Salfred err(1, "getnetconfigent tcp6 failed"); 35474462Salfred nb_tcp6.buf = ai_tcp6->ai_addr; 35574462Salfred nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 35674462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 35774462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 35874462Salfred err(1, "rpcb_set tcp6 failed"); 35974462Salfred freeaddrinfo(ai_tcp6); 36074462Salfred } 36174462Salfred exit (0); 3621558Srgrimes } 36374800Salfred if (debug == 0) { 36474800Salfred daemon(0, 0); 36574800Salfred (void)signal(SIGHUP, SIG_IGN); 36674800Salfred (void)signal(SIGINT, SIG_IGN); 36774800Salfred (void)signal(SIGSYS, nonfs); 36874800Salfred (void)signal(SIGUSR1, cleanup); 36974800Salfred /* 37074800Salfred * nfsd sits in the kernel most of the time. It needs 37174800Salfred * to ignore SIGTERM/SIGQUIT in order to stay alive as long 37274800Salfred * as possible during a shutdown, otherwise loopback 37374800Salfred * mounts will not be able to unmount. 37474800Salfred */ 37574800Salfred (void)signal(SIGTERM, SIG_IGN); 37674800Salfred (void)signal(SIGQUIT, SIG_IGN); 37774800Salfred } 37874800Salfred (void)signal(SIGCHLD, reapchild); 37974462Salfred 3801558Srgrimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 3811558Srgrimes 3821558Srgrimes for (i = 0; i < nfsdcnt; i++) { 38374462Salfred switch ((pid = fork())) { 3841558Srgrimes case -1: 3851558Srgrimes syslog(LOG_ERR, "fork: %m"); 38674462Salfred killchildren(); 3871558Srgrimes exit (1); 3881558Srgrimes case 0: 3891558Srgrimes break; 3901558Srgrimes default: 39174462Salfred children[i] = pid; 3921558Srgrimes continue; 3931558Srgrimes } 3941558Srgrimes 3959336Sdfr setproctitle("server"); 3961558Srgrimes nfssvc_flag = NFSSVC_NFSD; 3971558Srgrimes nsd.nsd_nfsd = NULL; 3989336Sdfr#ifdef NFSKERB 3999336Sdfr if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 4009336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 4019336Sdfr syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 4029336Sdfr nsd.nsd_authstr = (u_char *)&kt; 4039336Sdfr nsd.nsd_authlen = sizeof (kt); 4049336Sdfr nsd.nsd_verfstr = (u_char *)&kverf; 4059336Sdfr nsd.nsd_verflen = sizeof (kverf); 4061558Srgrimes#endif 4071558Srgrimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 4081558Srgrimes if (errno != ENEEDAUTH) { 4091558Srgrimes syslog(LOG_ERR, "nfssvc: %m"); 4101558Srgrimes exit(1); 4111558Srgrimes } 4121558Srgrimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 4139336Sdfr#ifdef NFSKERB 4149336Sdfr /* 4159336Sdfr * Get the Kerberos ticket out of the authenticator 4169336Sdfr * verify it and convert the principal name to a user 4179336Sdfr * name. The user name is then converted to a set of 4189336Sdfr * user credentials via the password and group file. 4199336Sdfr * Finally, decrypt the timestamp and validate it. 4209336Sdfr * For more info see the IETF Draft "Authentication 4219336Sdfr * in ONC RPC". 4229336Sdfr */ 4239336Sdfr kt.length = ntohl(kt.length); 4249336Sdfr if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 4259336Sdfr kt.length > 0 && kt.length <= 4269336Sdfr (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 4279336Sdfr kin.w1 = NFS_KERBW1(kt); 4289336Sdfr kt.mbz = 0; 4299336Sdfr (void)strcpy(inst, "*"); 4309336Sdfr if (krb_rd_req(&kt, NFS_KERBSRV, 4319336Sdfr inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 4329336Sdfr krb_kntoln(&kauth, lnam) == KSUCCESS && 4339336Sdfr (pwd = getpwnam(lnam)) != NULL) { 4341558Srgrimes cr = &nsd.nsd_cr; 4351558Srgrimes cr->cr_uid = pwd->pw_uid; 4361558Srgrimes cr->cr_groups[0] = pwd->pw_gid; 4371558Srgrimes cr->cr_ngroups = 1; 4381558Srgrimes setgrent(); 4391558Srgrimes while ((grp = getgrent()) != NULL) { 4401558Srgrimes if (grp->gr_gid == cr->cr_groups[0]) 4411558Srgrimes continue; 4421558Srgrimes for (cpp = grp->gr_mem; 4431558Srgrimes *cpp != NULL; ++cpp) 4441558Srgrimes if (!strcmp(*cpp, lnam)) 4451558Srgrimes break; 4461558Srgrimes if (*cpp == NULL) 4471558Srgrimes continue; 4481558Srgrimes cr->cr_groups[cr->cr_ngroups++] 4491558Srgrimes = grp->gr_gid; 4501558Srgrimes if (cr->cr_ngroups == NGROUPS) 4511558Srgrimes break; 4521558Srgrimes } 4531558Srgrimes endgrent(); 4549336Sdfr 4559336Sdfr /* 4569336Sdfr * Get the timestamp verifier out of the 4579336Sdfr * authenticator and verifier strings. 4589336Sdfr */ 4599336Sdfr kin.t1 = kverf.t1; 4609336Sdfr kin.t2 = kverf.t2; 4619336Sdfr kin.w2 = kverf.w2; 4629336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 4639336Sdfr bcopy((caddr_t)kauth.session, 4649336Sdfr (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 4659336Sdfr 4669336Sdfr /* 4679336Sdfr * Decrypt the timestamp verifier in CBC mode. 4689336Sdfr */ 4699336Sdfr XXX 4709336Sdfr 4719336Sdfr /* 4729336Sdfr * Validate the timestamp verifier, to 4739336Sdfr * check that the session key is ok. 4749336Sdfr */ 4759336Sdfr nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 4769336Sdfr nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 4779336Sdfr nsd.nsd_ttl = ntohl(kout.w1); 4789336Sdfr if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 4799336Sdfr nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 4801558Srgrimes } 4819336Sdfr#endif /* NFSKERB */ 4821558Srgrimes } 4831558Srgrimes exit(0); 4841558Srgrimes } 4851558Srgrimes 48674462Salfred if (atexit(killchildren) == -1) { 48774462Salfred syslog(LOG_ERR, "atexit: %s", strerror(errno)); 48874462Salfred exit(1); 48974462Salfred } 49074462Salfred FD_ZERO(&v4bits); 49174462Salfred FD_ZERO(&v6bits); 49274462Salfred 49374462Salfred rpcbregcnt = 0; 49474462Salfred /* Set up the socket for udp and rpcb register it. */ 49574462Salfred if (udpflag) { 49674462Salfred rpcbreg = 0; 49774462Salfred for (i = 0; i < bindhostc; i++) { 49874462Salfred memset(&hints, 0, sizeof hints); 49974462Salfred hints.ai_flags = AI_PASSIVE; 50074462Salfred hints.ai_family = AF_INET; 50174462Salfred hints.ai_socktype = SOCK_DGRAM; 50274462Salfred hints.ai_protocol = IPPROTO_UDP; 50374462Salfred if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 50474462Salfred rpcbreg = 1; 50574462Salfred rpcbregcnt++; 50674462Salfred if ((sock = socket(ai_udp->ai_family, 50774462Salfred ai_udp->ai_socktype, 50874462Salfred ai_udp->ai_protocol)) < 0) { 50974462Salfred syslog(LOG_ERR, 51074462Salfred "can't create udp socket"); 51174462Salfred exit(1); 51274462Salfred } 51374462Salfred if (bind(sock, ai_udp->ai_addr, 51474462Salfred ai_udp->ai_addrlen) < 0) { 51574462Salfred syslog(LOG_ERR, 51674462Salfred "can't bind udp addr %s: %m", 51774462Salfred bindhost[i]); 51874462Salfred exit(1); 51974462Salfred } 52074462Salfred freeaddrinfo(ai_udp); 52174462Salfred nfsdargs.sock = sock; 52274462Salfred nfsdargs.name = NULL; 52374462Salfred nfsdargs.namelen = 0; 52474462Salfred if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 52574462Salfred syslog(LOG_ERR, "can't Add UDP socket"); 52674462Salfred exit(1); 52774462Salfred } 52874462Salfred (void)close(sock); 52974462Salfred } 5301558Srgrimes } 53174462Salfred if (rpcbreg == 1) { 53274462Salfred memset(&hints, 0, sizeof hints); 53374462Salfred hints.ai_flags = AI_PASSIVE; 53474462Salfred hints.ai_family = AF_INET; 53574462Salfred hints.ai_socktype = SOCK_DGRAM; 53674462Salfred hints.ai_protocol = IPPROTO_UDP; 53774462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 53874462Salfred if (ecode != 0) { 53974462Salfred syslog(LOG_ERR, "getaddrinfo udp: %s", 54074462Salfred gai_strerror(ecode)); 54174462Salfred exit(1); 54274462Salfred } 54374462Salfred nconf_udp = getnetconfigent("udp"); 54474462Salfred if (nconf_udp == NULL) 54574462Salfred err(1, "getnetconfigent udp failed"); 54674462Salfred nb_udp.buf = ai_udp->ai_addr; 54774462Salfred nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 54874462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 54974462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 55074462Salfred err(1, "rpcb_set udp failed"); 55174462Salfred freeaddrinfo(ai_udp); 5521558Srgrimes } 5531558Srgrimes } 5541558Srgrimes 55574462Salfred /* Set up the socket for udp6 and rpcb register it. */ 55674462Salfred if (udpflag && ip6flag) { 55774462Salfred rpcbreg = 0; 55874462Salfred for (i = 0; i < bindhostc; i++) { 55974462Salfred memset(&hints, 0, sizeof hints); 56074462Salfred hints.ai_flags = AI_PASSIVE; 56174462Salfred hints.ai_family = AF_INET6; 56274462Salfred hints.ai_socktype = SOCK_DGRAM; 56374462Salfred hints.ai_protocol = IPPROTO_UDP; 56474462Salfred if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 56574462Salfred rpcbreg = 1; 56674462Salfred rpcbregcnt++; 56774462Salfred if ((sock = socket(ai_udp6->ai_family, 56874462Salfred ai_udp6->ai_socktype, 56974462Salfred ai_udp6->ai_protocol)) < 0) { 57074462Salfred syslog(LOG_ERR, 57174462Salfred "can't create udp6 socket"); 57274462Salfred exit(1); 57374462Salfred } 57474462Salfred if (setsockopt(sock, IPPROTO_IPV6, 57574462Salfred IPV6_BINDV6ONLY, 57674462Salfred &on, sizeof on) < 0) { 57774462Salfred syslog(LOG_ERR, 57874462Salfred "can't set v6-only binding for " 57974462Salfred "udp6 socket: %m"); 58074462Salfred exit(1); 58174462Salfred } 58274462Salfred if (bind(sock, ai_udp6->ai_addr, 58374462Salfred ai_udp6->ai_addrlen) < 0) { 58474462Salfred syslog(LOG_ERR, 58574462Salfred "can't bind udp6 addr %s: %m", 58674462Salfred bindhost[i]); 58774462Salfred exit(1); 58874462Salfred } 58974462Salfred freeaddrinfo(ai_udp6); 59074462Salfred nfsdargs.sock = sock; 59174462Salfred nfsdargs.name = NULL; 59274462Salfred nfsdargs.namelen = 0; 59374462Salfred if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 59474462Salfred syslog(LOG_ERR, 59574462Salfred "can't add UDP6 socket"); 59674462Salfred exit(1); 59774462Salfred } 59874462Salfred (void)close(sock); 59974462Salfred } 6001558Srgrimes } 60174462Salfred if (rpcbreg == 1) { 60274462Salfred memset(&hints, 0, sizeof hints); 60374462Salfred hints.ai_flags = AI_PASSIVE; 60474462Salfred hints.ai_family = AF_INET6; 60574462Salfred hints.ai_socktype = SOCK_DGRAM; 60674462Salfred hints.ai_protocol = IPPROTO_UDP; 60774462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 60874462Salfred if (ecode != 0) { 60974462Salfred syslog(LOG_ERR, "getaddrinfo udp6: %s", 61074462Salfred gai_strerror(ecode)); 61174462Salfred exit(1); 61274462Salfred } 61374462Salfred nconf_udp6 = getnetconfigent("udp6"); 61474462Salfred if (nconf_udp6 == NULL) 61574462Salfred err(1, "getnetconfigent udp6 failed"); 61674462Salfred nb_udp6.buf = ai_udp6->ai_addr; 61774462Salfred nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 61874462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 61974462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 62074462Salfred err(1, "rpcb_set udp6 failed"); 62174462Salfred freeaddrinfo(ai_udp6); 6221558Srgrimes } 6231558Srgrimes } 6241558Srgrimes 62574462Salfred /* Set up the socket for tcp and rpcb register it. */ 62674462Salfred if (tcpflag) { 62774462Salfred rpcbreg = 0; 62874462Salfred for (i = 0; i < bindhostc; i++) { 62974462Salfred memset(&hints, 0, sizeof hints); 63074462Salfred hints.ai_flags = AI_PASSIVE; 63174462Salfred hints.ai_family = AF_INET; 63274462Salfred hints.ai_socktype = SOCK_STREAM; 63374462Salfred hints.ai_protocol = IPPROTO_TCP; 63474462Salfred if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 63574462Salfred rpcbreg = 1; 63674462Salfred rpcbregcnt++; 63774462Salfred if ((tcpsock = socket(AF_INET, SOCK_STREAM, 63874462Salfred 0)) < 0) { 63974462Salfred syslog(LOG_ERR, 64074462Salfred "can't create tpc socket"); 64174462Salfred exit(1); 64274462Salfred } 64374462Salfred if (setsockopt(tcpsock, SOL_SOCKET, 64474462Salfred SO_REUSEADDR, 64574462Salfred (char *)&on, sizeof(on)) < 0) 64674462Salfred syslog(LOG_ERR, 64774462Salfred "setsockopt SO_REUSEADDR: %m"); 64874462Salfred if (bind(tcpsock, ai_tcp->ai_addr, 64974462Salfred ai_tcp->ai_addrlen) < 0) { 65074462Salfred syslog(LOG_ERR, 65174462Salfred "can't bind tcp addr %s: %m", 65274462Salfred bindhost[i]); 65374462Salfred exit(1); 65474462Salfred } 65574462Salfred if (listen(tcpsock, 5) < 0) { 65674462Salfred syslog(LOG_ERR, "listen failed"); 65774462Salfred exit(1); 65874462Salfred } 65974462Salfred freeaddrinfo(ai_tcp); 66074462Salfred FD_SET(tcpsock, &sockbits); 66174462Salfred FD_SET(tcpsock, &v4bits); 66274462Salfred maxsock = tcpsock; 66374462Salfred connect_type_cnt++; 66474462Salfred } 6651558Srgrimes } 66674462Salfred if (rpcbreg == 1) { 66774462Salfred memset(&hints, 0, sizeof hints); 66874462Salfred hints.ai_flags = AI_PASSIVE; 66974462Salfred hints.ai_family = AF_INET; 67074462Salfred hints.ai_socktype = SOCK_STREAM; 67174462Salfred hints.ai_protocol = IPPROTO_TCP; 67274462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, 67374462Salfred &ai_tcp); 67474462Salfred if (ecode != 0) { 67574462Salfred syslog(LOG_ERR, "getaddrinfo tcp: %s", 67674462Salfred gai_strerror(ecode)); 67774462Salfred exit(1); 67874462Salfred } 67974462Salfred nconf_tcp = getnetconfigent("tcp"); 68074462Salfred if (nconf_tcp == NULL) 68174462Salfred err(1, "getnetconfigent tcp failed"); 68274462Salfred nb_tcp.buf = ai_tcp->ai_addr; 68374462Salfred nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 68474462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 68574462Salfred &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 68674462Salfred nconf_tcp, &nb_tcp))) 68774462Salfred err(1, "rpcb_set tcp failed"); 68874462Salfred freeaddrinfo(ai_tcp); 6891558Srgrimes } 6901558Srgrimes } 6911558Srgrimes 69274462Salfred /* Set up the socket for tcp6 and rpcb register it. */ 69374462Salfred if (tcpflag && ip6flag) { 69474462Salfred rpcbreg = 0; 69574462Salfred for (i = 0; i < bindhostc; i++) { 69674462Salfred memset(&hints, 0, sizeof hints); 69774462Salfred hints.ai_flags = AI_PASSIVE; 69874462Salfred hints.ai_family = AF_INET6; 69974462Salfred hints.ai_socktype = SOCK_STREAM; 70074462Salfred hints.ai_protocol = IPPROTO_TCP; 70174462Salfred if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 70274462Salfred rpcbreg = 1; 70374462Salfred rpcbregcnt++; 70474462Salfred if ((tcp6sock = socket(ai_tcp6->ai_family, 70574462Salfred ai_tcp6->ai_socktype, 70674462Salfred ai_tcp6->ai_protocol)) < 0) { 70774462Salfred syslog(LOG_ERR, 70874462Salfred "can't create tcp6 socket"); 70974462Salfred exit(1); 71074462Salfred } 71174462Salfred if (setsockopt(tcp6sock, SOL_SOCKET, 71274462Salfred SO_REUSEADDR, 71374462Salfred (char *)&on, sizeof(on)) < 0) 71474462Salfred syslog(LOG_ERR, 71574462Salfred "setsockopt SO_REUSEADDR: %m"); 71674462Salfred if (setsockopt(tcp6sock, IPPROTO_IPV6, 71774462Salfred IPV6_BINDV6ONLY, &on, sizeof on) < 0) { 71874462Salfred syslog(LOG_ERR, 71974462Salfred "can't set v6-only binding for tcp6 " 72074462Salfred "socket: %m"); 72174462Salfred exit(1); 72274462Salfred } 72374462Salfred if (bind(tcp6sock, ai_tcp6->ai_addr, 72474462Salfred ai_tcp6->ai_addrlen) < 0) { 72574462Salfred syslog(LOG_ERR, 72674462Salfred "can't bind tcp6 addr %s: %m", 72774462Salfred bindhost[i]); 72874462Salfred exit(1); 72974462Salfred } 73074462Salfred if (listen(tcp6sock, 5) < 0) { 73174462Salfred syslog(LOG_ERR, "listen failed"); 73274462Salfred exit(1); 73374462Salfred } 73474462Salfred freeaddrinfo(ai_tcp6); 73574462Salfred FD_SET(tcp6sock, &sockbits); 73674462Salfred FD_SET(tcp6sock, &v6bits); 73774462Salfred if (maxsock < tcp6sock) 73874462Salfred maxsock = tcp6sock; 73974462Salfred connect_type_cnt++; 74074462Salfred } 7411558Srgrimes } 74274462Salfred if (rpcbreg == 1) { 74374462Salfred memset(&hints, 0, sizeof hints); 74474462Salfred hints.ai_flags = AI_PASSIVE; 74574462Salfred hints.ai_family = AF_INET6; 74674462Salfred hints.ai_socktype = SOCK_STREAM; 74774462Salfred hints.ai_protocol = IPPROTO_TCP; 74874462Salfred ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 74974462Salfred if (ecode != 0) { 75074462Salfred syslog(LOG_ERR, "getaddrinfo tcp6: %s", 75174462Salfred gai_strerror(ecode)); 75274462Salfred exit(1); 75374462Salfred } 75474462Salfred nconf_tcp6 = getnetconfigent("tcp6"); 75574462Salfred if (nconf_tcp6 == NULL) 75674462Salfred err(1, "getnetconfigent tcp6 failed"); 75774462Salfred nb_tcp6.buf = ai_tcp6->ai_addr; 75874462Salfred nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 75974462Salfred if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 76074462Salfred (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 76174462Salfred err(1, "rpcb_set tcp6 failed"); 76274462Salfred freeaddrinfo(ai_tcp6); 7631558Srgrimes } 7641558Srgrimes } 7651558Srgrimes 76674462Salfred if (rpcbregcnt == 0) { 76774462Salfred syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 76874462Salfred exit(1); 7691558Srgrimes } 7701558Srgrimes 77174462Salfred if ((tcpflag) && (connect_type_cnt == 0)) { 77274462Salfred syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 77374462Salfred exit(1); 77474462Salfred } 7751558Srgrimes 7769336Sdfr setproctitle("master"); 7771558Srgrimes 7781558Srgrimes /* 7791558Srgrimes * Loop forever accepting connections and passing the sockets 7801558Srgrimes * into the kernel for the mounts. 7811558Srgrimes */ 7821558Srgrimes for (;;) { 7831558Srgrimes ready = sockbits; 7841558Srgrimes if (connect_type_cnt > 1) { 7851558Srgrimes if (select(maxsock + 1, 7861558Srgrimes &ready, NULL, NULL, NULL) < 1) { 7871558Srgrimes syslog(LOG_ERR, "select failed: %m"); 7881558Srgrimes exit(1); 7891558Srgrimes } 7901558Srgrimes } 79174462Salfred for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { 79274462Salfred if (FD_ISSET(tcpsock, &ready)) { 79374462Salfred if (FD_ISSET(tcpsock, &v4bits)) { 79474462Salfred len = sizeof(inetpeer); 79574462Salfred if ((msgsock = accept(tcpsock, 79674462Salfred (struct sockaddr *)&inetpeer, &len)) < 0) { 79774462Salfred syslog(LOG_ERR, "accept failed: %m"); 79874462Salfred exit(1); 79974462Salfred } 80074462Salfred memset(inetpeer.sin_zero, 0, 80174462Salfred sizeof(inetpeer.sin_zero)); 80274462Salfred if (setsockopt(msgsock, SOL_SOCKET, 80374462Salfred SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 80474462Salfred syslog(LOG_ERR, 80574462Salfred "setsockopt SO_KEEPALIVE: %m"); 80674462Salfred nfsdargs.sock = msgsock; 80774462Salfred nfsdargs.name = (caddr_t)&inetpeer; 80874462Salfred nfsdargs.namelen = sizeof(inetpeer); 80974462Salfred nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 81074462Salfred (void)close(msgsock); 81174462Salfred } else if (FD_ISSET(tcpsock, &v6bits)) { 81274462Salfred len = sizeof(inet6peer); 81374462Salfred if ((msgsock = accept(tcpsock, 81474462Salfred (struct sockaddr *)&inet6peer, 81574462Salfred &len)) < 0) { 81674462Salfred syslog(LOG_ERR, 81774462Salfred "accept failed: %m"); 81874462Salfred exit(1); 81974462Salfred } 82074462Salfred if (setsockopt(msgsock, SOL_SOCKET, 82174462Salfred SO_KEEPALIVE, (char *)&on, 82274462Salfred sizeof(on)) < 0) 82374462Salfred syslog(LOG_ERR, "setsockopt " 82474462Salfred "SO_KEEPALIVE: %m"); 82574462Salfred nfsdargs.sock = msgsock; 82674462Salfred nfsdargs.name = (caddr_t)&inet6peer; 82774462Salfred nfsdargs.namelen = sizeof(inet6peer); 82874462Salfred nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 82974462Salfred (void)close(msgsock); 83074462Salfred } 8311558Srgrimes } 8321558Srgrimes } 8331558Srgrimes } 8341558Srgrimes} 8351558Srgrimes 83674462Salfredint 83774462Salfredsetbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) 83853096Sdillon{ 83974462Salfred int ecode; 84074462Salfred u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 84174462Salfred const char *hostptr; 84253096Sdillon 84374462Salfred if (bindhost == NULL || strcmp("*", bindhost) == 0) 84474462Salfred hostptr = NULL; 84574462Salfred else 84674462Salfred hostptr = bindhost; 84774462Salfred 84874462Salfred if (hostptr != NULL) { 84974462Salfred switch (hints.ai_family) { 85074462Salfred case AF_INET: 85174462Salfred if (inet_pton(AF_INET, hostptr, host_addr) == 1) { 85274462Salfred hints.ai_flags = AI_NUMERICHOST; 85374462Salfred } else { 85474462Salfred if (inet_pton(AF_INET6, hostptr, 85574462Salfred host_addr) == 1) 85674462Salfred return (1); 85753096Sdillon } 85874462Salfred break; 85974462Salfred case AF_INET6: 86074462Salfred if (inet_pton(AF_INET6, hostptr, host_addr) == 1) { 86174462Salfred hints.ai_flags = AI_NUMERICHOST; 86274462Salfred } else { 86374462Salfred if (inet_pton(AF_INET, hostptr, 86474462Salfred host_addr) == 1) 86574462Salfred return (1); 86674462Salfred } 86774462Salfred break; 86874462Salfred default: 86953096Sdillon } 87053096Sdillon } 87174462Salfred 87274462Salfred ecode = getaddrinfo(hostptr, "nfs", &hints, ai); 87374462Salfred if (ecode != 0) { 87474462Salfred syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, 87574462Salfred gai_strerror(ecode)); 87674462Salfred return (1); 87774462Salfred } 87874462Salfred return (0); 87953096Sdillon} 88053096Sdillon 88153096Sdillonvoid 8821558Srgrimesusage() 8831558Srgrimes{ 8849336Sdfr (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 8851558Srgrimes exit(1); 8861558Srgrimes} 8871558Srgrimes 8881558Srgrimesvoid 8891558Srgrimesnonfs(signo) 8901558Srgrimes int signo; 8911558Srgrimes{ 89237666Scharnier syslog(LOG_ERR, "missing system call: NFS not available"); 8931558Srgrimes} 8941558Srgrimes 8951558Srgrimesvoid 8961558Srgrimesreapchild(signo) 8971558Srgrimes int signo; 8981558Srgrimes{ 8991558Srgrimes 9009336Sdfr while (wait3(NULL, WNOHANG, NULL) > 0); 9011558Srgrimes} 9021558Srgrimes 90374462Salfredvoid 90474462Salfredunregistration() 90574462Salfred{ 90674462Salfred if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 90774462Salfred (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 90874462Salfred syslog(LOG_ERR, "rpcb_unset failed"); 90974462Salfred} 91074462Salfred 91174462Salfredvoid 91274462Salfredkillchildren() 91374462Salfred{ 91474462Salfred int i; 91574462Salfred sigset_t sigs; 91674462Salfred 91774462Salfred sigemptyset(&sigs); 91874462Salfred /* 91974462Salfred * Block SIGCHLD to avoid killing a reaped process (although it is 92074462Salfred * unlikely, the pid might have been reused). 92174462Salfred */ 92274462Salfred sigaddset(&sigs, SIGCHLD); 92374462Salfred if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) { 92474462Salfred syslog(LOG_ERR, "sigprocmask: %s", 92574462Salfred strerror(errno)); 92674462Salfred return; 92774462Salfred } 92874462Salfred for (i = 0; i < nfsdcnt; i++) { 92974462Salfred if (children[i] > 0) 93074462Salfred kill(children[i], SIGKILL); 93174462Salfred } 93274462Salfred if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) { 93374462Salfred syslog(LOG_ERR, "sigprocmask: %s", strerror(errno)); 93474462Salfred } 93574462Salfred unregistration(); 93674462Salfred} 93774462Salfred 93874462Salfredvoid 93974462Salfredcleanup(signo) 94074462Salfred{ 94174462Salfred killchildren(); 94274462Salfred exit (0); 94374462Salfred} 94474462Salfred 94513141Speter#ifdef OLD_SETPROCTITLE 9469336Sdfr#ifdef __FreeBSD__ 9471558Srgrimesvoid 9481558Srgrimessetproctitle(a) 9491558Srgrimes char *a; 9501558Srgrimes{ 9511558Srgrimes register char *cp; 9521558Srgrimes char buf[80]; 9531558Srgrimes 9541558Srgrimes cp = Argv[0]; 9559336Sdfr (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 9561558Srgrimes (void)strncpy(cp, buf, LastArg - cp); 9571558Srgrimes cp += strlen(cp); 9581558Srgrimes while (cp < LastArg) 9592030Sdg *cp++ = '\0'; 96012869Speter Argv[1] = NULL; 9611558Srgrimes} 9629336Sdfr#endif /* __FreeBSD__ */ 96313141Speter#endif 964