103914b0bSRick Macklem /*-
203914b0bSRick Macklem * Copyright (c) 2009 Rick Macklem, University of Guelph
303914b0bSRick Macklem * All rights reserved.
403914b0bSRick Macklem *
503914b0bSRick Macklem * Redistribution and use in source and binary forms, with or without
603914b0bSRick Macklem * modification, are permitted provided that the following conditions
703914b0bSRick Macklem * are met:
803914b0bSRick Macklem * 1. Redistributions of source code must retain the above copyright
903914b0bSRick Macklem * notice, this list of conditions and the following disclaimer.
1003914b0bSRick Macklem * 2. Redistributions in binary form must reproduce the above copyright
1103914b0bSRick Macklem * notice, this list of conditions and the following disclaimer in the
1203914b0bSRick Macklem * documentation and/or other materials provided with the distribution.
1303914b0bSRick Macklem *
1403914b0bSRick Macklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1503914b0bSRick Macklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1603914b0bSRick Macklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1703914b0bSRick Macklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1803914b0bSRick Macklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1903914b0bSRick Macklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2003914b0bSRick Macklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2103914b0bSRick Macklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2203914b0bSRick Macklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2303914b0bSRick Macklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2403914b0bSRick Macklem * SUCH DAMAGE.
2503914b0bSRick Macklem *
2603914b0bSRick Macklem */
2703914b0bSRick Macklem
2803914b0bSRick Macklem #include <sys/param.h>
2903914b0bSRick Macklem #include <sys/errno.h>
3003914b0bSRick Macklem #include <sys/linker.h>
3103914b0bSRick Macklem #include <sys/module.h>
3203914b0bSRick Macklem #include <sys/mount.h>
3303914b0bSRick Macklem #include <sys/socket.h>
3403914b0bSRick Macklem #include <sys/socketvar.h>
35*a94018e2SRick Macklem #include <sys/sysctl.h>
3603914b0bSRick Macklem #include <sys/time.h>
3703914b0bSRick Macklem #include <sys/ucred.h>
3803914b0bSRick Macklem #include <sys/vnode.h>
3903914b0bSRick Macklem #include <sys/wait.h>
4003914b0bSRick Macklem
41ce78460aSRick Macklem #include <netinet/in.h>
42ce78460aSRick Macklem
43ce78460aSRick Macklem #include <arpa/inet.h>
44ce78460aSRick Macklem
4503914b0bSRick Macklem #include <nfs/nfssvc.h>
4603914b0bSRick Macklem
4703914b0bSRick Macklem #include <rpc/rpc.h>
4803914b0bSRick Macklem
4903914b0bSRick Macklem #include <fs/nfs/rpcv2.h>
5003914b0bSRick Macklem #include <fs/nfs/nfsproto.h>
5103914b0bSRick Macklem #include <fs/nfs/nfskpiport.h>
5203914b0bSRick Macklem #include <fs/nfs/nfs.h>
5303914b0bSRick Macklem
5403914b0bSRick Macklem #include <ctype.h>
5503914b0bSRick Macklem #include <err.h>
5603914b0bSRick Macklem #include <grp.h>
5703914b0bSRick Macklem #include <netdb.h>
5803914b0bSRick Macklem #include <pwd.h>
5903914b0bSRick Macklem #include <signal.h>
6003914b0bSRick Macklem #include <stdio.h>
6103914b0bSRick Macklem #include <stdlib.h>
6203914b0bSRick Macklem #include <string.h>
6303914b0bSRick Macklem #include <syslog.h>
6403914b0bSRick Macklem #include <unistd.h>
6503914b0bSRick Macklem
6603914b0bSRick Macklem /*
6703914b0bSRick Macklem * This program loads the password and group databases into the kernel
6803914b0bSRick Macklem * for NFS V4.
6903914b0bSRick Macklem */
7003914b0bSRick Macklem
719964058eSXin LI static void cleanup_term(int);
729964058eSXin LI static void usage(void);
739964058eSXin LI static void nfsuserdsrv(struct svc_req *, SVCXPRT *);
749964058eSXin LI static bool_t xdr_getid(XDR *, caddr_t);
759964058eSXin LI static bool_t xdr_getname(XDR *, caddr_t);
769964058eSXin LI static bool_t xdr_retval(XDR *, caddr_t);
77ce78460aSRick Macklem static int nfsbind_localhost(void);
7803914b0bSRick Macklem
7903914b0bSRick Macklem #define MAXNAME 1024
8003914b0bSRick Macklem #define MAXNFSUSERD 20
8103914b0bSRick Macklem #define DEFNFSUSERD 4
82eb75badeSRick Macklem #define MAXUSERMAX 100000
83eb75badeSRick Macklem #define MINUSERMAX 10
8403914b0bSRick Macklem #define DEFUSERMAX 200
8503914b0bSRick Macklem #define DEFUSERTIMEOUT (1 * 60)
8603914b0bSRick Macklem struct info {
8703914b0bSRick Macklem long id;
8803914b0bSRick Macklem long retval;
8903914b0bSRick Macklem char name[MAXNAME + 1];
9003914b0bSRick Macklem };
9103914b0bSRick Macklem
9203914b0bSRick Macklem u_char *dnsname = "default.domain";
9303914b0bSRick Macklem u_char *defaultuser = "nobody";
94c1c63967SRick Macklem uid_t defaultuid = 65534;
9503914b0bSRick Macklem u_char *defaultgroup = "nogroup";
96c1c63967SRick Macklem gid_t defaultgid = 65533;
9733906122SRick Macklem int verbose = 0, im_a_server = 0, nfsuserdcnt = -1, forcestart = 0;
98e6c623c8SRick Macklem int defusertimeout = DEFUSERTIMEOUT, manage_gids = 0;
9933906122SRick Macklem pid_t servers[MAXNFSUSERD];
100ce78460aSRick Macklem static struct sockaddr_storage fromip;
101ce78460aSRick Macklem #ifdef INET6
102ce78460aSRick Macklem static struct in6_addr in6loopback = IN6ADDR_LOOPBACK_INIT;
103ce78460aSRick Macklem #endif
10403914b0bSRick Macklem
10503914b0bSRick Macklem int
main(int argc,char * argv[])1069964058eSXin LI main(int argc, char *argv[])
10703914b0bSRick Macklem {
108eb75badeSRick Macklem int i, j;
109eb75badeSRick Macklem int error, fnd_dup, len, mustfreeai = 0, start_uidpos;
11003914b0bSRick Macklem struct nfsd_idargs nid;
11103914b0bSRick Macklem struct passwd *pwd;
11203914b0bSRick Macklem struct group *grp;
1137897d2a5SRick Macklem int sock, one = 1;
1149964058eSXin LI SVCXPRT *udptransp;
115ce78460aSRick Macklem struct nfsuserd_args nargs;
11603914b0bSRick Macklem sigset_t signew;
1179964058eSXin LI char hostname[MAXHOSTNAMELEN + 1], *cp;
11803914b0bSRick Macklem struct addrinfo *aip, hints;
119eb75badeSRick Macklem static uid_t check_dups[MAXUSERMAX];
120e6c623c8SRick Macklem gid_t grps[NGROUPS];
121e6c623c8SRick Macklem int ngroup;
122ce78460aSRick Macklem #ifdef INET
123ce78460aSRick Macklem struct sockaddr_in *sin;
124ce78460aSRick Macklem #endif
125ce78460aSRick Macklem #ifdef INET6
126ce78460aSRick Macklem struct sockaddr_in6 *sin6;
127ce78460aSRick Macklem #endif
128*a94018e2SRick Macklem int jailed, s;
129*a94018e2SRick Macklem size_t jailed_size;
13003914b0bSRick Macklem
13103914b0bSRick Macklem if (modfind("nfscommon") < 0) {
13203914b0bSRick Macklem /* Not present in kernel, try loading it */
13303914b0bSRick Macklem if (kldload("nfscommon") < 0 ||
13403914b0bSRick Macklem modfind("nfscommon") < 0)
13503914b0bSRick Macklem errx(1, "Experimental nfs subsystem is not available");
13603914b0bSRick Macklem }
13703914b0bSRick Macklem
13803914b0bSRick Macklem /*
13903914b0bSRick Macklem * First, figure out what our domain name and Kerberos Realm
14003914b0bSRick Macklem * seem to be. Command line args may override these later.
14103914b0bSRick Macklem */
14203914b0bSRick Macklem if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
14303914b0bSRick Macklem if ((cp = strchr(hostname, '.')) != NULL &&
14403914b0bSRick Macklem *(cp + 1) != '\0') {
14503914b0bSRick Macklem dnsname = cp + 1;
14603914b0bSRick Macklem } else {
14703914b0bSRick Macklem memset((void *)&hints, 0, sizeof (hints));
14803914b0bSRick Macklem hints.ai_flags = AI_CANONNAME;
14903914b0bSRick Macklem error = getaddrinfo(hostname, NULL, &hints, &aip);
15003914b0bSRick Macklem if (error == 0) {
15103914b0bSRick Macklem if (aip->ai_canonname != NULL &&
15203914b0bSRick Macklem (cp = strchr(aip->ai_canonname, '.')) != NULL
15303914b0bSRick Macklem && *(cp + 1) != '\0') {
15403914b0bSRick Macklem dnsname = cp + 1;
15503914b0bSRick Macklem mustfreeai = 1;
15603914b0bSRick Macklem } else {
15703914b0bSRick Macklem freeaddrinfo(aip);
15803914b0bSRick Macklem }
15903914b0bSRick Macklem }
16003914b0bSRick Macklem }
16103914b0bSRick Macklem }
162ce78460aSRick Macklem
163ce78460aSRick Macklem /*
164ce78460aSRick Macklem * See if this server handles IPv4 or IPv6 and set up the default
165ce78460aSRick Macklem * localhost address.
166ce78460aSRick Macklem */
167ce78460aSRick Macklem s = -1;
168ce78460aSRick Macklem #ifdef INET6
169ce78460aSRick Macklem s = socket(PF_INET6, SOCK_DGRAM, 0);
170ce78460aSRick Macklem if (s >= 0) {
171ce78460aSRick Macklem fromip.ss_family = AF_INET6;
172ce78460aSRick Macklem fromip.ss_len = sizeof(struct sockaddr_in6);
173ce78460aSRick Macklem sin6 = (struct sockaddr_in6 *)&fromip;
174ce78460aSRick Macklem sin6->sin6_addr = in6loopback;
175ce78460aSRick Macklem close(s);
176ce78460aSRick Macklem }
177ce78460aSRick Macklem #endif /* INET6 */
178ce78460aSRick Macklem #ifdef INET
179ce78460aSRick Macklem if (s < 0) {
180ce78460aSRick Macklem s = socket(PF_INET, SOCK_DGRAM, 0);
181ce78460aSRick Macklem if (s >= 0) {
182ce78460aSRick Macklem fromip.ss_family = AF_INET;
183ce78460aSRick Macklem fromip.ss_len = sizeof(struct sockaddr_in);
184ce78460aSRick Macklem sin = (struct sockaddr_in *)&fromip;
185ce78460aSRick Macklem sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
186ce78460aSRick Macklem close(s);
187ce78460aSRick Macklem }
188ce78460aSRick Macklem }
189ce78460aSRick Macklem #endif /* INET */
190ce78460aSRick Macklem if (s < 0)
191ce78460aSRick Macklem err(1, "Can't create a inet/inet6 socket");
192ce78460aSRick Macklem
19303914b0bSRick Macklem nid.nid_usermax = DEFUSERMAX;
19403914b0bSRick Macklem nid.nid_usertimeout = defusertimeout;
19503914b0bSRick Macklem
19603914b0bSRick Macklem argc--;
19703914b0bSRick Macklem argv++;
19803914b0bSRick Macklem while (argc >= 1) {
19903914b0bSRick Macklem if (!strcmp(*argv, "-domain")) {
20003914b0bSRick Macklem if (argc == 1)
20103914b0bSRick Macklem usage();
20203914b0bSRick Macklem argc--;
20303914b0bSRick Macklem argv++;
20403914b0bSRick Macklem strncpy(hostname, *argv, MAXHOSTNAMELEN);
20503914b0bSRick Macklem hostname[MAXHOSTNAMELEN] = '\0';
20603914b0bSRick Macklem dnsname = hostname;
20703914b0bSRick Macklem } else if (!strcmp(*argv, "-verbose")) {
20803914b0bSRick Macklem verbose = 1;
20903914b0bSRick Macklem } else if (!strcmp(*argv, "-force")) {
21003914b0bSRick Macklem forcestart = 1;
211e6c623c8SRick Macklem } else if (!strcmp(*argv, "-manage-gids")) {
212e6c623c8SRick Macklem manage_gids = 1;
21303914b0bSRick Macklem } else if (!strcmp(*argv, "-usermax")) {
21403914b0bSRick Macklem if (argc == 1)
21503914b0bSRick Macklem usage();
21603914b0bSRick Macklem argc--;
21703914b0bSRick Macklem argv++;
21803914b0bSRick Macklem i = atoi(*argv);
219eb75badeSRick Macklem if (i < MINUSERMAX || i > MAXUSERMAX) {
22003914b0bSRick Macklem fprintf(stderr,
221eb75badeSRick Macklem "usermax %d out of range %d<->%d\n", i,
222eb75badeSRick Macklem MINUSERMAX, MAXUSERMAX);
22303914b0bSRick Macklem usage();
22403914b0bSRick Macklem }
22503914b0bSRick Macklem nid.nid_usermax = i;
22603914b0bSRick Macklem } else if (!strcmp(*argv, "-usertimeout")) {
22703914b0bSRick Macklem if (argc == 1)
22803914b0bSRick Macklem usage();
22903914b0bSRick Macklem argc--;
23003914b0bSRick Macklem argv++;
23103914b0bSRick Macklem i = atoi(*argv);
23203914b0bSRick Macklem if (i < 0 || i > 100000) {
23303914b0bSRick Macklem fprintf(stderr,
2349964058eSXin LI "usertimeout %d out of range 0<->100000\n",
23503914b0bSRick Macklem i);
23603914b0bSRick Macklem usage();
23703914b0bSRick Macklem }
23803914b0bSRick Macklem nid.nid_usertimeout = defusertimeout = i * 60;
23903914b0bSRick Macklem } else if (nfsuserdcnt == -1) {
24003914b0bSRick Macklem nfsuserdcnt = atoi(*argv);
24103914b0bSRick Macklem if (nfsuserdcnt < 1)
24203914b0bSRick Macklem usage();
24303914b0bSRick Macklem if (nfsuserdcnt > MAXNFSUSERD) {
24403914b0bSRick Macklem warnx("nfsuserd count %d; reset to %d",
24503914b0bSRick Macklem nfsuserdcnt, DEFNFSUSERD);
24603914b0bSRick Macklem nfsuserdcnt = DEFNFSUSERD;
24703914b0bSRick Macklem }
24803914b0bSRick Macklem } else {
24903914b0bSRick Macklem usage();
25003914b0bSRick Macklem }
25103914b0bSRick Macklem argc--;
25203914b0bSRick Macklem argv++;
25303914b0bSRick Macklem }
25403914b0bSRick Macklem if (nfsuserdcnt < 1)
25503914b0bSRick Macklem nfsuserdcnt = DEFNFSUSERD;
25603914b0bSRick Macklem
25703914b0bSRick Macklem /*
25803914b0bSRick Macklem * Strip off leading and trailing '.'s in domain name and map
25903914b0bSRick Macklem * alphabetics to lower case.
26003914b0bSRick Macklem */
26103914b0bSRick Macklem while (*dnsname == '.')
26203914b0bSRick Macklem dnsname++;
26303914b0bSRick Macklem if (*dnsname == '\0')
26403914b0bSRick Macklem errx(1, "Domain name all '.'");
26503914b0bSRick Macklem len = strlen(dnsname);
26603914b0bSRick Macklem cp = dnsname + len - 1;
26703914b0bSRick Macklem while (*cp == '.') {
26803914b0bSRick Macklem *cp = '\0';
26903914b0bSRick Macklem len--;
27003914b0bSRick Macklem cp--;
27103914b0bSRick Macklem }
27203914b0bSRick Macklem for (i = 0; i < len; i++) {
27303914b0bSRick Macklem if (!isascii(dnsname[i]))
27403914b0bSRick Macklem errx(1, "Domain name has non-ascii char");
27503914b0bSRick Macklem if (isupper(dnsname[i]))
27603914b0bSRick Macklem dnsname[i] = tolower(dnsname[i]);
27703914b0bSRick Macklem }
27803914b0bSRick Macklem
27903914b0bSRick Macklem /*
28003914b0bSRick Macklem * If the nfsuserd died off ungracefully, this is necessary to
28103914b0bSRick Macklem * get them to start again.
28203914b0bSRick Macklem */
28303914b0bSRick Macklem if (forcestart && nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0)
28403914b0bSRick Macklem errx(1, "Can't do nfssvc() to delete the port");
28503914b0bSRick Macklem
28603914b0bSRick Macklem if (verbose)
28703914b0bSRick Macklem fprintf(stderr,
28803914b0bSRick Macklem "nfsuserd: domain=%s usermax=%d usertimeout=%d\n",
28903914b0bSRick Macklem dnsname, nid.nid_usermax, nid.nid_usertimeout);
29003914b0bSRick Macklem
29103914b0bSRick Macklem for (i = 0; i < nfsuserdcnt; i++)
29233906122SRick Macklem servers[i] = (pid_t)-1;
29303914b0bSRick Macklem
294ce78460aSRick Macklem nargs.nuserd_family = fromip.ss_family;
29503914b0bSRick Macklem /*
29603914b0bSRick Macklem * Set up the service port to accept requests via UDP from
297ce78460aSRick Macklem * localhost (INADDR_LOOPBACK or IN6ADDR_LOOPBACK_INIT).
29803914b0bSRick Macklem */
299ce78460aSRick Macklem if ((sock = socket(nargs.nuserd_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
30003914b0bSRick Macklem err(1, "cannot create udp socket");
30103914b0bSRick Macklem
30203914b0bSRick Macklem /*
30303914b0bSRick Macklem * Not sure what this does, so I'll leave it here for now.
30403914b0bSRick Macklem */
30503914b0bSRick Macklem setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
30603914b0bSRick Macklem
30703914b0bSRick Macklem if ((udptransp = svcudp_create(sock)) == NULL)
30803914b0bSRick Macklem err(1, "Can't set up socket");
30903914b0bSRick Macklem
31003914b0bSRick Macklem /*
31103914b0bSRick Macklem * By not specifying a protocol, it is linked into the
31203914b0bSRick Macklem * dispatch queue, but not registered with portmapper,
31303914b0bSRick Macklem * which is just what I want.
31403914b0bSRick Macklem */
31503914b0bSRick Macklem if (!svc_register(udptransp, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS,
31603914b0bSRick Macklem nfsuserdsrv, 0))
31703914b0bSRick Macklem err(1, "Can't register nfsuserd");
31803914b0bSRick Macklem
31903914b0bSRick Macklem /*
32003914b0bSRick Macklem * Tell the kernel what my port# is.
32103914b0bSRick Macklem */
322ce78460aSRick Macklem nargs.nuserd_port = htons(udptransp->xp_port);
32303914b0bSRick Macklem #ifdef DEBUG
324ce78460aSRick Macklem printf("portnum=0x%x\n", nargs.nuserd_port);
32503914b0bSRick Macklem #else
326ce78460aSRick Macklem if (nfssvc(NFSSVC_NFSUSERDPORT | NFSSVC_NEWSTRUCT, &nargs) < 0) {
3277897d2a5SRick Macklem if (errno == EPERM) {
328*a94018e2SRick Macklem jailed = 0;
329*a94018e2SRick Macklem jailed_size = sizeof(jailed);
330*a94018e2SRick Macklem sysctlbyname("security.jail.jailed", &jailed,
331*a94018e2SRick Macklem &jailed_size, NULL, 0);
332*a94018e2SRick Macklem if (jailed != 0) {
333*a94018e2SRick Macklem fprintf(stderr, "Cannot start nfsuserd. "
334*a94018e2SRick Macklem "allow.nfsd might not be configured\n");
335*a94018e2SRick Macklem } else {
336*a94018e2SRick Macklem fprintf(stderr, "Cannot start nfsuserd "
337*a94018e2SRick Macklem "when already running.");
338*a94018e2SRick Macklem fprintf(stderr, " If not running, "
339*a94018e2SRick Macklem "use the -force option.\n");
340*a94018e2SRick Macklem }
34177193c05SRick Macklem } else {
3427897d2a5SRick Macklem fprintf(stderr, "Can't do nfssvc() to add port\n");
3437897d2a5SRick Macklem }
34477193c05SRick Macklem exit(1);
34577193c05SRick Macklem }
34677193c05SRick Macklem #endif
34703914b0bSRick Macklem
34803914b0bSRick Macklem pwd = getpwnam(defaultuser);
34903914b0bSRick Macklem if (pwd)
35003914b0bSRick Macklem nid.nid_uid = pwd->pw_uid;
35103914b0bSRick Macklem else
35203914b0bSRick Macklem nid.nid_uid = defaultuid;
35303914b0bSRick Macklem grp = getgrnam(defaultgroup);
35403914b0bSRick Macklem if (grp)
35503914b0bSRick Macklem nid.nid_gid = grp->gr_gid;
35603914b0bSRick Macklem else
35703914b0bSRick Macklem nid.nid_gid = defaultgid;
35803914b0bSRick Macklem nid.nid_name = dnsname;
35903914b0bSRick Macklem nid.nid_namelen = strlen(nid.nid_name);
360e6c623c8SRick Macklem nid.nid_ngroup = 0;
361e6c623c8SRick Macklem nid.nid_grps = NULL;
36203914b0bSRick Macklem nid.nid_flag = NFSID_INITIALIZE;
36303914b0bSRick Macklem #ifdef DEBUG
36403914b0bSRick Macklem printf("Initialize uid=%d gid=%d dns=%s\n", nid.nid_uid, nid.nid_gid,
36503914b0bSRick Macklem nid.nid_name);
36603914b0bSRick Macklem #else
367e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
36803914b0bSRick Macklem if (error)
36903914b0bSRick Macklem errx(1, "Can't initialize nfs user/groups");
37003914b0bSRick Macklem #endif
37103914b0bSRick Macklem
37203914b0bSRick Macklem i = 0;
37303914b0bSRick Macklem /*
37403914b0bSRick Macklem * Loop around adding all groups.
37503914b0bSRick Macklem */
37603914b0bSRick Macklem setgrent();
37703914b0bSRick Macklem while (i < nid.nid_usermax && (grp = getgrent())) {
37803914b0bSRick Macklem nid.nid_gid = grp->gr_gid;
37903914b0bSRick Macklem nid.nid_name = grp->gr_name;
38003914b0bSRick Macklem nid.nid_namelen = strlen(grp->gr_name);
381e6c623c8SRick Macklem nid.nid_ngroup = 0;
382e6c623c8SRick Macklem nid.nid_grps = NULL;
38303914b0bSRick Macklem nid.nid_flag = NFSID_ADDGID;
38403914b0bSRick Macklem #ifdef DEBUG
38503914b0bSRick Macklem printf("add gid=%d name=%s\n", nid.nid_gid, nid.nid_name);
38603914b0bSRick Macklem #else
387e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
38803914b0bSRick Macklem if (error)
38903914b0bSRick Macklem errx(1, "Can't add group %s", grp->gr_name);
39003914b0bSRick Macklem #endif
39103914b0bSRick Macklem i++;
39203914b0bSRick Macklem }
393670c1e4bSMark Johnston endgrent();
39403914b0bSRick Macklem
39503914b0bSRick Macklem /*
39603914b0bSRick Macklem * Loop around adding all users.
39703914b0bSRick Macklem */
398eb75badeSRick Macklem start_uidpos = i;
39903914b0bSRick Macklem setpwent();
40003914b0bSRick Macklem while (i < nid.nid_usermax && (pwd = getpwent())) {
401eb75badeSRick Macklem fnd_dup = 0;
402eb75badeSRick Macklem /*
403eb75badeSRick Macklem * Yes, this is inefficient, but it is only done once when
404eb75badeSRick Macklem * the daemon is started and will run in a fraction of a second
405eb75badeSRick Macklem * for nid_usermax at 10000. If nid_usermax is cranked up to
406eb75badeSRick Macklem * 100000, it will take several seconds, depending on the CPU.
407eb75badeSRick Macklem */
408eb75badeSRick Macklem for (j = 0; j < (i - start_uidpos); j++)
409eb75badeSRick Macklem if (check_dups[j] == pwd->pw_uid) {
410eb75badeSRick Macklem /* Found another entry for uid, so skip it */
411eb75badeSRick Macklem fnd_dup = 1;
412eb75badeSRick Macklem break;
413eb75badeSRick Macklem }
414eb75badeSRick Macklem if (fnd_dup != 0)
415eb75badeSRick Macklem continue;
416eb75badeSRick Macklem check_dups[i - start_uidpos] = pwd->pw_uid;
41703914b0bSRick Macklem nid.nid_uid = pwd->pw_uid;
41803914b0bSRick Macklem nid.nid_name = pwd->pw_name;
41903914b0bSRick Macklem nid.nid_namelen = strlen(pwd->pw_name);
420e6c623c8SRick Macklem if (manage_gids != 0) {
421e6c623c8SRick Macklem /* Get the group list for this user. */
422e6c623c8SRick Macklem ngroup = NGROUPS;
423e6c623c8SRick Macklem if (getgrouplist(pwd->pw_name, pwd->pw_gid, grps,
424e6c623c8SRick Macklem &ngroup) < 0)
425e6c623c8SRick Macklem syslog(LOG_ERR, "Group list too small");
426e6c623c8SRick Macklem nid.nid_ngroup = ngroup;
427e6c623c8SRick Macklem nid.nid_grps = grps;
428e6c623c8SRick Macklem } else {
429e6c623c8SRick Macklem nid.nid_ngroup = 0;
430e6c623c8SRick Macklem nid.nid_grps = NULL;
431e6c623c8SRick Macklem }
43203914b0bSRick Macklem nid.nid_flag = NFSID_ADDUID;
43303914b0bSRick Macklem #ifdef DEBUG
43403914b0bSRick Macklem printf("add uid=%d name=%s\n", nid.nid_uid, nid.nid_name);
43503914b0bSRick Macklem #else
436e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
43703914b0bSRick Macklem if (error)
43803914b0bSRick Macklem errx(1, "Can't add user %s", pwd->pw_name);
43903914b0bSRick Macklem #endif
44003914b0bSRick Macklem i++;
44103914b0bSRick Macklem }
442670c1e4bSMark Johnston endpwent();
44303914b0bSRick Macklem
44403914b0bSRick Macklem /*
44503914b0bSRick Macklem * I should feel guilty for not calling this for all the above exit()
44603914b0bSRick Macklem * upon error cases, but I don't.
44703914b0bSRick Macklem */
44803914b0bSRick Macklem if (mustfreeai)
44903914b0bSRick Macklem freeaddrinfo(aip);
45003914b0bSRick Macklem
45103914b0bSRick Macklem #ifdef DEBUG
45203914b0bSRick Macklem exit(0);
45303914b0bSRick Macklem #endif
45403914b0bSRick Macklem /*
45533906122SRick Macklem * Temporarily block SIGUSR1 and SIGCHLD, so servers[] can't
45603914b0bSRick Macklem * end up bogus.
45703914b0bSRick Macklem */
45803914b0bSRick Macklem sigemptyset(&signew);
45903914b0bSRick Macklem sigaddset(&signew, SIGUSR1);
46003914b0bSRick Macklem sigaddset(&signew, SIGCHLD);
46103914b0bSRick Macklem sigprocmask(SIG_BLOCK, &signew, NULL);
46203914b0bSRick Macklem
46303914b0bSRick Macklem daemon(0, 0);
46403914b0bSRick Macklem (void)signal(SIGHUP, SIG_IGN);
46503914b0bSRick Macklem (void)signal(SIGINT, SIG_IGN);
46603914b0bSRick Macklem (void)signal(SIGQUIT, SIG_IGN);
46703914b0bSRick Macklem (void)signal(SIGTERM, SIG_IGN);
46803914b0bSRick Macklem (void)signal(SIGUSR1, cleanup_term);
46903914b0bSRick Macklem (void)signal(SIGCHLD, cleanup_term);
47003914b0bSRick Macklem
47103914b0bSRick Macklem openlog("nfsuserd:", LOG_PID, LOG_DAEMON);
47203914b0bSRick Macklem
47303914b0bSRick Macklem /*
47433906122SRick Macklem * Fork off the server daemons that do the work. All the master
47533906122SRick Macklem * does is terminate them and cleanup.
47603914b0bSRick Macklem */
47703914b0bSRick Macklem for (i = 0; i < nfsuserdcnt; i++) {
47833906122SRick Macklem servers[i] = fork();
47933906122SRick Macklem if (servers[i] == 0) {
48033906122SRick Macklem im_a_server = 1;
48133906122SRick Macklem setproctitle("server");
48203914b0bSRick Macklem sigemptyset(&signew);
48303914b0bSRick Macklem sigaddset(&signew, SIGUSR1);
48403914b0bSRick Macklem sigprocmask(SIG_UNBLOCK, &signew, NULL);
48503914b0bSRick Macklem
48603914b0bSRick Macklem /*
48703914b0bSRick Macklem * and away we go.
48803914b0bSRick Macklem */
48903914b0bSRick Macklem svc_run();
49003914b0bSRick Macklem syslog(LOG_ERR, "nfsuserd died: %m");
49103914b0bSRick Macklem exit(1);
49233906122SRick Macklem } else if (servers[i] < 0) {
49303914b0bSRick Macklem syslog(LOG_ERR, "fork: %m");
49403914b0bSRick Macklem }
49503914b0bSRick Macklem }
49603914b0bSRick Macklem
49703914b0bSRick Macklem /*
49803914b0bSRick Macklem * Just wait for SIGUSR1 or a child to die and then...
49903914b0bSRick Macklem * As the Governor of California would say, "Terminate them".
50003914b0bSRick Macklem */
50103914b0bSRick Macklem setproctitle("master");
50203914b0bSRick Macklem sigemptyset(&signew);
50303914b0bSRick Macklem while (1)
50403914b0bSRick Macklem sigsuspend(&signew);
50503914b0bSRick Macklem }
50603914b0bSRick Macklem
50703914b0bSRick Macklem /*
50803914b0bSRick Macklem * The nfsuserd rpc service
50903914b0bSRick Macklem */
5109964058eSXin LI static void
nfsuserdsrv(struct svc_req * rqstp,SVCXPRT * transp)51103914b0bSRick Macklem nfsuserdsrv(struct svc_req *rqstp, SVCXPRT *transp)
51203914b0bSRick Macklem {
51303914b0bSRick Macklem struct passwd *pwd;
51403914b0bSRick Macklem struct group *grp;
51503914b0bSRick Macklem int error;
516ce78460aSRick Macklem #if defined(INET) || defined(INET6)
51703914b0bSRick Macklem u_short sport;
518ce78460aSRick Macklem int ret;
519ce78460aSRick Macklem #endif
52003914b0bSRick Macklem struct info info;
52103914b0bSRick Macklem struct nfsd_idargs nid;
522e6c623c8SRick Macklem gid_t grps[NGROUPS];
523e6c623c8SRick Macklem int ngroup;
524ce78460aSRick Macklem #ifdef INET
525ce78460aSRick Macklem struct sockaddr_in *fromsin, *sin;
526ce78460aSRick Macklem #endif
527ce78460aSRick Macklem #ifdef INET6
528ce78460aSRick Macklem struct sockaddr_in6 *fromsin6, *sin6;
529ce78460aSRick Macklem char buf[INET6_ADDRSTRLEN];
530ce78460aSRick Macklem #endif
53103914b0bSRick Macklem
53203914b0bSRick Macklem /*
533ce78460aSRick Macklem * Only handle requests from localhost on a reserved port number.
534ce78460aSRick Macklem * If the upcall is from a different address, call nfsbind_localhost()
535ce78460aSRick Macklem * to check for a remapping of localhost, due to jails.
5367897d2a5SRick Macklem * (Since a reserved port # at localhost implies a client with
5377897d2a5SRick Macklem * local root, there won't be a security breach. This is about
5387897d2a5SRick Macklem * the only case I can think of where a reserved port # means
5397897d2a5SRick Macklem * something.)
54003914b0bSRick Macklem */
541ce78460aSRick Macklem if (rqstp->rq_proc != NULLPROC) {
542ce78460aSRick Macklem switch (fromip.ss_family) {
543ce78460aSRick Macklem #ifdef INET
544ce78460aSRick Macklem case AF_INET:
545ce78460aSRick Macklem if (transp->xp_rtaddr.len < sizeof(*sin)) {
546ce78460aSRick Macklem syslog(LOG_ERR, "xp_rtaddr too small");
54703914b0bSRick Macklem svcerr_weakauth(transp);
54803914b0bSRick Macklem return;
54903914b0bSRick Macklem }
550ce78460aSRick Macklem sin = (struct sockaddr_in *)transp->xp_rtaddr.buf;
551ce78460aSRick Macklem fromsin = (struct sockaddr_in *)&fromip;
552ce78460aSRick Macklem sport = ntohs(sin->sin_port);
553ce78460aSRick Macklem if (sport >= IPPORT_RESERVED) {
554ce78460aSRick Macklem syslog(LOG_ERR, "not a reserved port#");
555ce78460aSRick Macklem svcerr_weakauth(transp);
556ce78460aSRick Macklem return;
557ce78460aSRick Macklem }
558ce78460aSRick Macklem ret = 1;
559ce78460aSRick Macklem if (sin->sin_addr.s_addr != fromsin->sin_addr.s_addr)
560ce78460aSRick Macklem ret = nfsbind_localhost();
561ce78460aSRick Macklem if (ret == 0 || sin->sin_addr.s_addr !=
562ce78460aSRick Macklem fromsin->sin_addr.s_addr) {
563ce78460aSRick Macklem syslog(LOG_ERR, "bad from ip %s",
564ce78460aSRick Macklem inet_ntoa(sin->sin_addr));
565ce78460aSRick Macklem svcerr_weakauth(transp);
566ce78460aSRick Macklem return;
567ce78460aSRick Macklem }
568ce78460aSRick Macklem break;
569ce78460aSRick Macklem #endif /* INET */
570ce78460aSRick Macklem #ifdef INET6
571ce78460aSRick Macklem case AF_INET6:
572ce78460aSRick Macklem if (transp->xp_rtaddr.len < sizeof(*sin6)) {
573ce78460aSRick Macklem syslog(LOG_ERR, "xp_rtaddr too small");
574ce78460aSRick Macklem svcerr_weakauth(transp);
575ce78460aSRick Macklem return;
576ce78460aSRick Macklem }
577ce78460aSRick Macklem sin6 = (struct sockaddr_in6 *)transp->xp_rtaddr.buf;
578ce78460aSRick Macklem fromsin6 = (struct sockaddr_in6 *)&fromip;
579ce78460aSRick Macklem sport = ntohs(sin6->sin6_port);
580ce78460aSRick Macklem if (sport >= IPV6PORT_RESERVED) {
581ce78460aSRick Macklem syslog(LOG_ERR, "not a reserved port#");
582ce78460aSRick Macklem svcerr_weakauth(transp);
583ce78460aSRick Macklem return;
584ce78460aSRick Macklem }
585ce78460aSRick Macklem ret = 1;
586ce78460aSRick Macklem if (!IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
587ce78460aSRick Macklem &fromsin6->sin6_addr))
588ce78460aSRick Macklem ret = nfsbind_localhost();
589ce78460aSRick Macklem if (ret == 0 || !IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
590ce78460aSRick Macklem &fromsin6->sin6_addr)) {
591ce78460aSRick Macklem if (inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
592ce78460aSRick Macklem INET6_ADDRSTRLEN) != NULL)
593ce78460aSRick Macklem syslog(LOG_ERR, "bad from ip %s", buf);
594ce78460aSRick Macklem else
595ce78460aSRick Macklem syslog(LOG_ERR, "bad from ip6 addr");
596ce78460aSRick Macklem svcerr_weakauth(transp);
597ce78460aSRick Macklem return;
598ce78460aSRick Macklem }
599ce78460aSRick Macklem break;
600ce78460aSRick Macklem #endif /* INET6 */
601ce78460aSRick Macklem }
602ce78460aSRick Macklem }
60303914b0bSRick Macklem switch (rqstp->rq_proc) {
60403914b0bSRick Macklem case NULLPROC:
60503914b0bSRick Macklem if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL))
60603914b0bSRick Macklem syslog(LOG_ERR, "Can't send reply");
60703914b0bSRick Macklem return;
60803914b0bSRick Macklem case RPCNFSUSERD_GETUID:
60903914b0bSRick Macklem if (!svc_getargs(transp, (xdrproc_t)xdr_getid,
61003914b0bSRick Macklem (caddr_t)&info)) {
61103914b0bSRick Macklem svcerr_decode(transp);
61203914b0bSRick Macklem return;
61303914b0bSRick Macklem }
61403914b0bSRick Macklem pwd = getpwuid((uid_t)info.id);
61503914b0bSRick Macklem info.retval = 0;
61603914b0bSRick Macklem if (pwd != NULL) {
61703914b0bSRick Macklem nid.nid_usertimeout = defusertimeout;
61803914b0bSRick Macklem nid.nid_uid = pwd->pw_uid;
61903914b0bSRick Macklem nid.nid_name = pwd->pw_name;
620e6c623c8SRick Macklem if (manage_gids != 0) {
621e6c623c8SRick Macklem /* Get the group list for this user. */
622e6c623c8SRick Macklem ngroup = NGROUPS;
623e6c623c8SRick Macklem if (getgrouplist(pwd->pw_name, pwd->pw_gid,
624e6c623c8SRick Macklem grps, &ngroup) < 0)
625e6c623c8SRick Macklem syslog(LOG_ERR, "Group list too small");
626e6c623c8SRick Macklem nid.nid_ngroup = ngroup;
627e6c623c8SRick Macklem nid.nid_grps = grps;
628e6c623c8SRick Macklem } else {
629e6c623c8SRick Macklem nid.nid_ngroup = 0;
630e6c623c8SRick Macklem nid.nid_grps = NULL;
631e6c623c8SRick Macklem }
63203914b0bSRick Macklem } else {
63303914b0bSRick Macklem nid.nid_usertimeout = 5;
63403914b0bSRick Macklem nid.nid_uid = (uid_t)info.id;
63503914b0bSRick Macklem nid.nid_name = defaultuser;
636e6c623c8SRick Macklem nid.nid_ngroup = 0;
637e6c623c8SRick Macklem nid.nid_grps = NULL;
63803914b0bSRick Macklem }
63903914b0bSRick Macklem nid.nid_namelen = strlen(nid.nid_name);
64003914b0bSRick Macklem nid.nid_flag = NFSID_ADDUID;
641e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
64203914b0bSRick Macklem if (error) {
64303914b0bSRick Macklem info.retval = error;
64403914b0bSRick Macklem syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name);
64503914b0bSRick Macklem } else if (verbose) {
64603914b0bSRick Macklem syslog(LOG_ERR,"Added uid=%d name=%s\n",
64703914b0bSRick Macklem nid.nid_uid, nid.nid_name);
64803914b0bSRick Macklem }
64903914b0bSRick Macklem if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
65003914b0bSRick Macklem (caddr_t)&info))
65103914b0bSRick Macklem syslog(LOG_ERR, "Can't send reply");
65203914b0bSRick Macklem return;
65303914b0bSRick Macklem case RPCNFSUSERD_GETGID:
65403914b0bSRick Macklem if (!svc_getargs(transp, (xdrproc_t)xdr_getid,
65503914b0bSRick Macklem (caddr_t)&info)) {
65603914b0bSRick Macklem svcerr_decode(transp);
65703914b0bSRick Macklem return;
65803914b0bSRick Macklem }
65903914b0bSRick Macklem grp = getgrgid((gid_t)info.id);
66003914b0bSRick Macklem info.retval = 0;
66103914b0bSRick Macklem if (grp != NULL) {
66203914b0bSRick Macklem nid.nid_usertimeout = defusertimeout;
66303914b0bSRick Macklem nid.nid_gid = grp->gr_gid;
66403914b0bSRick Macklem nid.nid_name = grp->gr_name;
66503914b0bSRick Macklem } else {
66603914b0bSRick Macklem nid.nid_usertimeout = 5;
66703914b0bSRick Macklem nid.nid_gid = (gid_t)info.id;
66803914b0bSRick Macklem nid.nid_name = defaultgroup;
66903914b0bSRick Macklem }
67003914b0bSRick Macklem nid.nid_namelen = strlen(nid.nid_name);
671e6c623c8SRick Macklem nid.nid_ngroup = 0;
672e6c623c8SRick Macklem nid.nid_grps = NULL;
67303914b0bSRick Macklem nid.nid_flag = NFSID_ADDGID;
674e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
67503914b0bSRick Macklem if (error) {
67603914b0bSRick Macklem info.retval = error;
67703914b0bSRick Macklem syslog(LOG_ERR, "Can't add group %s\n",
67803914b0bSRick Macklem grp->gr_name);
67903914b0bSRick Macklem } else if (verbose) {
68003914b0bSRick Macklem syslog(LOG_ERR,"Added gid=%d name=%s\n",
68103914b0bSRick Macklem nid.nid_gid, nid.nid_name);
68203914b0bSRick Macklem }
68303914b0bSRick Macklem if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
68403914b0bSRick Macklem (caddr_t)&info))
68503914b0bSRick Macklem syslog(LOG_ERR, "Can't send reply");
68603914b0bSRick Macklem return;
68703914b0bSRick Macklem case RPCNFSUSERD_GETUSER:
68803914b0bSRick Macklem if (!svc_getargs(transp, (xdrproc_t)xdr_getname,
68903914b0bSRick Macklem (caddr_t)&info)) {
69003914b0bSRick Macklem svcerr_decode(transp);
69103914b0bSRick Macklem return;
69203914b0bSRick Macklem }
69303914b0bSRick Macklem pwd = getpwnam(info.name);
69403914b0bSRick Macklem info.retval = 0;
69503914b0bSRick Macklem if (pwd != NULL) {
69603914b0bSRick Macklem nid.nid_usertimeout = defusertimeout;
69703914b0bSRick Macklem nid.nid_uid = pwd->pw_uid;
69803914b0bSRick Macklem nid.nid_name = pwd->pw_name;
69903914b0bSRick Macklem } else {
70003914b0bSRick Macklem nid.nid_usertimeout = 5;
70103914b0bSRick Macklem nid.nid_uid = defaultuid;
70203914b0bSRick Macklem nid.nid_name = info.name;
70303914b0bSRick Macklem }
70403914b0bSRick Macklem nid.nid_namelen = strlen(nid.nid_name);
705e6c623c8SRick Macklem nid.nid_ngroup = 0;
706e6c623c8SRick Macklem nid.nid_grps = NULL;
70703914b0bSRick Macklem nid.nid_flag = NFSID_ADDUSERNAME;
708e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
70903914b0bSRick Macklem if (error) {
71003914b0bSRick Macklem info.retval = error;
71103914b0bSRick Macklem syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name);
71203914b0bSRick Macklem } else if (verbose) {
71303914b0bSRick Macklem syslog(LOG_ERR,"Added uid=%d name=%s\n",
71403914b0bSRick Macklem nid.nid_uid, nid.nid_name);
71503914b0bSRick Macklem }
71603914b0bSRick Macklem if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
71703914b0bSRick Macklem (caddr_t)&info))
71803914b0bSRick Macklem syslog(LOG_ERR, "Can't send reply");
71903914b0bSRick Macklem return;
72003914b0bSRick Macklem case RPCNFSUSERD_GETGROUP:
72103914b0bSRick Macklem if (!svc_getargs(transp, (xdrproc_t)xdr_getname,
72203914b0bSRick Macklem (caddr_t)&info)) {
72303914b0bSRick Macklem svcerr_decode(transp);
72403914b0bSRick Macklem return;
72503914b0bSRick Macklem }
72603914b0bSRick Macklem grp = getgrnam(info.name);
72703914b0bSRick Macklem info.retval = 0;
72803914b0bSRick Macklem if (grp != NULL) {
72903914b0bSRick Macklem nid.nid_usertimeout = defusertimeout;
73003914b0bSRick Macklem nid.nid_gid = grp->gr_gid;
73103914b0bSRick Macklem nid.nid_name = grp->gr_name;
73203914b0bSRick Macklem } else {
73303914b0bSRick Macklem nid.nid_usertimeout = 5;
73403914b0bSRick Macklem nid.nid_gid = defaultgid;
73503914b0bSRick Macklem nid.nid_name = info.name;
73603914b0bSRick Macklem }
73703914b0bSRick Macklem nid.nid_namelen = strlen(nid.nid_name);
738e6c623c8SRick Macklem nid.nid_ngroup = 0;
739e6c623c8SRick Macklem nid.nid_grps = NULL;
74003914b0bSRick Macklem nid.nid_flag = NFSID_ADDGROUPNAME;
741e6c623c8SRick Macklem error = nfssvc(NFSSVC_IDNAME | NFSSVC_NEWSTRUCT, &nid);
74203914b0bSRick Macklem if (error) {
74303914b0bSRick Macklem info.retval = error;
74403914b0bSRick Macklem syslog(LOG_ERR, "Can't add group %s\n",
74503914b0bSRick Macklem grp->gr_name);
74603914b0bSRick Macklem } else if (verbose) {
74703914b0bSRick Macklem syslog(LOG_ERR,"Added gid=%d name=%s\n",
74803914b0bSRick Macklem nid.nid_gid, nid.nid_name);
74903914b0bSRick Macklem }
75003914b0bSRick Macklem if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
75103914b0bSRick Macklem (caddr_t)&info))
75203914b0bSRick Macklem syslog(LOG_ERR, "Can't send reply");
75303914b0bSRick Macklem return;
75403914b0bSRick Macklem default:
75503914b0bSRick Macklem svcerr_noproc(transp);
75603914b0bSRick Macklem return;
75703914b0bSRick Macklem };
75803914b0bSRick Macklem }
75903914b0bSRick Macklem
76003914b0bSRick Macklem /*
76103914b0bSRick Macklem * Xdr routine to get an id number
76203914b0bSRick Macklem */
7639964058eSXin LI static bool_t
xdr_getid(XDR * xdrsp,caddr_t cp)76403914b0bSRick Macklem xdr_getid(XDR *xdrsp, caddr_t cp)
76503914b0bSRick Macklem {
76603914b0bSRick Macklem struct info *ifp = (struct info *)cp;
76703914b0bSRick Macklem
76803914b0bSRick Macklem return (xdr_long(xdrsp, &ifp->id));
76903914b0bSRick Macklem }
77003914b0bSRick Macklem
77103914b0bSRick Macklem /*
77203914b0bSRick Macklem * Xdr routine to get a user name
77303914b0bSRick Macklem */
7749964058eSXin LI static bool_t
xdr_getname(XDR * xdrsp,caddr_t cp)77503914b0bSRick Macklem xdr_getname(XDR *xdrsp, caddr_t cp)
77603914b0bSRick Macklem {
77703914b0bSRick Macklem struct info *ifp = (struct info *)cp;
77803914b0bSRick Macklem long len;
77903914b0bSRick Macklem
78003914b0bSRick Macklem if (!xdr_long(xdrsp, &len))
78103914b0bSRick Macklem return (0);
78203914b0bSRick Macklem if (len > MAXNAME)
78303914b0bSRick Macklem return (0);
78403914b0bSRick Macklem if (!xdr_opaque(xdrsp, ifp->name, len))
78503914b0bSRick Macklem return (0);
78603914b0bSRick Macklem ifp->name[len] = '\0';
78703914b0bSRick Macklem return (1);
78803914b0bSRick Macklem }
78903914b0bSRick Macklem
79003914b0bSRick Macklem /*
79103914b0bSRick Macklem * Xdr routine to return the value.
79203914b0bSRick Macklem */
7939964058eSXin LI static bool_t
xdr_retval(XDR * xdrsp,caddr_t cp)79403914b0bSRick Macklem xdr_retval(XDR *xdrsp, caddr_t cp)
79503914b0bSRick Macklem {
79603914b0bSRick Macklem struct info *ifp = (struct info *)cp;
79703914b0bSRick Macklem long val;
79803914b0bSRick Macklem
79903914b0bSRick Macklem val = ifp->retval;
80003914b0bSRick Macklem return (xdr_long(xdrsp, &val));
80103914b0bSRick Macklem }
80203914b0bSRick Macklem
80303914b0bSRick Macklem /*
80403914b0bSRick Macklem * cleanup_term() called via SIGUSR1.
80503914b0bSRick Macklem */
8069964058eSXin LI static void
cleanup_term(int signo __unused)8079964058eSXin LI cleanup_term(int signo __unused)
80803914b0bSRick Macklem {
80903914b0bSRick Macklem int i, cnt;
81003914b0bSRick Macklem
81133906122SRick Macklem if (im_a_server)
81203914b0bSRick Macklem exit(0);
81303914b0bSRick Macklem
81403914b0bSRick Macklem /*
81503914b0bSRick Macklem * Ok, so I'm the master.
81603914b0bSRick Macklem * As the Governor of California might say, "Terminate them".
81703914b0bSRick Macklem */
81803914b0bSRick Macklem cnt = 0;
81903914b0bSRick Macklem for (i = 0; i < nfsuserdcnt; i++) {
82033906122SRick Macklem if (servers[i] != (pid_t)-1) {
82103914b0bSRick Macklem cnt++;
82233906122SRick Macklem kill(servers[i], SIGUSR1);
82303914b0bSRick Macklem }
82403914b0bSRick Macklem }
82503914b0bSRick Macklem
82603914b0bSRick Macklem /*
82703914b0bSRick Macklem * and wait for them to die
82803914b0bSRick Macklem */
82903914b0bSRick Macklem for (i = 0; i < cnt; i++)
83003914b0bSRick Macklem wait3(NULL, 0, NULL);
83103914b0bSRick Macklem
83203914b0bSRick Macklem /*
83303914b0bSRick Macklem * Finally, get rid of the socket
83403914b0bSRick Macklem */
83503914b0bSRick Macklem if (nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) {
83603914b0bSRick Macklem syslog(LOG_ERR, "Can't do nfssvc() to delete the port\n");
83703914b0bSRick Macklem exit(1);
83803914b0bSRick Macklem }
83903914b0bSRick Macklem exit(0);
84003914b0bSRick Macklem }
84103914b0bSRick Macklem
842ce78460aSRick Macklem /*
843ce78460aSRick Macklem * Get the IP address that the localhost address maps to.
844ce78460aSRick Macklem * This is needed when jails map localhost to another IP address.
845ce78460aSRick Macklem */
846ce78460aSRick Macklem static int
nfsbind_localhost(void)847ce78460aSRick Macklem nfsbind_localhost(void)
848ce78460aSRick Macklem {
849ce78460aSRick Macklem #ifdef INET
850ce78460aSRick Macklem struct sockaddr_in sin;
851ce78460aSRick Macklem #endif
852ce78460aSRick Macklem #ifdef INET6
853ce78460aSRick Macklem struct sockaddr_in6 sin6;
854ce78460aSRick Macklem #endif
855ce78460aSRick Macklem socklen_t slen;
856ce78460aSRick Macklem int ret, s;
857ce78460aSRick Macklem
858ce78460aSRick Macklem switch (fromip.ss_family) {
859ce78460aSRick Macklem #ifdef INET6
860ce78460aSRick Macklem case AF_INET6:
861ce78460aSRick Macklem s = socket(PF_INET6, SOCK_DGRAM, 0);
862ce78460aSRick Macklem if (s < 0)
863ce78460aSRick Macklem return (0);
864ce78460aSRick Macklem memset(&sin6, 0, sizeof(sin6));
865ce78460aSRick Macklem sin6.sin6_len = sizeof(sin6);
866ce78460aSRick Macklem sin6.sin6_family = AF_INET6;
867ce78460aSRick Macklem sin6.sin6_addr = in6loopback;
868ce78460aSRick Macklem sin6.sin6_port = 0;
869ce78460aSRick Macklem ret = bind(s, (struct sockaddr *)&sin6, sizeof(sin6));
870ce78460aSRick Macklem if (ret < 0) {
871ce78460aSRick Macklem close(s);
872ce78460aSRick Macklem return (0);
873ce78460aSRick Macklem }
874ce78460aSRick Macklem break;
875ce78460aSRick Macklem #endif /* INET6 */
876ce78460aSRick Macklem #ifdef INET
877ce78460aSRick Macklem case AF_INET:
878ce78460aSRick Macklem s = socket(PF_INET, SOCK_DGRAM, 0);
879ce78460aSRick Macklem if (s < 0)
880ce78460aSRick Macklem return (0);
881ce78460aSRick Macklem memset(&sin, 0, sizeof(sin));
882ce78460aSRick Macklem sin.sin_len = sizeof(sin);
883ce78460aSRick Macklem sin.sin_family = AF_INET;
884ce78460aSRick Macklem sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
885ce78460aSRick Macklem sin.sin_port = 0;
886ce78460aSRick Macklem ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
887ce78460aSRick Macklem if (ret < 0) {
888ce78460aSRick Macklem close(s);
889ce78460aSRick Macklem return (0);
890ce78460aSRick Macklem }
891ce78460aSRick Macklem break;
892ce78460aSRick Macklem #endif /* INET */
893ce78460aSRick Macklem }
894ce78460aSRick Macklem memset(&fromip, 0, sizeof(fromip));
895ce78460aSRick Macklem slen = sizeof(fromip);
896ce78460aSRick Macklem ret = getsockname(s, (struct sockaddr *)&fromip, &slen);
897ce78460aSRick Macklem close(s);
898ce78460aSRick Macklem if (ret < 0)
899ce78460aSRick Macklem return (0);
900ce78460aSRick Macklem return (1);
901ce78460aSRick Macklem }
902ce78460aSRick Macklem
9039964058eSXin LI static void
usage(void)90403914b0bSRick Macklem usage(void)
90503914b0bSRick Macklem {
90603914b0bSRick Macklem
9077897d2a5SRick Macklem errx(1,
9087897d2a5SRick Macklem "usage: nfsuserd [-usermax cache_size] [-usertimeout minutes] [-verbose] [-manage-gids] [-domain domain_name] [n]");
90903914b0bSRick Macklem }
910