Deleted Added
full compact
nfsd.c (2030) nfsd.c (2999)
1/*
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1989, 1993, 1994\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif not lint
42
43#ifndef lint
44static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
45#endif not lint
46
47#include <sys/param.h>
48#include <sys/syslog.h>
49#include <sys/ioctl.h>
50#include <sys/stat.h>
51#include <sys/wait.h>
52#include <sys/uio.h>
53#include <sys/ucred.h>
54#include <sys/mount.h>
55#include <sys/socket.h>
56#include <sys/socketvar.h>
57
58#include <rpc/rpc.h>
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61
62#ifdef ISO
63#include <netiso/iso.h>
64#endif
65#include <nfs/rpcv2.h>
66#include <nfs/nfsv2.h>
67#include <nfs/nfs.h>
68
69#ifdef KERBEROS
70#include <kerberosIV/des.h>
71#include <kerberosIV/krb.h>
72#endif
73
74#include <err.h>
75#include <errno.h>
76#include <fcntl.h>
77#include <grp.h>
78#include <pwd.h>
79#include <signal.h>
80#include <stdio.h>
81#include <stdlib.h>
82#include <strings.h>
83#include <unistd.h>
84
85/* Global defs */
86#ifdef DEBUG
87#define syslog(e, s) fprintf(stderr,(s))
88int debug = 1;
89#else
90int debug = 0;
91#endif
92
93struct nfsd_srvargs nsd;
94char **Argv = NULL; /* pointer to argument vector */
95char *LastArg = NULL; /* end of argv */
96
97#ifdef KERBEROS
98char lnam[ANAME_SZ];
99KTEXT_ST kt;
100AUTH_DAT auth;
101char inst[INST_SZ];
102#endif
103
104void nonfs __P((int));
105void reapchild __P((int));
106void setproctitle __P((char *));
107void usage __P((void));
108
109/*
110 * Nfs server daemon mostly just a user context for nfssvc()
111 *
112 * 1 - do file descriptor and signal cleanup
113 * 2 - fork the nfsd(s)
114 * 3 - create server socket(s)
115 * 4 - register socket with portmap
116 *
117 * For connectionless protocols, just pass the socket into the kernel via.
118 * nfssvc().
119 * For connection based sockets, loop doing accepts. When you get a new
120 * socket from accept, pass the msgsock into the kernel via. nfssvc().
121 * The arguments are:
122 * -c - support iso cltp clients
123 * -r - reregister with portmapper
124 * -t - support tcp nfs clients
125 * -u - support udp nfs clients
126 * followed by "n" which is the number of nfsds' to fork off
127 */
128int
129main(argc, argv, envp)
130 int argc;
131 char *argv[], *envp[];
132{
133 extern int optind;
134 struct group *grp;
135 struct nfsd_args nfsdargs;
136 struct passwd *pwd;
137 struct ucred *cr;
138 struct sockaddr_in inetaddr, inetpeer;
139#ifdef ISO
140 struct sockaddr_iso isoaddr, isopeer;
141#endif
142 fd_set ready, sockbits;
143 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
144 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
145 int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
146 char *cp, **cpp;
1/*
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1989, 1993, 1994\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif not lint
42
43#ifndef lint
44static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
45#endif not lint
46
47#include <sys/param.h>
48#include <sys/syslog.h>
49#include <sys/ioctl.h>
50#include <sys/stat.h>
51#include <sys/wait.h>
52#include <sys/uio.h>
53#include <sys/ucred.h>
54#include <sys/mount.h>
55#include <sys/socket.h>
56#include <sys/socketvar.h>
57
58#include <rpc/rpc.h>
59#include <rpc/pmap_clnt.h>
60#include <rpc/pmap_prot.h>
61
62#ifdef ISO
63#include <netiso/iso.h>
64#endif
65#include <nfs/rpcv2.h>
66#include <nfs/nfsv2.h>
67#include <nfs/nfs.h>
68
69#ifdef KERBEROS
70#include <kerberosIV/des.h>
71#include <kerberosIV/krb.h>
72#endif
73
74#include <err.h>
75#include <errno.h>
76#include <fcntl.h>
77#include <grp.h>
78#include <pwd.h>
79#include <signal.h>
80#include <stdio.h>
81#include <stdlib.h>
82#include <strings.h>
83#include <unistd.h>
84
85/* Global defs */
86#ifdef DEBUG
87#define syslog(e, s) fprintf(stderr,(s))
88int debug = 1;
89#else
90int debug = 0;
91#endif
92
93struct nfsd_srvargs nsd;
94char **Argv = NULL; /* pointer to argument vector */
95char *LastArg = NULL; /* end of argv */
96
97#ifdef KERBEROS
98char lnam[ANAME_SZ];
99KTEXT_ST kt;
100AUTH_DAT auth;
101char inst[INST_SZ];
102#endif
103
104void nonfs __P((int));
105void reapchild __P((int));
106void setproctitle __P((char *));
107void usage __P((void));
108
109/*
110 * Nfs server daemon mostly just a user context for nfssvc()
111 *
112 * 1 - do file descriptor and signal cleanup
113 * 2 - fork the nfsd(s)
114 * 3 - create server socket(s)
115 * 4 - register socket with portmap
116 *
117 * For connectionless protocols, just pass the socket into the kernel via.
118 * nfssvc().
119 * For connection based sockets, loop doing accepts. When you get a new
120 * socket from accept, pass the msgsock into the kernel via. nfssvc().
121 * The arguments are:
122 * -c - support iso cltp clients
123 * -r - reregister with portmapper
124 * -t - support tcp nfs clients
125 * -u - support udp nfs clients
126 * followed by "n" which is the number of nfsds' to fork off
127 */
128int
129main(argc, argv, envp)
130 int argc;
131 char *argv[], *envp[];
132{
133 extern int optind;
134 struct group *grp;
135 struct nfsd_args nfsdargs;
136 struct passwd *pwd;
137 struct ucred *cr;
138 struct sockaddr_in inetaddr, inetpeer;
139#ifdef ISO
140 struct sockaddr_iso isoaddr, isopeer;
141#endif
142 fd_set ready, sockbits;
143 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
144 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
145 int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
146 char *cp, **cpp;
147 struct vfsconf *vfc;
147
148
149 vfc = getvfsbyname("nfs");
150 if(!vfc && vfsisloadable("nfs")) {
151 if(vfsload("nfs"))
152 err(1, "vfsload(nfs)");
153 endvfsent(); /* flush cache */
154 vfc = getvfsbyname("nfs"); /* probably unnecessary */
155 }
156 if(!vfc) {
157 errx(1, "NFS is not available in the running kernel");
158 }
159
148 /* Save start and extent of argv for setproctitle. */
149 Argv = argv;
150 if (envp == 0 || *envp == 0)
151 envp = argv;
152 while (*envp)
153 envp++;
154 LastArg = envp[-1] + strlen(envp[-1]);
155
156#define MAXNFSDCNT 20
157#define DEFNFSDCNT 4
158 nfsdcnt = DEFNFSDCNT;
159 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
160 tpipflag = udpflag = 0;
161#ifdef ISO
162#define GETOPT "cn:rtu"
163#define USAGE "[-crtu] [-n num_servers]"
164#else
165#define GETOPT "n:rtu"
166#define USAGE "[-rtu] [-n num_servers]"
167#endif
168 while ((ch = getopt(argc, argv, GETOPT)) != EOF)
169 switch (ch) {
170 case 'n':
171 nfsdcnt = atoi(optarg);
172 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
173 warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
174 nfsdcnt = DEFNFSDCNT;
175 }
176 break;
177 case 'r':
178 reregister = 1;
179 break;
180 case 't':
181 tcpflag = 1;
182 break;
183 case 'u':
184 udpflag = 1;
185 break;
186#ifdef ISO
187 case 'c':
188 cltpflag = 1;
189 break;
190#ifdef notyet
191 case 'i':
192 tp4cnt = 1;
193 break;
194 case 'p':
195 tpipcnt = 1;
196 break;
197#endif /* notyet */
198#endif /* ISO */
199 default:
200 case '?':
201 usage();
202 };
203 argv += optind;
204 argc -= optind;
205
206 /*
207 * XXX
208 * Backward compatibility, trailing number is the count of daemons.
209 */
210 if (argc > 1)
211 usage();
212 if (argc == 1) {
213 nfsdcnt = atoi(argv[0]);
214 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
215 warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
216 nfsdcnt = DEFNFSDCNT;
217 }
218 }
219
220 if (debug == 0) {
221 daemon(0, 0);
222 (void)signal(SIGHUP, SIG_IGN);
223 (void)signal(SIGINT, SIG_IGN);
224 (void)signal(SIGQUIT, SIG_IGN);
225 (void)signal(SIGSYS, nonfs);
226 (void)signal(SIGTERM, SIG_IGN);
227 }
228 (void)signal(SIGCHLD, reapchild);
229
230 if (reregister) {
231 if (udpflag &&
232 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
233 err(1, "can't register with portmap for UDP.");
234 if (tcpflag &&
235 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
236 err(1, "can't register with portmap for TCP.");
237 exit(0);
238 }
239 openlog("nfsd:", LOG_PID, LOG_DAEMON);
240
241 for (i = 0; i < nfsdcnt; i++) {
242 switch (fork()) {
243 case -1:
244 syslog(LOG_ERR, "fork: %m");
245 exit (1);
246 case 0:
247 break;
248 default:
249 continue;
250 }
251
252 setproctitle("nfsd-srv");
253 nfssvc_flag = NFSSVC_NFSD;
254 nsd.nsd_nfsd = NULL;
255#ifdef KERBEROS
256 nsd.nsd_authstr = (char *)kt.dat;
257#endif
258 while (nfssvc(nfssvc_flag, &nsd) < 0) {
259 if (errno != ENEEDAUTH) {
260 syslog(LOG_ERR, "nfssvc: %m");
261 exit(1);
262 }
263 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
264#ifdef KERBEROS
265 kt.length = nsd.nsd_authlen;
266 kt.mbz = 0;
267 (void)strcpy(inst, "*");
268 if (krb_rd_req(&kt, "rcmd",
269 inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
270 krb_kntoln(&auth, lnam) == KSUCCESS &&
271 (pwd = getpwnam(lnam)) != NULL) {
272 cr = &nsd.nsd_cr;
273 cr->cr_uid = pwd->pw_uid;
274 cr->cr_groups[0] = pwd->pw_gid;
275 cr->cr_ngroups = 1;
276 setgrent();
277 while ((grp = getgrent()) != NULL) {
278 if (grp->gr_gid == cr->cr_groups[0])
279 continue;
280 for (cpp = grp->gr_mem;
281 *cpp != NULL; ++cpp)
282 if (!strcmp(*cpp, lnam))
283 break;
284 if (*cpp == NULL)
285 continue;
286 cr->cr_groups[cr->cr_ngroups++]
287 = grp->gr_gid;
288 if (cr->cr_ngroups == NGROUPS)
289 break;
290 }
291 endgrent();
292 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
293 }
294#endif /* KERBEROS */
295 }
296 exit(0);
297 }
298
299 /* If we are serving udp, set up the socket. */
300 if (udpflag) {
301 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
302 syslog(LOG_ERR, "can't create udp socket");
303 exit(1);
304 }
305 inetaddr.sin_family = AF_INET;
306 inetaddr.sin_addr.s_addr = INADDR_ANY;
307 inetaddr.sin_port = htons(NFS_PORT);
308 inetaddr.sin_len = sizeof(inetaddr);
309 if (bind(sock,
310 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
311 syslog(LOG_ERR, "can't bind udp addr");
312 exit(1);
313 }
314 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
315 syslog(LOG_ERR, "can't register with udp portmap");
316 exit(1);
317 }
318 nfsdargs.sock = sock;
319 nfsdargs.name = NULL;
320 nfsdargs.namelen = 0;
321 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
322 syslog(LOG_ERR, "can't Add UDP socket");
323 exit(1);
324 }
325 (void)close(sock);
326 }
327
328#ifdef ISO
329 /* If we are serving cltp, set up the socket. */
330 if (cltpflag) {
331 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
332 syslog(LOG_ERR, "can't create cltp socket");
333 exit(1);
334 }
335 memset(&isoaddr, 0, sizeof(isoaddr));
336 isoaddr.siso_family = AF_ISO;
337 isoaddr.siso_tlen = 2;
338 cp = TSEL(&isoaddr);
339 *cp++ = (NFS_PORT >> 8);
340 *cp = (NFS_PORT & 0xff);
341 isoaddr.siso_len = sizeof(isoaddr);
342 if (bind(sock,
343 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
344 syslog(LOG_ERR, "can't bind cltp addr");
345 exit(1);
346 }
347#ifdef notyet
348 /*
349 * XXX
350 * Someday this should probably use "rpcbind", the son of
351 * portmap.
352 */
353 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
354 syslog(LOG_ERR, "can't register with udp portmap");
355 exit(1);
356 }
357#endif /* notyet */
358 nfsdargs.sock = sock;
359 nfsdargs.name = NULL;
360 nfsdargs.namelen = 0;
361 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
362 syslog(LOG_ERR, "can't add UDP socket");
363 exit(1);
364 }
365 close(sock);
366 }
367#endif /* ISO */
368
369 /* Now set up the master server socket waiting for tcp connections. */
370 on = 1;
371 FD_ZERO(&sockbits);
372 connect_type_cnt = 0;
373 if (tcpflag) {
374 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
375 syslog(LOG_ERR, "can't create tcp socket");
376 exit(1);
377 }
378 if (setsockopt(tcpsock,
379 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
380 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
381 inetaddr.sin_family = AF_INET;
382 inetaddr.sin_addr.s_addr = INADDR_ANY;
383 inetaddr.sin_port = htons(NFS_PORT);
384 inetaddr.sin_len = sizeof(inetaddr);
385 if (bind(tcpsock,
386 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
387 syslog(LOG_ERR, "can't bind tcp addr");
388 exit(1);
389 }
390 if (listen(tcpsock, 5) < 0) {
391 syslog(LOG_ERR, "listen failed");
392 exit(1);
393 }
394 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
395 syslog(LOG_ERR, "can't register tcp with portmap");
396 exit(1);
397 }
398 FD_SET(tcpsock, &sockbits);
399 maxsock = tcpsock;
400 connect_type_cnt++;
401 }
402
403#ifdef notyet
404 /* Now set up the master server socket waiting for tp4 connections. */
405 if (tp4flag) {
406 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
407 syslog(LOG_ERR, "can't create tp4 socket");
408 exit(1);
409 }
410 if (setsockopt(tp4sock,
411 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
412 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
413 memset(&isoaddr, 0, sizeof(isoaddr));
414 isoaddr.siso_family = AF_ISO;
415 isoaddr.siso_tlen = 2;
416 cp = TSEL(&isoaddr);
417 *cp++ = (NFS_PORT >> 8);
418 *cp = (NFS_PORT & 0xff);
419 isoaddr.siso_len = sizeof(isoaddr);
420 if (bind(tp4sock,
421 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
422 syslog(LOG_ERR, "can't bind tp4 addr");
423 exit(1);
424 }
425 if (listen(tp4sock, 5) < 0) {
426 syslog(LOG_ERR, "listen failed");
427 exit(1);
428 }
429 /*
430 * XXX
431 * Someday this should probably use "rpcbind", the son of
432 * portmap.
433 */
434 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
435 syslog(LOG_ERR, "can't register tcp with portmap");
436 exit(1);
437 }
438 FD_SET(tp4sock, &sockbits);
439 maxsock = tp4sock;
440 connect_type_cnt++;
441 }
442
443 /* Now set up the master server socket waiting for tpip connections. */
444 if (tpipflag) {
445 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
446 syslog(LOG_ERR, "can't create tpip socket");
447 exit(1);
448 }
449 if (setsockopt(tpipsock,
450 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
451 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
452 inetaddr.sin_family = AF_INET;
453 inetaddr.sin_addr.s_addr = INADDR_ANY;
454 inetaddr.sin_port = htons(NFS_PORT);
455 inetaddr.sin_len = sizeof(inetaddr);
456 if (bind(tpipsock,
457 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
458 syslog(LOG_ERR, "can't bind tcp addr");
459 exit(1);
460 }
461 if (listen(tpipsock, 5) < 0) {
462 syslog(LOG_ERR, "listen failed");
463 exit(1);
464 }
465 /*
466 * XXX
467 * Someday this should probably use "rpcbind", the son of
468 * portmap.
469 */
470 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
471 syslog(LOG_ERR, "can't register tcp with portmap");
472 exit(1);
473 }
474 FD_SET(tpipsock, &sockbits);
475 maxsock = tpipsock;
476 connect_type_cnt++;
477 }
478#endif /* notyet */
479
480 if (connect_type_cnt == 0)
481 exit(0);
482
483 setproctitle("nfsd-master");
484
485 /*
486 * Loop forever accepting connections and passing the sockets
487 * into the kernel for the mounts.
488 */
489 for (;;) {
490 ready = sockbits;
491 if (connect_type_cnt > 1) {
492 if (select(maxsock + 1,
493 &ready, NULL, NULL, NULL) < 1) {
494 syslog(LOG_ERR, "select failed: %m");
495 exit(1);
496 }
497 }
498 if (tcpflag && FD_ISSET(tcpsock, &ready)) {
499 len = sizeof(inetpeer);
500 if ((msgsock = accept(tcpsock,
501 (struct sockaddr *)&inetpeer, &len)) < 0) {
502 syslog(LOG_ERR, "accept failed: %m");
503 exit(1);
504 }
505 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
506 if (setsockopt(msgsock, SOL_SOCKET,
507 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
508 syslog(LOG_ERR,
509 "setsockopt SO_KEEPALIVE: %m");
510 nfsdargs.sock = msgsock;
511 nfsdargs.name = (caddr_t)&inetpeer;
512 nfsdargs.namelen = sizeof(inetpeer);
513 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
514 (void)close(msgsock);
515 }
516#ifdef notyet
517 if (tp4flag && FD_ISSET(tp4sock, &ready)) {
518 len = sizeof(isopeer);
519 if ((msgsock = accept(tp4sock,
520 (struct sockaddr *)&isopeer, &len)) < 0) {
521 syslog(LOG_ERR, "accept failed: %m");
522 exit(1);
523 }
524 if (setsockopt(msgsock, SOL_SOCKET,
525 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
526 syslog(LOG_ERR,
527 "setsockopt SO_KEEPALIVE: %m");
528 nfsdargs.sock = msgsock;
529 nfsdargs.name = (caddr_t)&isopeer;
530 nfsdargs.namelen = len;
531 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
532 (void)close(msgsock);
533 }
534 if (tpipflag && FD_ISSET(tpipsock, &ready)) {
535 len = sizeof(inetpeer);
536 if ((msgsock = accept(tpipsock,
537 (struct sockaddr *)&inetpeer, &len)) < 0) {
538 syslog(LOG_ERR, "Accept failed: %m");
539 exit(1);
540 }
541 if (setsockopt(msgsock, SOL_SOCKET,
542 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
543 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
544 nfsdargs.sock = msgsock;
545 nfsdargs.name = (caddr_t)&inetpeer;
546 nfsdargs.namelen = len;
547 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
548 (void)close(msgsock);
549 }
550#endif /* notyet */
551 }
552}
553
554void
555usage()
556{
557 (void)fprintf(stderr, "nfsd %s\n", USAGE);
558 exit(1);
559}
560
561void
562nonfs(signo)
563 int signo;
564{
565 syslog(LOG_ERR, "missing system call: NFS not available.");
566}
567
568void
569reapchild(signo)
570 int signo;
571{
572
573 while (wait3(NULL, WNOHANG, NULL));
574}
575
576void
577setproctitle(a)
578 char *a;
579{
580 register char *cp;
581 char buf[80];
582
583 cp = Argv[0];
584 (void)snprintf(buf, sizeof(buf), "%s", a);
585 (void)strncpy(cp, buf, LastArg - cp);
586 cp += strlen(cp);
587 while (cp < LastArg)
588 *cp++ = '\0';
589}
160 /* Save start and extent of argv for setproctitle. */
161 Argv = argv;
162 if (envp == 0 || *envp == 0)
163 envp = argv;
164 while (*envp)
165 envp++;
166 LastArg = envp[-1] + strlen(envp[-1]);
167
168#define MAXNFSDCNT 20
169#define DEFNFSDCNT 4
170 nfsdcnt = DEFNFSDCNT;
171 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
172 tpipflag = udpflag = 0;
173#ifdef ISO
174#define GETOPT "cn:rtu"
175#define USAGE "[-crtu] [-n num_servers]"
176#else
177#define GETOPT "n:rtu"
178#define USAGE "[-rtu] [-n num_servers]"
179#endif
180 while ((ch = getopt(argc, argv, GETOPT)) != EOF)
181 switch (ch) {
182 case 'n':
183 nfsdcnt = atoi(optarg);
184 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
185 warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
186 nfsdcnt = DEFNFSDCNT;
187 }
188 break;
189 case 'r':
190 reregister = 1;
191 break;
192 case 't':
193 tcpflag = 1;
194 break;
195 case 'u':
196 udpflag = 1;
197 break;
198#ifdef ISO
199 case 'c':
200 cltpflag = 1;
201 break;
202#ifdef notyet
203 case 'i':
204 tp4cnt = 1;
205 break;
206 case 'p':
207 tpipcnt = 1;
208 break;
209#endif /* notyet */
210#endif /* ISO */
211 default:
212 case '?':
213 usage();
214 };
215 argv += optind;
216 argc -= optind;
217
218 /*
219 * XXX
220 * Backward compatibility, trailing number is the count of daemons.
221 */
222 if (argc > 1)
223 usage();
224 if (argc == 1) {
225 nfsdcnt = atoi(argv[0]);
226 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
227 warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
228 nfsdcnt = DEFNFSDCNT;
229 }
230 }
231
232 if (debug == 0) {
233 daemon(0, 0);
234 (void)signal(SIGHUP, SIG_IGN);
235 (void)signal(SIGINT, SIG_IGN);
236 (void)signal(SIGQUIT, SIG_IGN);
237 (void)signal(SIGSYS, nonfs);
238 (void)signal(SIGTERM, SIG_IGN);
239 }
240 (void)signal(SIGCHLD, reapchild);
241
242 if (reregister) {
243 if (udpflag &&
244 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
245 err(1, "can't register with portmap for UDP.");
246 if (tcpflag &&
247 !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
248 err(1, "can't register with portmap for TCP.");
249 exit(0);
250 }
251 openlog("nfsd:", LOG_PID, LOG_DAEMON);
252
253 for (i = 0; i < nfsdcnt; i++) {
254 switch (fork()) {
255 case -1:
256 syslog(LOG_ERR, "fork: %m");
257 exit (1);
258 case 0:
259 break;
260 default:
261 continue;
262 }
263
264 setproctitle("nfsd-srv");
265 nfssvc_flag = NFSSVC_NFSD;
266 nsd.nsd_nfsd = NULL;
267#ifdef KERBEROS
268 nsd.nsd_authstr = (char *)kt.dat;
269#endif
270 while (nfssvc(nfssvc_flag, &nsd) < 0) {
271 if (errno != ENEEDAUTH) {
272 syslog(LOG_ERR, "nfssvc: %m");
273 exit(1);
274 }
275 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
276#ifdef KERBEROS
277 kt.length = nsd.nsd_authlen;
278 kt.mbz = 0;
279 (void)strcpy(inst, "*");
280 if (krb_rd_req(&kt, "rcmd",
281 inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
282 krb_kntoln(&auth, lnam) == KSUCCESS &&
283 (pwd = getpwnam(lnam)) != NULL) {
284 cr = &nsd.nsd_cr;
285 cr->cr_uid = pwd->pw_uid;
286 cr->cr_groups[0] = pwd->pw_gid;
287 cr->cr_ngroups = 1;
288 setgrent();
289 while ((grp = getgrent()) != NULL) {
290 if (grp->gr_gid == cr->cr_groups[0])
291 continue;
292 for (cpp = grp->gr_mem;
293 *cpp != NULL; ++cpp)
294 if (!strcmp(*cpp, lnam))
295 break;
296 if (*cpp == NULL)
297 continue;
298 cr->cr_groups[cr->cr_ngroups++]
299 = grp->gr_gid;
300 if (cr->cr_ngroups == NGROUPS)
301 break;
302 }
303 endgrent();
304 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
305 }
306#endif /* KERBEROS */
307 }
308 exit(0);
309 }
310
311 /* If we are serving udp, set up the socket. */
312 if (udpflag) {
313 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
314 syslog(LOG_ERR, "can't create udp socket");
315 exit(1);
316 }
317 inetaddr.sin_family = AF_INET;
318 inetaddr.sin_addr.s_addr = INADDR_ANY;
319 inetaddr.sin_port = htons(NFS_PORT);
320 inetaddr.sin_len = sizeof(inetaddr);
321 if (bind(sock,
322 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
323 syslog(LOG_ERR, "can't bind udp addr");
324 exit(1);
325 }
326 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
327 syslog(LOG_ERR, "can't register with udp portmap");
328 exit(1);
329 }
330 nfsdargs.sock = sock;
331 nfsdargs.name = NULL;
332 nfsdargs.namelen = 0;
333 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
334 syslog(LOG_ERR, "can't Add UDP socket");
335 exit(1);
336 }
337 (void)close(sock);
338 }
339
340#ifdef ISO
341 /* If we are serving cltp, set up the socket. */
342 if (cltpflag) {
343 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
344 syslog(LOG_ERR, "can't create cltp socket");
345 exit(1);
346 }
347 memset(&isoaddr, 0, sizeof(isoaddr));
348 isoaddr.siso_family = AF_ISO;
349 isoaddr.siso_tlen = 2;
350 cp = TSEL(&isoaddr);
351 *cp++ = (NFS_PORT >> 8);
352 *cp = (NFS_PORT & 0xff);
353 isoaddr.siso_len = sizeof(isoaddr);
354 if (bind(sock,
355 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
356 syslog(LOG_ERR, "can't bind cltp addr");
357 exit(1);
358 }
359#ifdef notyet
360 /*
361 * XXX
362 * Someday this should probably use "rpcbind", the son of
363 * portmap.
364 */
365 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
366 syslog(LOG_ERR, "can't register with udp portmap");
367 exit(1);
368 }
369#endif /* notyet */
370 nfsdargs.sock = sock;
371 nfsdargs.name = NULL;
372 nfsdargs.namelen = 0;
373 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
374 syslog(LOG_ERR, "can't add UDP socket");
375 exit(1);
376 }
377 close(sock);
378 }
379#endif /* ISO */
380
381 /* Now set up the master server socket waiting for tcp connections. */
382 on = 1;
383 FD_ZERO(&sockbits);
384 connect_type_cnt = 0;
385 if (tcpflag) {
386 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
387 syslog(LOG_ERR, "can't create tcp socket");
388 exit(1);
389 }
390 if (setsockopt(tcpsock,
391 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
392 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
393 inetaddr.sin_family = AF_INET;
394 inetaddr.sin_addr.s_addr = INADDR_ANY;
395 inetaddr.sin_port = htons(NFS_PORT);
396 inetaddr.sin_len = sizeof(inetaddr);
397 if (bind(tcpsock,
398 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
399 syslog(LOG_ERR, "can't bind tcp addr");
400 exit(1);
401 }
402 if (listen(tcpsock, 5) < 0) {
403 syslog(LOG_ERR, "listen failed");
404 exit(1);
405 }
406 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
407 syslog(LOG_ERR, "can't register tcp with portmap");
408 exit(1);
409 }
410 FD_SET(tcpsock, &sockbits);
411 maxsock = tcpsock;
412 connect_type_cnt++;
413 }
414
415#ifdef notyet
416 /* Now set up the master server socket waiting for tp4 connections. */
417 if (tp4flag) {
418 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
419 syslog(LOG_ERR, "can't create tp4 socket");
420 exit(1);
421 }
422 if (setsockopt(tp4sock,
423 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
424 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
425 memset(&isoaddr, 0, sizeof(isoaddr));
426 isoaddr.siso_family = AF_ISO;
427 isoaddr.siso_tlen = 2;
428 cp = TSEL(&isoaddr);
429 *cp++ = (NFS_PORT >> 8);
430 *cp = (NFS_PORT & 0xff);
431 isoaddr.siso_len = sizeof(isoaddr);
432 if (bind(tp4sock,
433 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
434 syslog(LOG_ERR, "can't bind tp4 addr");
435 exit(1);
436 }
437 if (listen(tp4sock, 5) < 0) {
438 syslog(LOG_ERR, "listen failed");
439 exit(1);
440 }
441 /*
442 * XXX
443 * Someday this should probably use "rpcbind", the son of
444 * portmap.
445 */
446 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
447 syslog(LOG_ERR, "can't register tcp with portmap");
448 exit(1);
449 }
450 FD_SET(tp4sock, &sockbits);
451 maxsock = tp4sock;
452 connect_type_cnt++;
453 }
454
455 /* Now set up the master server socket waiting for tpip connections. */
456 if (tpipflag) {
457 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
458 syslog(LOG_ERR, "can't create tpip socket");
459 exit(1);
460 }
461 if (setsockopt(tpipsock,
462 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
463 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
464 inetaddr.sin_family = AF_INET;
465 inetaddr.sin_addr.s_addr = INADDR_ANY;
466 inetaddr.sin_port = htons(NFS_PORT);
467 inetaddr.sin_len = sizeof(inetaddr);
468 if (bind(tpipsock,
469 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
470 syslog(LOG_ERR, "can't bind tcp addr");
471 exit(1);
472 }
473 if (listen(tpipsock, 5) < 0) {
474 syslog(LOG_ERR, "listen failed");
475 exit(1);
476 }
477 /*
478 * XXX
479 * Someday this should probably use "rpcbind", the son of
480 * portmap.
481 */
482 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
483 syslog(LOG_ERR, "can't register tcp with portmap");
484 exit(1);
485 }
486 FD_SET(tpipsock, &sockbits);
487 maxsock = tpipsock;
488 connect_type_cnt++;
489 }
490#endif /* notyet */
491
492 if (connect_type_cnt == 0)
493 exit(0);
494
495 setproctitle("nfsd-master");
496
497 /*
498 * Loop forever accepting connections and passing the sockets
499 * into the kernel for the mounts.
500 */
501 for (;;) {
502 ready = sockbits;
503 if (connect_type_cnt > 1) {
504 if (select(maxsock + 1,
505 &ready, NULL, NULL, NULL) < 1) {
506 syslog(LOG_ERR, "select failed: %m");
507 exit(1);
508 }
509 }
510 if (tcpflag && FD_ISSET(tcpsock, &ready)) {
511 len = sizeof(inetpeer);
512 if ((msgsock = accept(tcpsock,
513 (struct sockaddr *)&inetpeer, &len)) < 0) {
514 syslog(LOG_ERR, "accept failed: %m");
515 exit(1);
516 }
517 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
518 if (setsockopt(msgsock, SOL_SOCKET,
519 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
520 syslog(LOG_ERR,
521 "setsockopt SO_KEEPALIVE: %m");
522 nfsdargs.sock = msgsock;
523 nfsdargs.name = (caddr_t)&inetpeer;
524 nfsdargs.namelen = sizeof(inetpeer);
525 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
526 (void)close(msgsock);
527 }
528#ifdef notyet
529 if (tp4flag && FD_ISSET(tp4sock, &ready)) {
530 len = sizeof(isopeer);
531 if ((msgsock = accept(tp4sock,
532 (struct sockaddr *)&isopeer, &len)) < 0) {
533 syslog(LOG_ERR, "accept failed: %m");
534 exit(1);
535 }
536 if (setsockopt(msgsock, SOL_SOCKET,
537 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
538 syslog(LOG_ERR,
539 "setsockopt SO_KEEPALIVE: %m");
540 nfsdargs.sock = msgsock;
541 nfsdargs.name = (caddr_t)&isopeer;
542 nfsdargs.namelen = len;
543 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
544 (void)close(msgsock);
545 }
546 if (tpipflag && FD_ISSET(tpipsock, &ready)) {
547 len = sizeof(inetpeer);
548 if ((msgsock = accept(tpipsock,
549 (struct sockaddr *)&inetpeer, &len)) < 0) {
550 syslog(LOG_ERR, "Accept failed: %m");
551 exit(1);
552 }
553 if (setsockopt(msgsock, SOL_SOCKET,
554 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
555 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
556 nfsdargs.sock = msgsock;
557 nfsdargs.name = (caddr_t)&inetpeer;
558 nfsdargs.namelen = len;
559 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
560 (void)close(msgsock);
561 }
562#endif /* notyet */
563 }
564}
565
566void
567usage()
568{
569 (void)fprintf(stderr, "nfsd %s\n", USAGE);
570 exit(1);
571}
572
573void
574nonfs(signo)
575 int signo;
576{
577 syslog(LOG_ERR, "missing system call: NFS not available.");
578}
579
580void
581reapchild(signo)
582 int signo;
583{
584
585 while (wait3(NULL, WNOHANG, NULL));
586}
587
588void
589setproctitle(a)
590 char *a;
591{
592 register char *cp;
593 char buf[80];
594
595 cp = Argv[0];
596 (void)snprintf(buf, sizeof(buf), "%s", a);
597 (void)strncpy(cp, buf, LastArg - cp);
598 cp += strlen(cp);
599 while (cp < LastArg)
600 *cp++ = '\0';
601}