Commit | Line | Data |
---|---|---|
e3ab21d9 | 1 | /* |
587330af | 2 | * Copyright (c) 1989, 1993, 1994 |
da519673 | 3 | * The Regents of the University of California. All rights reserved. |
e3ab21d9 KM |
4 | * |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Rick Macklem at The University of Guelph. | |
7 | * | |
70ab3c27 | 8 | * %sccs.include.redist.c% |
e3ab21d9 KM |
9 | */ |
10 | ||
11 | #ifndef lint | |
da519673 | 12 | static char copyright[] = |
587330af | 13 | "@(#) Copyright (c) 1989, 1993, 1994\n\ |
da519673 | 14 | The Regents of the University of California. All rights reserved.\n"; |
e3ab21d9 KM |
15 | #endif not lint |
16 | ||
17 | #ifndef lint | |
f7cbb72d | 18 | static char sccsid[] = "@(#)nfsd.c 8.10 (Berkeley) %G%"; |
e3ab21d9 KM |
19 | #endif not lint |
20 | ||
9a8f56c5 | 21 | #include <sys/param.h> |
587330af | 22 | #include <sys/syslog.h> |
e3ab21d9 KM |
23 | #include <sys/ioctl.h> |
24 | #include <sys/stat.h> | |
af62051f | 25 | #include <sys/wait.h> |
9a8f56c5 | 26 | #include <sys/uio.h> |
9a8f56c5 | 27 | #include <sys/ucred.h> |
e3ab21d9 KM |
28 | #include <sys/mount.h> |
29 | #include <sys/socket.h> | |
30 | #include <sys/socketvar.h> | |
587330af | 31 | |
e3ab21d9 KM |
32 | #include <rpc/rpc.h> |
33 | #include <rpc/pmap_clnt.h> | |
34 | #include <rpc/pmap_prot.h> | |
587330af | 35 | |
9a8f56c5 KM |
36 | #ifdef ISO |
37 | #include <netiso/iso.h> | |
38 | #endif | |
e3ab21d9 | 39 | #include <nfs/rpcv2.h> |
3e124b12 | 40 | #include <nfs/nfsproto.h> |
9a8f56c5 | 41 | #include <nfs/nfs.h> |
587330af | 42 | |
3e124b12 | 43 | #ifdef NFSKERB |
dbbed105 | 44 | #include <kerberosIV/des.h> |
9a8f56c5 KM |
45 | #include <kerberosIV/krb.h> |
46 | #endif | |
e3ab21d9 | 47 | |
587330af KB |
48 | #include <err.h> |
49 | #include <errno.h> | |
50 | #include <fcntl.h> | |
51 | #include <grp.h> | |
52 | #include <pwd.h> | |
53 | #include <signal.h> | |
54 | #include <stdio.h> | |
55 | #include <stdlib.h> | |
56 | #include <strings.h> | |
57 | #include <unistd.h> | |
58 | ||
e3ab21d9 KM |
59 | /* Global defs */ |
60 | #ifdef DEBUG | |
61 | #define syslog(e, s) fprintf(stderr,(s)) | |
bad1fdd6 | 62 | int debug = 1; |
e3ab21d9 | 63 | #else |
bad1fdd6 | 64 | int debug = 0; |
e3ab21d9 | 65 | #endif |
587330af | 66 | |
9a8f56c5 | 67 | struct nfsd_srvargs nsd; |
bad1fdd6 MK |
68 | char **Argv = NULL; /* pointer to argument vector */ |
69 | char *LastArg = NULL; /* end of argv */ | |
e3ab21d9 | 70 | |
3e124b12 | 71 | #ifdef NFSKERB |
9a8f56c5 KM |
72 | char lnam[ANAME_SZ]; |
73 | KTEXT_ST kt; | |
3e124b12 | 74 | AUTH_DAT kauth; |
9a8f56c5 | 75 | char inst[INST_SZ]; |
3e124b12 KM |
76 | struct nfsrpc_fullblock kin, kout; |
77 | struct nfsrpc_fullverf kverf; | |
78 | NFSKERBKEY_T kivec; | |
79 | struct timeval ktv; | |
80 | NFSKERBKEYSCHED_T kerb_keysched; | |
587330af KB |
81 | #endif |
82 | ||
0d28df7e | 83 | void nonfs __P((int)); |
587330af KB |
84 | void reapchild __P((int)); |
85 | void setproctitle __P((char *)); | |
86 | void usage __P((void)); | |
9a8f56c5 | 87 | |
e3ab21d9 KM |
88 | /* |
89 | * Nfs server daemon mostly just a user context for nfssvc() | |
587330af | 90 | * |
e3ab21d9 | 91 | * 1 - do file descriptor and signal cleanup |
9a8f56c5 KM |
92 | * 2 - fork the nfsd(s) |
93 | * 3 - create server socket(s) | |
94 | * 4 - register socket with portmap | |
587330af | 95 | * |
9a8f56c5 KM |
96 | * For connectionless protocols, just pass the socket into the kernel via. |
97 | * nfssvc(). | |
587330af KB |
98 | * For connection based sockets, loop doing accepts. When you get a new |
99 | * socket from accept, pass the msgsock into the kernel via. nfssvc(). | |
af62051f | 100 | * The arguments are: |
587330af KB |
101 | * -c - support iso cltp clients |
102 | * -r - reregister with portmapper | |
103 | * -t - support tcp nfs clients | |
104 | * -u - support udp nfs clients | |
9a8f56c5 | 105 | * followed by "n" which is the number of nfsds' to fork off |
e3ab21d9 | 106 | */ |
587330af | 107 | int |
bad1fdd6 | 108 | main(argc, argv, envp) |
e3ab21d9 | 109 | int argc; |
bad1fdd6 | 110 | char *argv[], *envp[]; |
e3ab21d9 | 111 | { |
587330af | 112 | extern int optind; |
9a8f56c5 | 113 | struct group *grp; |
587330af KB |
114 | struct nfsd_args nfsdargs; |
115 | struct passwd *pwd; | |
116 | struct ucred *cr; | |
9a8f56c5 KM |
117 | struct sockaddr_in inetaddr, inetpeer; |
118 | #ifdef ISO | |
119 | struct sockaddr_iso isoaddr, isopeer; | |
120 | #endif | |
3e124b12 | 121 | struct timeval ktv; |
9a8f56c5 | 122 | fd_set ready, sockbits; |
587330af KB |
123 | int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; |
124 | int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; | |
125 | int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; | |
126 | char *cp, **cpp; | |
bad1fdd6 | 127 | |
587330af | 128 | /* Save start and extent of argv for setproctitle. */ |
bad1fdd6 MK |
129 | Argv = argv; |
130 | if (envp == 0 || *envp == 0) | |
131 | envp = argv; | |
132 | while (*envp) | |
133 | envp++; | |
134 | LastArg = envp[-1] + strlen(envp[-1]); | |
587330af | 135 | |
ef57306a KB |
136 | #define MAXNFSDCNT 20 |
137 | #define DEFNFSDCNT 4 | |
138 | nfsdcnt = DEFNFSDCNT; | |
587330af KB |
139 | cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; |
140 | tpipflag = udpflag = 0; | |
141 | #ifdef ISO | |
ef57306a KB |
142 | #define GETOPT "cn:rtu" |
143 | #define USAGE "[-crtu] [-n num_servers]" | |
587330af | 144 | #else |
ef57306a KB |
145 | #define GETOPT "n:rtu" |
146 | #define USAGE "[-rtu] [-n num_servers]" | |
587330af | 147 | #endif |
ef57306a | 148 | while ((ch = getopt(argc, argv, GETOPT)) != EOF) |
587330af | 149 | switch (ch) { |
ef57306a | 150 | case 'n': |
661ac293 | 151 | nfsdcnt = atoi(optarg); |
ef57306a KB |
152 | if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { |
153 | warnx("nfsd count %d; reset to %d", DEFNFSDCNT); | |
154 | nfsdcnt = DEFNFSDCNT; | |
155 | } | |
156 | break; | |
587330af KB |
157 | case 'r': |
158 | reregister = 1; | |
bad1fdd6 | 159 | break; |
af62051f | 160 | case 't': |
587330af | 161 | tcpflag = 1; |
af62051f | 162 | break; |
587330af KB |
163 | case 'u': |
164 | udpflag = 1; | |
9a8f56c5 KM |
165 | break; |
166 | #ifdef ISO | |
167 | case 'c': | |
587330af | 168 | cltpflag = 1; |
9a8f56c5 KM |
169 | break; |
170 | #ifdef notyet | |
171 | case 'i': | |
587330af | 172 | tp4cnt = 1; |
af62051f | 173 | break; |
9a8f56c5 | 174 | case 'p': |
587330af | 175 | tpipcnt = 1; |
9a8f56c5 KM |
176 | break; |
177 | #endif /* notyet */ | |
587330af | 178 | #endif /* ISO */ |
af62051f KM |
179 | default: |
180 | case '?': | |
181 | usage(); | |
9a8f56c5 | 182 | }; |
587330af KB |
183 | argv += optind; |
184 | argc -= optind; | |
185 | ||
ef57306a KB |
186 | /* |
187 | * XXX | |
188 | * Backward compatibility, trailing number is the count of daemons. | |
189 | */ | |
587330af KB |
190 | if (argc > 1) |
191 | usage(); | |
192 | if (argc == 1) { | |
661ac293 | 193 | nfsdcnt = atoi(argv[0]); |
ef57306a KB |
194 | if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { |
195 | warnx("nfsd count %d; reset to %d", DEFNFSDCNT); | |
196 | nfsdcnt = DEFNFSDCNT; | |
587330af KB |
197 | } |
198 | } | |
bad1fdd6 | 199 | |
e3ab21d9 | 200 | if (debug == 0) { |
43d42ac6 | 201 | daemon(0, 0); |
d6a55244 | 202 | (void)signal(SIGHUP, SIG_IGN); |
587330af KB |
203 | (void)signal(SIGINT, SIG_IGN); |
204 | (void)signal(SIGQUIT, SIG_IGN); | |
d6a55244 | 205 | (void)signal(SIGSYS, nonfs); |
587330af | 206 | (void)signal(SIGTERM, SIG_IGN); |
e3ab21d9 | 207 | } |
587330af | 208 | (void)signal(SIGCHLD, reapchild); |
bad1fdd6 MK |
209 | |
210 | if (reregister) { | |
587330af | 211 | if (udpflag && |
3e124b12 KM |
212 | (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || |
213 | !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) | |
587330af KB |
214 | err(1, "can't register with portmap for UDP."); |
215 | if (tcpflag && | |
3e124b12 KM |
216 | (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || |
217 | !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) | |
587330af | 218 | err(1, "can't register with portmap for TCP."); |
bad1fdd6 MK |
219 | exit(0); |
220 | } | |
e3ab21d9 | 221 | openlog("nfsd:", LOG_PID, LOG_DAEMON); |
9a8f56c5 | 222 | |
587330af KB |
223 | for (i = 0; i < nfsdcnt; i++) { |
224 | switch (fork()) { | |
225 | case -1: | |
226 | syslog(LOG_ERR, "fork: %m"); | |
227 | exit (1); | |
228 | case 0: | |
229 | break; | |
230 | default: | |
231 | continue; | |
232 | } | |
233 | ||
3e124b12 | 234 | setproctitle("server"); |
9a8f56c5 | 235 | nfssvc_flag = NFSSVC_NFSD; |
587330af | 236 | nsd.nsd_nfsd = NULL; |
3e124b12 KM |
237 | #ifdef NFSKERB |
238 | if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || | |
239 | sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) | |
240 | syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); | |
241 | nsd.nsd_authstr = (u_char *)&kt; | |
242 | nsd.nsd_authlen = sizeof (kt); | |
243 | nsd.nsd_verfstr = (u_char *)&kverf; | |
244 | nsd.nsd_verflen = sizeof (kverf); | |
bad1fdd6 | 245 | #endif |
587330af KB |
246 | while (nfssvc(nfssvc_flag, &nsd) < 0) { |
247 | if (errno != ENEEDAUTH) { | |
248 | syslog(LOG_ERR, "nfssvc: %m"); | |
249 | exit(1); | |
250 | } | |
251 | nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; | |
3e124b12 KM |
252 | #ifdef NFSKERB |
253 | /* | |
254 | * Get the Kerberos ticket out of the authenticator | |
255 | * verify it and convert the principal name to a user | |
256 | * name. The user name is then converted to a set of | |
257 | * user credentials via the password and group file. | |
258 | * Finally, decrypt the timestamp and validate it. | |
259 | * For more info see the IETF Draft "Authentication | |
260 | * in ONC RPC". | |
261 | */ | |
262 | kt.length = ntohl(kt.length); | |
263 | if (gettimeofday(&ktv, (struct timezone *)0) == 0 && | |
264 | kt.length > 0 && kt.length <= | |
265 | (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { | |
266 | kin.w1 = NFS_KERBW1(kt); | |
267 | kt.mbz = 0; | |
268 | (void)strcpy(inst, "*"); | |
269 | if (krb_rd_req(&kt, NFS_KERBSRV, | |
270 | inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && | |
271 | krb_kntoln(&kauth, lnam) == KSUCCESS && | |
272 | (pwd = getpwnam(lnam)) != NULL) { | |
587330af KB |
273 | cr = &nsd.nsd_cr; |
274 | cr->cr_uid = pwd->pw_uid; | |
275 | cr->cr_groups[0] = pwd->pw_gid; | |
276 | cr->cr_ngroups = 1; | |
277 | setgrent(); | |
278 | while ((grp = getgrent()) != NULL) { | |
279 | if (grp->gr_gid == cr->cr_groups[0]) | |
280 | continue; | |
281 | for (cpp = grp->gr_mem; | |
282 | *cpp != NULL; ++cpp) | |
283 | if (!strcmp(*cpp, lnam)) | |
284 | break; | |
285 | if (*cpp == NULL) | |
286 | continue; | |
287 | cr->cr_groups[cr->cr_ngroups++] | |
288 | = grp->gr_gid; | |
289 | if (cr->cr_ngroups == NGROUPS) | |
290 | break; | |
9a8f56c5 | 291 | } |
587330af | 292 | endgrent(); |
3e124b12 KM |
293 | |
294 | /* | |
295 | * Get the timestamp verifier out of the | |
296 | * authenticator and verifier strings. | |
297 | */ | |
298 | kin.t1 = kverf.t1; | |
299 | kin.t2 = kverf.t2; | |
300 | kin.w2 = kverf.w2; | |
301 | bzero((caddr_t)kivec, sizeof (kivec)); | |
302 | bcopy((caddr_t)kauth.session, | |
303 | (caddr_t)nsd.nsd_key,sizeof(kauth.session)); | |
304 | ||
305 | /* | |
306 | * Decrypt the timestamp verifier in CBC mode. | |
307 | */ | |
308 | XXX | |
309 | ||
310 | /* | |
311 | * Validate the timestamp verifier, to | |
312 | * check that the session key is ok. | |
313 | */ | |
314 | nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); | |
315 | nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); | |
316 | nsd.nsd_ttl = ntohl(kout.w1); | |
317 | if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) | |
318 | nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; | |
9a8f56c5 | 319 | } |
3e124b12 | 320 | #endif /* NFSKERB */ |
9a8f56c5 | 321 | } |
587330af KB |
322 | exit(0); |
323 | } | |
9a8f56c5 | 324 | |
587330af | 325 | /* If we are serving udp, set up the socket. */ |
af62051f KM |
326 | if (udpflag) { |
327 | if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | |
587330af | 328 | syslog(LOG_ERR, "can't create udp socket"); |
af62051f KM |
329 | exit(1); |
330 | } | |
9a8f56c5 KM |
331 | inetaddr.sin_family = AF_INET; |
332 | inetaddr.sin_addr.s_addr = INADDR_ANY; | |
333 | inetaddr.sin_port = htons(NFS_PORT); | |
334 | inetaddr.sin_len = sizeof(inetaddr); | |
587330af KB |
335 | if (bind(sock, |
336 | (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { | |
337 | syslog(LOG_ERR, "can't bind udp addr"); | |
af62051f KM |
338 | exit(1); |
339 | } | |
3e124b12 KM |
340 | if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || |
341 | !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { | |
587330af | 342 | syslog(LOG_ERR, "can't register with udp portmap"); |
9a8f56c5 KM |
343 | exit(1); |
344 | } | |
345 | nfsdargs.sock = sock; | |
587330af | 346 | nfsdargs.name = NULL; |
9a8f56c5 KM |
347 | nfsdargs.namelen = 0; |
348 | if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { | |
587330af | 349 | syslog(LOG_ERR, "can't Add UDP socket"); |
af62051f KM |
350 | exit(1); |
351 | } | |
587330af | 352 | (void)close(sock); |
9a8f56c5 KM |
353 | } |
354 | ||
9a8f56c5 | 355 | #ifdef ISO |
587330af | 356 | /* If we are serving cltp, set up the socket. */ |
9a8f56c5 KM |
357 | if (cltpflag) { |
358 | if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { | |
587330af | 359 | syslog(LOG_ERR, "can't create cltp socket"); |
9a8f56c5 KM |
360 | exit(1); |
361 | } | |
587330af | 362 | memset(&isoaddr, 0, sizeof(isoaddr)); |
9a8f56c5 KM |
363 | isoaddr.siso_family = AF_ISO; |
364 | isoaddr.siso_tlen = 2; | |
365 | cp = TSEL(&isoaddr); | |
366 | *cp++ = (NFS_PORT >> 8); | |
367 | *cp = (NFS_PORT & 0xff); | |
368 | isoaddr.siso_len = sizeof(isoaddr); | |
587330af KB |
369 | if (bind(sock, |
370 | (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { | |
371 | syslog(LOG_ERR, "can't bind cltp addr"); | |
9a8f56c5 KM |
372 | exit(1); |
373 | } | |
374 | #ifdef notyet | |
af62051f | 375 | /* |
587330af | 376 | * XXX |
9a8f56c5 KM |
377 | * Someday this should probably use "rpcbind", the son of |
378 | * portmap. | |
af62051f | 379 | */ |
9a8f56c5 | 380 | if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { |
587330af | 381 | syslog(LOG_ERR, "can't register with udp portmap"); |
9a8f56c5 KM |
382 | exit(1); |
383 | } | |
384 | #endif /* notyet */ | |
385 | nfsdargs.sock = sock; | |
587330af | 386 | nfsdargs.name = NULL; |
9a8f56c5 KM |
387 | nfsdargs.namelen = 0; |
388 | if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { | |
587330af KB |
389 | syslog(LOG_ERR, "can't add UDP socket"); |
390 | exit(1); | |
9a8f56c5 | 391 | } |
af62051f | 392 | close(sock); |
e3ab21d9 | 393 | } |
587330af | 394 | #endif /* ISO */ |
af62051f | 395 | |
587330af KB |
396 | /* Now set up the master server socket waiting for tcp connections. */ |
397 | on = 1; | |
9a8f56c5 | 398 | FD_ZERO(&sockbits); |
587330af | 399 | connect_type_cnt = 0; |
af62051f | 400 | if (tcpflag) { |
9a8f56c5 | 401 | if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
587330af | 402 | syslog(LOG_ERR, "can't create tcp socket"); |
9a8f56c5 KM |
403 | exit(1); |
404 | } | |
587330af KB |
405 | if (setsockopt(tcpsock, |
406 | SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) | |
9a8f56c5 KM |
407 | syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); |
408 | inetaddr.sin_family = AF_INET; | |
409 | inetaddr.sin_addr.s_addr = INADDR_ANY; | |
410 | inetaddr.sin_port = htons(NFS_PORT); | |
587330af KB |
411 | inetaddr.sin_len = sizeof(inetaddr); |
412 | if (bind(tcpsock, | |
413 | (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { | |
414 | syslog(LOG_ERR, "can't bind tcp addr"); | |
9a8f56c5 KM |
415 | exit(1); |
416 | } | |
417 | if (listen(tcpsock, 5) < 0) { | |
587330af | 418 | syslog(LOG_ERR, "listen failed"); |
9a8f56c5 KM |
419 | exit(1); |
420 | } | |
3e124b12 KM |
421 | if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || |
422 | !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { | |
587330af | 423 | syslog(LOG_ERR, "can't register tcp with portmap"); |
9a8f56c5 KM |
424 | exit(1); |
425 | } | |
426 | FD_SET(tcpsock, &sockbits); | |
427 | maxsock = tcpsock; | |
428 | connect_type_cnt++; | |
429 | } | |
bad1fdd6 | 430 | |
9a8f56c5 | 431 | #ifdef notyet |
587330af | 432 | /* Now set up the master server socket waiting for tp4 connections. */ |
9a8f56c5 KM |
433 | if (tp4flag) { |
434 | if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { | |
587330af | 435 | syslog(LOG_ERR, "can't create tp4 socket"); |
af62051f KM |
436 | exit(1); |
437 | } | |
587330af KB |
438 | if (setsockopt(tp4sock, |
439 | SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) | |
bad1fdd6 | 440 | syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); |
587330af | 441 | memset(&isoaddr, 0, sizeof(isoaddr)); |
9a8f56c5 KM |
442 | isoaddr.siso_family = AF_ISO; |
443 | isoaddr.siso_tlen = 2; | |
444 | cp = TSEL(&isoaddr); | |
445 | *cp++ = (NFS_PORT >> 8); | |
446 | *cp = (NFS_PORT & 0xff); | |
447 | isoaddr.siso_len = sizeof(isoaddr); | |
587330af KB |
448 | if (bind(tp4sock, |
449 | (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { | |
450 | syslog(LOG_ERR, "can't bind tp4 addr"); | |
af62051f KM |
451 | exit(1); |
452 | } | |
9a8f56c5 | 453 | if (listen(tp4sock, 5) < 0) { |
587330af | 454 | syslog(LOG_ERR, "listen failed"); |
af62051f KM |
455 | exit(1); |
456 | } | |
9a8f56c5 | 457 | /* |
587330af KB |
458 | * XXX |
459 | * Someday this should probably use "rpcbind", the son of | |
460 | * portmap. | |
9a8f56c5 | 461 | */ |
af62051f | 462 | if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { |
587330af | 463 | syslog(LOG_ERR, "can't register tcp with portmap"); |
9a8f56c5 KM |
464 | exit(1); |
465 | } | |
466 | FD_SET(tp4sock, &sockbits); | |
467 | maxsock = tp4sock; | |
468 | connect_type_cnt++; | |
469 | } | |
470 | ||
587330af | 471 | /* Now set up the master server socket waiting for tpip connections. */ |
9a8f56c5 KM |
472 | if (tpipflag) { |
473 | if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { | |
587330af | 474 | syslog(LOG_ERR, "can't create tpip socket"); |
9a8f56c5 KM |
475 | exit(1); |
476 | } | |
587330af KB |
477 | if (setsockopt(tpipsock, |
478 | SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) | |
9a8f56c5 KM |
479 | syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); |
480 | inetaddr.sin_family = AF_INET; | |
481 | inetaddr.sin_addr.s_addr = INADDR_ANY; | |
482 | inetaddr.sin_port = htons(NFS_PORT); | |
587330af KB |
483 | inetaddr.sin_len = sizeof(inetaddr); |
484 | if (bind(tpipsock, | |
485 | (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { | |
486 | syslog(LOG_ERR, "can't bind tcp addr"); | |
9a8f56c5 KM |
487 | exit(1); |
488 | } | |
489 | if (listen(tpipsock, 5) < 0) { | |
587330af | 490 | syslog(LOG_ERR, "listen failed"); |
af62051f KM |
491 | exit(1); |
492 | } | |
493 | /* | |
587330af KB |
494 | * XXX |
495 | * Someday this should probably use "rpcbind", the son of | |
496 | * portmap. | |
af62051f | 497 | */ |
9a8f56c5 | 498 | if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { |
587330af | 499 | syslog(LOG_ERR, "can't register tcp with portmap"); |
9a8f56c5 KM |
500 | exit(1); |
501 | } | |
502 | FD_SET(tpipsock, &sockbits); | |
503 | maxsock = tpipsock; | |
504 | connect_type_cnt++; | |
505 | } | |
587330af | 506 | #endif /* notyet */ |
9a8f56c5 KM |
507 | |
508 | if (connect_type_cnt == 0) | |
587330af KB |
509 | exit(0); |
510 | ||
3e124b12 | 511 | setproctitle("master"); |
587330af | 512 | |
9a8f56c5 KM |
513 | /* |
514 | * Loop forever accepting connections and passing the sockets | |
515 | * into the kernel for the mounts. | |
516 | */ | |
517 | for (;;) { | |
518 | ready = sockbits; | |
519 | if (connect_type_cnt > 1) { | |
587330af KB |
520 | if (select(maxsock + 1, |
521 | &ready, NULL, NULL, NULL) < 1) { | |
522 | syslog(LOG_ERR, "select failed: %m"); | |
9a8f56c5 KM |
523 | exit(1); |
524 | } | |
525 | } | |
526 | if (tcpflag && FD_ISSET(tcpsock, &ready)) { | |
527 | len = sizeof(inetpeer); | |
528 | if ((msgsock = accept(tcpsock, | |
529 | (struct sockaddr *)&inetpeer, &len)) < 0) { | |
587330af | 530 | syslog(LOG_ERR, "accept failed: %m"); |
af62051f KM |
531 | exit(1); |
532 | } | |
587330af | 533 | memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); |
9a8f56c5 | 534 | if (setsockopt(msgsock, SOL_SOCKET, |
587330af | 535 | SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) |
9a8f56c5 KM |
536 | syslog(LOG_ERR, |
537 | "setsockopt SO_KEEPALIVE: %m"); | |
538 | nfsdargs.sock = msgsock; | |
539 | nfsdargs.name = (caddr_t)&inetpeer; | |
d674eb63 | 540 | nfsdargs.namelen = sizeof(inetpeer); |
9a8f56c5 | 541 | nfssvc(NFSSVC_ADDSOCK, &nfsdargs); |
587330af | 542 | (void)close(msgsock); |
9a8f56c5 KM |
543 | } |
544 | #ifdef notyet | |
545 | if (tp4flag && FD_ISSET(tp4sock, &ready)) { | |
546 | len = sizeof(isopeer); | |
547 | if ((msgsock = accept(tp4sock, | |
548 | (struct sockaddr *)&isopeer, &len)) < 0) { | |
587330af | 549 | syslog(LOG_ERR, "accept failed: %m"); |
9a8f56c5 | 550 | exit(1); |
af62051f | 551 | } |
9a8f56c5 | 552 | if (setsockopt(msgsock, SOL_SOCKET, |
587330af | 553 | SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) |
9a8f56c5 KM |
554 | syslog(LOG_ERR, |
555 | "setsockopt SO_KEEPALIVE: %m"); | |
556 | nfsdargs.sock = msgsock; | |
557 | nfsdargs.name = (caddr_t)&isopeer; | |
558 | nfsdargs.namelen = len; | |
559 | nfssvc(NFSSVC_ADDSOCK, &nfsdargs); | |
587330af | 560 | (void)close(msgsock); |
9a8f56c5 KM |
561 | } |
562 | if (tpipflag && FD_ISSET(tpipsock, &ready)) { | |
563 | len = sizeof(inetpeer); | |
564 | if ((msgsock = accept(tpipsock, | |
565 | (struct sockaddr *)&inetpeer, &len)) < 0) { | |
566 | syslog(LOG_ERR, "Accept failed: %m"); | |
362d7dce | 567 | exit(1); |
af62051f | 568 | } |
9a8f56c5 | 569 | if (setsockopt(msgsock, SOL_SOCKET, |
587330af KB |
570 | SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) |
571 | syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); | |
9a8f56c5 KM |
572 | nfsdargs.sock = msgsock; |
573 | nfsdargs.name = (caddr_t)&inetpeer; | |
574 | nfsdargs.namelen = len; | |
575 | nfssvc(NFSSVC_ADDSOCK, &nfsdargs); | |
587330af | 576 | (void)close(msgsock); |
af62051f | 577 | } |
587330af | 578 | #endif /* notyet */ |
1b3a818d | 579 | } |
af62051f KM |
580 | } |
581 | ||
587330af | 582 | void |
af62051f KM |
583 | usage() |
584 | { | |
3e124b12 | 585 | (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); |
af62051f | 586 | exit(1); |
e3ab21d9 | 587 | } |
bad1fdd6 | 588 | |
0d28df7e KB |
589 | void |
590 | nonfs(signo) | |
591 | int signo; | |
592 | { | |
593 | syslog(LOG_ERR, "missing system call: NFS not available."); | |
594 | } | |
595 | ||
bad1fdd6 | 596 | void |
587330af KB |
597 | reapchild(signo) |
598 | int signo; | |
bad1fdd6 MK |
599 | { |
600 | ||
3e124b12 | 601 | while (wait3(NULL, WNOHANG, NULL) > 0); |
bad1fdd6 MK |
602 | } |
603 | ||
587330af | 604 | void |
9a8f56c5 | 605 | setproctitle(a) |
bad1fdd6 | 606 | char *a; |
bad1fdd6 MK |
607 | { |
608 | register char *cp; | |
609 | char buf[80]; | |
610 | ||
611 | cp = Argv[0]; | |
3e124b12 | 612 | (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); |
587330af | 613 | (void)strncpy(cp, buf, LastArg - cp); |
bad1fdd6 MK |
614 | cp += strlen(cp); |
615 | while (cp < LastArg) | |
4ea4dec8 | 616 | *cp++ = '\0'; |
bad1fdd6 | 617 | } |