xref: /freebsd/usr.sbin/nfsuserd/nfsuserd.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
1 /*-
2  * Copyright (c) 2009 Rick Macklem, University of Guelph
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/linker.h>
34 #include <sys/module.h>
35 #include <sys/mount.h>
36 #include <sys/socket.h>
37 #include <sys/socketvar.h>
38 #include <sys/time.h>
39 #include <sys/ucred.h>
40 #include <sys/vnode.h>
41 #include <sys/wait.h>
42 
43 #include <nfs/nfssvc.h>
44 
45 #include <rpc/rpc.h>
46 
47 #include <fs/nfs/rpcv2.h>
48 #include <fs/nfs/nfsproto.h>
49 #include <fs/nfs/nfskpiport.h>
50 #include <fs/nfs/nfs.h>
51 
52 #include <ctype.h>
53 #include <err.h>
54 #include <grp.h>
55 #include <netdb.h>
56 #include <pwd.h>
57 #include <signal.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <syslog.h>
62 #include <unistd.h>
63 
64 /*
65  * This program loads the password and group databases into the kernel
66  * for NFS V4.
67  */
68 
69 static void	cleanup_term(int);
70 static void	usage(void);
71 static void	nfsuserdsrv(struct svc_req *, SVCXPRT *);
72 static bool_t	xdr_getid(XDR *, caddr_t);
73 static bool_t	xdr_getname(XDR *, caddr_t);
74 static bool_t	xdr_retval(XDR *, caddr_t);
75 
76 #define	MAXNAME		1024
77 #define	MAXNFSUSERD	20
78 #define	DEFNFSUSERD	4
79 #define	DEFUSERMAX	200
80 #define	DEFUSERTIMEOUT	(1 * 60)
81 struct info {
82 	long	id;
83 	long	retval;
84 	char	name[MAXNAME + 1];
85 };
86 
87 u_char *dnsname = "default.domain";
88 u_char *defaultuser = "nobody";
89 uid_t defaultuid = (uid_t)32767;
90 u_char *defaultgroup = "nogroup";
91 gid_t defaultgid = (gid_t)32767;
92 int verbose = 0, im_a_slave = 0, nfsuserdcnt = -1, forcestart = 0;
93 int defusertimeout = DEFUSERTIMEOUT;
94 pid_t slaves[MAXNFSUSERD];
95 
96 int
97 main(int argc, char *argv[])
98 {
99 	int i;
100 	int error, len, mustfreeai = 0;
101 	struct nfsd_idargs nid;
102 	struct passwd *pwd;
103 	struct group *grp;
104 	int sock, one = 1;
105 	SVCXPRT *udptransp;
106 	u_short portnum;
107 	sigset_t signew;
108 	char hostname[MAXHOSTNAMELEN + 1], *cp;
109 	struct addrinfo *aip, hints;
110 
111 	if (modfind("nfscommon") < 0) {
112 		/* Not present in kernel, try loading it */
113 		if (kldload("nfscommon") < 0 ||
114 		    modfind("nfscommon") < 0)
115 			errx(1, "Experimental nfs subsystem is not available");
116 	}
117 
118 	/*
119 	 * First, figure out what our domain name and Kerberos Realm
120 	 * seem to be. Command line args may override these later.
121 	 */
122 	if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
123 		if ((cp = strchr(hostname, '.')) != NULL &&
124 		    *(cp + 1) != '\0') {
125 			dnsname = cp + 1;
126 		} else {
127 			memset((void *)&hints, 0, sizeof (hints));
128 			hints.ai_flags = AI_CANONNAME;
129 			error = getaddrinfo(hostname, NULL, &hints, &aip);
130 			if (error == 0) {
131 			    if (aip->ai_canonname != NULL &&
132 				(cp = strchr(aip->ai_canonname, '.')) != NULL
133 				&& *(cp + 1) != '\0') {
134 					dnsname = cp + 1;
135 					mustfreeai = 1;
136 				} else {
137 					freeaddrinfo(aip);
138 				}
139 			}
140 		}
141 	}
142 	nid.nid_usermax = DEFUSERMAX;
143 	nid.nid_usertimeout = defusertimeout;
144 
145 	argc--;
146 	argv++;
147 	while (argc >= 1) {
148 		if (!strcmp(*argv, "-domain")) {
149 			if (argc == 1)
150 				usage();
151 			argc--;
152 			argv++;
153 			strncpy(hostname, *argv, MAXHOSTNAMELEN);
154 			hostname[MAXHOSTNAMELEN] = '\0';
155 			dnsname = hostname;
156 		} else if (!strcmp(*argv, "-verbose")) {
157 			verbose = 1;
158 		} else if (!strcmp(*argv, "-force")) {
159 			forcestart = 1;
160 		} else if (!strcmp(*argv, "-usermax")) {
161 			if (argc == 1)
162 				usage();
163 			argc--;
164 			argv++;
165 			i = atoi(*argv);
166 			if (i < 10 || i > 100000) {
167 				fprintf(stderr,
168 				    "usermax %d out of range 10<->100000\n", i);
169 				usage();
170 			}
171 			nid.nid_usermax = i;
172 		} else if (!strcmp(*argv, "-usertimeout")) {
173 			if (argc == 1)
174 				usage();
175 			argc--;
176 			argv++;
177 			i = atoi(*argv);
178 			if (i < 0 || i > 100000) {
179 				fprintf(stderr,
180 				    "usertimeout %d out of range 0<->100000\n",
181 				    i);
182 				usage();
183 			}
184 			nid.nid_usertimeout = defusertimeout = i * 60;
185 		} else if (nfsuserdcnt == -1) {
186 			nfsuserdcnt = atoi(*argv);
187 			if (nfsuserdcnt < 1)
188 				usage();
189 			if (nfsuserdcnt > MAXNFSUSERD) {
190 				warnx("nfsuserd count %d; reset to %d",
191 				    nfsuserdcnt, DEFNFSUSERD);
192 				nfsuserdcnt = DEFNFSUSERD;
193 			}
194 		} else {
195 			usage();
196 		}
197 		argc--;
198 		argv++;
199 	}
200 	if (nfsuserdcnt < 1)
201 		nfsuserdcnt = DEFNFSUSERD;
202 
203 	/*
204 	 * Strip off leading and trailing '.'s in domain name and map
205 	 * alphabetics to lower case.
206 	 */
207 	while (*dnsname == '.')
208 		dnsname++;
209 	if (*dnsname == '\0')
210 		errx(1, "Domain name all '.'");
211 	len = strlen(dnsname);
212 	cp = dnsname + len - 1;
213 	while (*cp == '.') {
214 		*cp = '\0';
215 		len--;
216 		cp--;
217 	}
218 	for (i = 0; i < len; i++) {
219 		if (!isascii(dnsname[i]))
220 			errx(1, "Domain name has non-ascii char");
221 		if (isupper(dnsname[i]))
222 			dnsname[i] = tolower(dnsname[i]);
223 	}
224 
225 	/*
226 	 * If the nfsuserd died off ungracefully, this is necessary to
227 	 * get them to start again.
228 	 */
229 	if (forcestart && nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0)
230 		errx(1, "Can't do nfssvc() to delete the port");
231 
232 	if (verbose)
233 		fprintf(stderr,
234 		    "nfsuserd: domain=%s usermax=%d usertimeout=%d\n",
235 		    dnsname, nid.nid_usermax, nid.nid_usertimeout);
236 
237 	for (i = 0; i < nfsuserdcnt; i++)
238 		slaves[i] = (pid_t)-1;
239 
240 	/*
241 	 * Set up the service port to accept requests via UDP from
242 	 * localhost (127.0.0.1).
243 	 */
244 	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
245 		err(1, "cannot create udp socket");
246 
247 	/*
248 	 * Not sure what this does, so I'll leave it here for now.
249 	 */
250 	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
251 
252 	if ((udptransp = svcudp_create(sock)) == NULL)
253 		err(1, "Can't set up socket");
254 
255 	/*
256 	 * By not specifying a protocol, it is linked into the
257 	 * dispatch queue, but not registered with portmapper,
258 	 * which is just what I want.
259 	 */
260 	if (!svc_register(udptransp, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS,
261 	    nfsuserdsrv, 0))
262 		err(1, "Can't register nfsuserd");
263 
264 	/*
265 	 * Tell the kernel what my port# is.
266 	 */
267 	portnum = htons(udptransp->xp_port);
268 #ifdef DEBUG
269 	printf("portnum=0x%x\n", portnum);
270 #else
271 	if (nfssvc(NFSSVC_NFSUSERDPORT, (caddr_t)&portnum) < 0) {
272 		if (errno == EPERM) {
273 			fprintf(stderr,
274 			    "Can't start nfsuserd when already running");
275 			fprintf(stderr,
276 			    " If not running, use the -force option.\n");
277 		} else {
278 			fprintf(stderr, "Can't do nfssvc() to add port\n");
279 		}
280 		exit(1);
281 	}
282 #endif
283 
284 	pwd = getpwnam(defaultuser);
285 	if (pwd)
286 		nid.nid_uid = pwd->pw_uid;
287 	else
288 		nid.nid_uid = defaultuid;
289 	grp = getgrnam(defaultgroup);
290 	if (grp)
291 		nid.nid_gid = grp->gr_gid;
292 	else
293 		nid.nid_gid = defaultgid;
294 	nid.nid_name = dnsname;
295 	nid.nid_namelen = strlen(nid.nid_name);
296 	nid.nid_flag = NFSID_INITIALIZE;
297 #ifdef DEBUG
298 	printf("Initialize uid=%d gid=%d dns=%s\n", nid.nid_uid, nid.nid_gid,
299 	    nid.nid_name);
300 #else
301 	error = nfssvc(NFSSVC_IDNAME, &nid);
302 	if (error)
303 		errx(1, "Can't initialize nfs user/groups");
304 #endif
305 
306 	i = 0;
307 	/*
308 	 * Loop around adding all groups.
309 	 */
310 	setgrent();
311 	while (i < nid.nid_usermax && (grp = getgrent())) {
312 		nid.nid_gid = grp->gr_gid;
313 		nid.nid_name = grp->gr_name;
314 		nid.nid_namelen = strlen(grp->gr_name);
315 		nid.nid_flag = NFSID_ADDGID;
316 #ifdef DEBUG
317 		printf("add gid=%d name=%s\n", nid.nid_gid, nid.nid_name);
318 #else
319 		error = nfssvc(NFSSVC_IDNAME, &nid);
320 		if (error)
321 			errx(1, "Can't add group %s", grp->gr_name);
322 #endif
323 		i++;
324 	}
325 
326 	/*
327 	 * Loop around adding all users.
328 	 */
329 	setpwent();
330 	while (i < nid.nid_usermax && (pwd = getpwent())) {
331 		nid.nid_uid = pwd->pw_uid;
332 		nid.nid_name = pwd->pw_name;
333 		nid.nid_namelen = strlen(pwd->pw_name);
334 		nid.nid_flag = NFSID_ADDUID;
335 #ifdef DEBUG
336 		printf("add uid=%d name=%s\n", nid.nid_uid, nid.nid_name);
337 #else
338 		error = nfssvc(NFSSVC_IDNAME, &nid);
339 		if (error)
340 			errx(1, "Can't add user %s", pwd->pw_name);
341 #endif
342 		i++;
343 	}
344 
345 	/*
346 	 * I should feel guilty for not calling this for all the above exit()
347 	 * upon error cases, but I don't.
348 	 */
349 	if (mustfreeai)
350 		freeaddrinfo(aip);
351 
352 #ifdef DEBUG
353 	exit(0);
354 #endif
355 	/*
356 	 * Temporarily block SIGUSR1 and SIGCHLD, so slaves[] can't
357 	 * end up bogus.
358 	 */
359 	sigemptyset(&signew);
360 	sigaddset(&signew, SIGUSR1);
361 	sigaddset(&signew, SIGCHLD);
362 	sigprocmask(SIG_BLOCK, &signew, NULL);
363 
364 	daemon(0, 0);
365 	(void)signal(SIGHUP, SIG_IGN);
366 	(void)signal(SIGINT, SIG_IGN);
367 	(void)signal(SIGQUIT, SIG_IGN);
368 	(void)signal(SIGTERM, SIG_IGN);
369 	(void)signal(SIGUSR1, cleanup_term);
370 	(void)signal(SIGCHLD, cleanup_term);
371 
372 	openlog("nfsuserd:", LOG_PID, LOG_DAEMON);
373 
374 	/*
375 	 * Fork off the slave daemons that do the work. All the master
376 	 * does is kill them off and cleanup.
377 	 */
378 	for (i = 0; i < nfsuserdcnt; i++) {
379 		slaves[i] = fork();
380 		if (slaves[i] == 0) {
381 			im_a_slave = 1;
382 			setproctitle("slave");
383 			sigemptyset(&signew);
384 			sigaddset(&signew, SIGUSR1);
385 			sigprocmask(SIG_UNBLOCK, &signew, NULL);
386 
387 			/*
388 			 * and away we go.
389 			 */
390 			svc_run();
391 			syslog(LOG_ERR, "nfsuserd died: %m");
392 			exit(1);
393 		} else if (slaves[i] < 0) {
394 			syslog(LOG_ERR, "fork: %m");
395 		}
396 	}
397 
398 	/*
399 	 * Just wait for SIGUSR1 or a child to die and then...
400 	 * As the Governor of California would say, "Terminate them".
401 	 */
402 	setproctitle("master");
403 	sigemptyset(&signew);
404 	while (1)
405 		sigsuspend(&signew);
406 }
407 
408 /*
409  * The nfsuserd rpc service
410  */
411 static void
412 nfsuserdsrv(struct svc_req *rqstp, SVCXPRT *transp)
413 {
414 	struct passwd *pwd;
415 	struct group *grp;
416 	int error;
417 	u_short sport;
418 	struct info info;
419 	struct nfsd_idargs nid;
420 	u_int32_t saddr;
421 
422 	/*
423 	 * Only handle requests from 127.0.0.1 on a reserved port number.
424 	 * (Since a reserved port # at localhost implies a client with
425 	 *  local root, there won't be a security breach. This is about
426 	 *  the only case I can think of where a reserved port # means
427 	 *  something.)
428 	 */
429 	sport = ntohs(transp->xp_raddr.sin_port);
430 	saddr = ntohl(transp->xp_raddr.sin_addr.s_addr);
431 	if ((rqstp->rq_proc != NULLPROC && sport >= IPPORT_RESERVED) ||
432 	    saddr != 0x7f000001) {
433 		syslog(LOG_ERR, "req from ip=0x%x port=%d\n", saddr, sport);
434 		svcerr_weakauth(transp);
435 		return;
436 	}
437 	switch (rqstp->rq_proc) {
438 	case NULLPROC:
439 		if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL))
440 			syslog(LOG_ERR, "Can't send reply");
441 		return;
442 	case RPCNFSUSERD_GETUID:
443 		if (!svc_getargs(transp, (xdrproc_t)xdr_getid,
444 		    (caddr_t)&info)) {
445 			svcerr_decode(transp);
446 			return;
447 		}
448 		pwd = getpwuid((uid_t)info.id);
449 		info.retval = 0;
450 		if (pwd != NULL) {
451 			nid.nid_usertimeout = defusertimeout;
452 			nid.nid_uid = pwd->pw_uid;
453 			nid.nid_name = pwd->pw_name;
454 		} else {
455 			nid.nid_usertimeout = 5;
456 			nid.nid_uid = (uid_t)info.id;
457 			nid.nid_name = defaultuser;
458 		}
459 		nid.nid_namelen = strlen(nid.nid_name);
460 		nid.nid_flag = NFSID_ADDUID;
461 		error = nfssvc(NFSSVC_IDNAME, &nid);
462 		if (error) {
463 			info.retval = error;
464 			syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name);
465 		} else if (verbose) {
466 			syslog(LOG_ERR,"Added uid=%d name=%s\n",
467 			    nid.nid_uid, nid.nid_name);
468 		}
469 		if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
470 		    (caddr_t)&info))
471 			syslog(LOG_ERR, "Can't send reply");
472 		return;
473 	case RPCNFSUSERD_GETGID:
474 		if (!svc_getargs(transp, (xdrproc_t)xdr_getid,
475 		    (caddr_t)&info)) {
476 			svcerr_decode(transp);
477 			return;
478 		}
479 		grp = getgrgid((gid_t)info.id);
480 		info.retval = 0;
481 		if (grp != NULL) {
482 			nid.nid_usertimeout = defusertimeout;
483 			nid.nid_gid = grp->gr_gid;
484 			nid.nid_name = grp->gr_name;
485 		} else {
486 			nid.nid_usertimeout = 5;
487 			nid.nid_gid = (gid_t)info.id;
488 			nid.nid_name = defaultgroup;
489 		}
490 		nid.nid_namelen = strlen(nid.nid_name);
491 		nid.nid_flag = NFSID_ADDGID;
492 		error = nfssvc(NFSSVC_IDNAME, &nid);
493 		if (error) {
494 			info.retval = error;
495 			syslog(LOG_ERR, "Can't add group %s\n",
496 			    grp->gr_name);
497 		} else if (verbose) {
498 			syslog(LOG_ERR,"Added gid=%d name=%s\n",
499 			    nid.nid_gid, nid.nid_name);
500 		}
501 		if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
502 		    (caddr_t)&info))
503 			syslog(LOG_ERR, "Can't send reply");
504 		return;
505 	case RPCNFSUSERD_GETUSER:
506 		if (!svc_getargs(transp, (xdrproc_t)xdr_getname,
507 		    (caddr_t)&info)) {
508 			svcerr_decode(transp);
509 			return;
510 		}
511 		pwd = getpwnam(info.name);
512 		info.retval = 0;
513 		if (pwd != NULL) {
514 			nid.nid_usertimeout = defusertimeout;
515 			nid.nid_uid = pwd->pw_uid;
516 			nid.nid_name = pwd->pw_name;
517 		} else {
518 			nid.nid_usertimeout = 5;
519 			nid.nid_uid = defaultuid;
520 			nid.nid_name = info.name;
521 		}
522 		nid.nid_namelen = strlen(nid.nid_name);
523 		nid.nid_flag = NFSID_ADDUSERNAME;
524 		error = nfssvc(NFSSVC_IDNAME, &nid);
525 		if (error) {
526 			info.retval = error;
527 			syslog(LOG_ERR, "Can't add user %s\n", pwd->pw_name);
528 		} else if (verbose) {
529 			syslog(LOG_ERR,"Added uid=%d name=%s\n",
530 			    nid.nid_uid, nid.nid_name);
531 		}
532 		if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
533 		    (caddr_t)&info))
534 			syslog(LOG_ERR, "Can't send reply");
535 		return;
536 	case RPCNFSUSERD_GETGROUP:
537 		if (!svc_getargs(transp, (xdrproc_t)xdr_getname,
538 		    (caddr_t)&info)) {
539 			svcerr_decode(transp);
540 			return;
541 		}
542 		grp = getgrnam(info.name);
543 		info.retval = 0;
544 		if (grp != NULL) {
545 			nid.nid_usertimeout = defusertimeout;
546 			nid.nid_gid = grp->gr_gid;
547 			nid.nid_name = grp->gr_name;
548 		} else {
549 			nid.nid_usertimeout = 5;
550 			nid.nid_gid = defaultgid;
551 			nid.nid_name = info.name;
552 		}
553 		nid.nid_namelen = strlen(nid.nid_name);
554 		nid.nid_flag = NFSID_ADDGROUPNAME;
555 		error = nfssvc(NFSSVC_IDNAME, &nid);
556 		if (error) {
557 			info.retval = error;
558 			syslog(LOG_ERR, "Can't add group %s\n",
559 			    grp->gr_name);
560 		} else if (verbose) {
561 			syslog(LOG_ERR,"Added gid=%d name=%s\n",
562 			    nid.nid_gid, nid.nid_name);
563 		}
564 		if (!svc_sendreply(transp, (xdrproc_t)xdr_retval,
565 		    (caddr_t)&info))
566 			syslog(LOG_ERR, "Can't send reply");
567 		return;
568 	default:
569 		svcerr_noproc(transp);
570 		return;
571 	};
572 }
573 
574 /*
575  * Xdr routine to get an id number
576  */
577 static bool_t
578 xdr_getid(XDR *xdrsp, caddr_t cp)
579 {
580 	struct info *ifp = (struct info *)cp;
581 
582 	return (xdr_long(xdrsp, &ifp->id));
583 }
584 
585 /*
586  * Xdr routine to get a user name
587  */
588 static bool_t
589 xdr_getname(XDR *xdrsp, caddr_t cp)
590 {
591 	struct info *ifp = (struct info *)cp;
592 	long len;
593 
594 	if (!xdr_long(xdrsp, &len))
595 		return (0);
596 	if (len > MAXNAME)
597 		return (0);
598 	if (!xdr_opaque(xdrsp, ifp->name, len))
599 		return (0);
600 	ifp->name[len] = '\0';
601 	return (1);
602 }
603 
604 /*
605  * Xdr routine to return the value.
606  */
607 static bool_t
608 xdr_retval(XDR *xdrsp, caddr_t cp)
609 {
610 	struct info *ifp = (struct info *)cp;
611 	long val;
612 
613 	val = ifp->retval;
614 	return (xdr_long(xdrsp, &val));
615 }
616 
617 /*
618  * cleanup_term() called via SIGUSR1.
619  */
620 static void
621 cleanup_term(int signo __unused)
622 {
623 	int i, cnt;
624 
625 	if (im_a_slave)
626 		exit(0);
627 
628 	/*
629 	 * Ok, so I'm the master.
630 	 * As the Governor of California might say, "Terminate them".
631 	 */
632 	cnt = 0;
633 	for (i = 0; i < nfsuserdcnt; i++) {
634 		if (slaves[i] != (pid_t)-1) {
635 			cnt++;
636 			kill(slaves[i], SIGUSR1);
637 		}
638 	}
639 
640 	/*
641 	 * and wait for them to die
642 	 */
643 	for (i = 0; i < cnt; i++)
644 		wait3(NULL, 0, NULL);
645 
646 	/*
647 	 * Finally, get rid of the socket
648 	 */
649 	if (nfssvc(NFSSVC_NFSUSERDDELPORT, NULL) < 0) {
650 		syslog(LOG_ERR, "Can't do nfssvc() to delete the port\n");
651 		exit(1);
652 	}
653 	exit(0);
654 }
655 
656 static void
657 usage(void)
658 {
659 
660 	errx(1,
661 	    "usage: nfsuserd [-usermax cache_size] [-usertimeout minutes] [-verbose] [-domain domain_name] [n]");
662 }
663