Deleted Added
full compact
nfsd.c (65379) nfsd.c (74462)
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 const 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
44#if 0
45static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
46#endif
47static const char rcsid[] =
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 const 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
44#if 0
45static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
46#endif
47static const char rcsid[] =
48 "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 65379 2000-09-02 20:52:15Z brian $";
48 "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 74462 2001-03-19 12:50:13Z alfred $";
49#endif not lint
50
51#include <sys/param.h>
52#include <sys/syslog.h>
53#include <sys/wait.h>
54#include <sys/mount.h>
55
56#include <rpc/rpc.h>
57#include <rpc/pmap_clnt.h>
58
59#include <netdb.h>
60#include <arpa/inet.h>
49#endif not lint
50
51#include <sys/param.h>
52#include <sys/syslog.h>
53#include <sys/wait.h>
54#include <sys/mount.h>
55
56#include <rpc/rpc.h>
57#include <rpc/pmap_clnt.h>
58
59#include <netdb.h>
60#include <arpa/inet.h>
61#ifdef ISO
62#include <netiso/iso.h>
63#endif
64#include <nfs/rpcv2.h>
65#include <nfs/nfsproto.h>
66#include <nfs/nfs.h>
67
68#ifdef NFSKERB
69#include <kerberosIV/des.h>
70#include <kerberosIV/krb.h>
71#endif
72
73#include <err.h>
74#include <errno.h>
75#include <stdio.h>
76#include <stdlib.h>
77#include <strings.h>
78#include <unistd.h>
61#include <nfs/rpcv2.h>
62#include <nfs/nfsproto.h>
63#include <nfs/nfs.h>
64
65#ifdef NFSKERB
66#include <kerberosIV/des.h>
67#include <kerberosIV/krb.h>
68#endif
69
70#include <err.h>
71#include <errno.h>
72#include <stdio.h>
73#include <stdlib.h>
74#include <strings.h>
75#include <unistd.h>
76#include <netdb.h>
79
80/* Global defs */
81#ifdef DEBUG
82#define syslog(e, s) fprintf(stderr,(s))
83int debug = 1;
84#else
85int debug = 0;
86#endif
87
88struct nfsd_srvargs nsd;
89#ifdef OLD_SETPROCTITLE
90char **Argv = NULL; /* pointer to argument vector */
91char *LastArg = NULL; /* end of argv */
92#endif
93
94#ifdef NFSKERB
95char lnam[ANAME_SZ];
96KTEXT_ST kt;
97AUTH_DAT kauth;
98char inst[INST_SZ];
99struct nfsrpc_fullblock kin, kout;
100struct nfsrpc_fullverf kverf;
101NFSKERBKEY_T kivec;
102struct timeval ktv;
103NFSKERBKEYSCHED_T kerb_keysched;
104#endif
105
77
78/* Global defs */
79#ifdef DEBUG
80#define syslog(e, s) fprintf(stderr,(s))
81int debug = 1;
82#else
83int debug = 0;
84#endif
85
86struct nfsd_srvargs nsd;
87#ifdef OLD_SETPROCTITLE
88char **Argv = NULL; /* pointer to argument vector */
89char *LastArg = NULL; /* end of argv */
90#endif
91
92#ifdef NFSKERB
93char lnam[ANAME_SZ];
94KTEXT_ST kt;
95AUTH_DAT kauth;
96char inst[INST_SZ];
97struct nfsrpc_fullblock kin, kout;
98struct nfsrpc_fullverf kverf;
99NFSKERBKEY_T kivec;
100struct timeval ktv;
101NFSKERBKEYSCHED_T kerb_keysched;
102#endif
103
106void nonfs __P((int));
107void reapchild __P((int));
108void setbindhost __P((struct sockaddr_in *ia, const char *bindhost));
104#define MAXNFSDCNT 20
105#define DEFNFSDCNT 4
106pid_t children[MAXNFSDCNT]; /* PIDs of children */
107int nfsdcnt; /* number of children */
108
109void cleanup(int);
110void killchildren(void);
111void nonfs (int);
112void reapchild (int);
113int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints);
109#ifdef OLD_SETPROCTITLE
110#ifdef __FreeBSD__
114#ifdef OLD_SETPROCTITLE
115#ifdef __FreeBSD__
111void setproctitle __P((char *));
116void setproctitle (char *);
112#endif
113#endif
117#endif
118#endif
114void usage __P((void));
119void unregistration (void);
120void usage (void);
115
116/*
117 * Nfs server daemon mostly just a user context for nfssvc()
118 *
119 * 1 - do file descriptor and signal cleanup
120 * 2 - fork the nfsd(s)
121 * 3 - create server socket(s)
121
122/*
123 * Nfs server daemon mostly just a user context for nfssvc()
124 *
125 * 1 - do file descriptor and signal cleanup
126 * 2 - fork the nfsd(s)
127 * 3 - create server socket(s)
122 * 4 - register socket with portmap
128 * 4 - register socket with rpcbind
123 *
124 * For connectionless protocols, just pass the socket into the kernel via.
125 * nfssvc().
126 * For connection based sockets, loop doing accepts. When you get a new
127 * socket from accept, pass the msgsock into the kernel via. nfssvc().
128 * The arguments are:
129 * -c - support iso cltp clients
129 *
130 * For connectionless protocols, just pass the socket into the kernel via.
131 * nfssvc().
132 * For connection based sockets, loop doing accepts. When you get a new
133 * socket from accept, pass the msgsock into the kernel via. nfssvc().
134 * The arguments are:
135 * -c - support iso cltp clients
130 * -r - reregister with portmapper
136 * -r - reregister with rpcbind
137 * -d - unregister with rpcbind
131 * -t - support tcp nfs clients
132 * -u - support udp nfs clients
133 * followed by "n" which is the number of nfsds' to fork off
134 */
135int
136main(argc, argv, envp)
137 int argc;
138 char *argv[], *envp[];
139{
140 struct nfsd_args nfsdargs;
138 * -t - support tcp nfs clients
139 * -u - support udp nfs clients
140 * followed by "n" which is the number of nfsds' to fork off
141 */
142int
143main(argc, argv, envp)
144 int argc;
145 char *argv[], *envp[];
146{
147 struct nfsd_args nfsdargs;
141 struct sockaddr_in inetaddr, inetpeer;
142#ifdef ISO
143 struct sockaddr_iso isoaddr, isopeer;
144 char *cp;
145#endif
148 struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
149 struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
150 struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
151 struct sockaddr_in inetpeer;
152 struct sockaddr_in6 inet6peer;
146 fd_set ready, sockbits;
153 fd_set ready, sockbits;
154 fd_set v4bits, v6bits;
147 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
155 int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
148 int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
149 int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
150 int bindhostc = 0, bindanyflag;
156 int nfssvc_flag, on = 1, unregister, reregister, sock;
157 int tcp6sock, ip6flag, tcpflag, tcpsock;
158 int udpflag, ecode, s;
159 int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt;
151 char **bindhost = NULL;
160 char **bindhost = NULL;
152#ifdef notyet
153 int tp4sock, tpipsock;
154#endif
161 pid_t pid;
155#ifdef NFSKERB
156 struct group *grp;
157 struct passwd *pwd;
158 struct ucred *cr;
159 struct timeval ktv;
160 char **cpp;
161#endif
162#ifdef __FreeBSD__
163 struct vfsconf vfc;
164 int error;
165
166 error = getvfsbyname("nfs", &vfc);
167 if (error && vfsisloadable("nfs")) {
168 if (vfsload("nfs"))
169 err(1, "vfsload(nfs)");
170 endvfsent(); /* flush cache */
171 error = getvfsbyname("nfs", &vfc);
172 }
173 if (error)
174 errx(1, "NFS is not available in the running kernel");
175#endif
176
177#ifdef OLD_SETPROCTITLE
178 /* Save start and extent of argv for setproctitle. */
179 Argv = argv;
180 if (envp == 0 || *envp == 0)
181 envp = argv;
182 while (*envp)
183 envp++;
184 LastArg = envp[-1] + strlen(envp[-1]);
185#endif
186
162#ifdef NFSKERB
163 struct group *grp;
164 struct passwd *pwd;
165 struct ucred *cr;
166 struct timeval ktv;
167 char **cpp;
168#endif
169#ifdef __FreeBSD__
170 struct vfsconf vfc;
171 int error;
172
173 error = getvfsbyname("nfs", &vfc);
174 if (error && vfsisloadable("nfs")) {
175 if (vfsload("nfs"))
176 err(1, "vfsload(nfs)");
177 endvfsent(); /* flush cache */
178 error = getvfsbyname("nfs", &vfc);
179 }
180 if (error)
181 errx(1, "NFS is not available in the running kernel");
182#endif
183
184#ifdef OLD_SETPROCTITLE
185 /* Save start and extent of argv for setproctitle. */
186 Argv = argv;
187 if (envp == 0 || *envp == 0)
188 envp = argv;
189 while (*envp)
190 envp++;
191 LastArg = envp[-1] + strlen(envp[-1]);
192#endif
193
187#define MAXNFSDCNT 20
188#define DEFNFSDCNT 4
189 nfsdcnt = DEFNFSDCNT;
194 nfsdcnt = DEFNFSDCNT;
190 cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
191 bindanyflag = tpipflag = udpflag = 0;
192#ifdef ISO
193#define GETOPT "ach:n:rtu"
194#define USAGE "[-acrtu] [-n num_servers] [-h bindip]"
195#else
196#define GETOPT "ah:n:rtu"
197#define USAGE "[-artu] [-n num_servers] [-h bindip]"
198#endif
195 cltpflag = unregister = reregister = tcpflag = 0;
196 bindanyflag = udpflag = ip6flag = 0;
197#define GETOPT "ah:n:rdtu"
198#define USAGE "[-ardtu] [-n num_servers] [-h bindip]"
199 while ((ch = getopt(argc, argv, GETOPT)) != -1)
200 switch (ch) {
201 case 'a':
202 bindanyflag = 1;
203 break;
204 case 'n':
205 nfsdcnt = atoi(optarg);
206 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
207 warnx("nfsd count %d; reset to %d", nfsdcnt,
208 DEFNFSDCNT);
209 nfsdcnt = DEFNFSDCNT;
210 }
211 break;
212 case 'h':
213 bindhostc++;
214 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
215 if (bindhost == NULL)
216 errx(1, "Out of memory");
217 bindhost[bindhostc-1] = strdup(optarg);
218 if (bindhost[bindhostc-1] == NULL)
219 errx(1, "Out of memory");
220 break;
221 case 'r':
222 reregister = 1;
223 break;
199 while ((ch = getopt(argc, argv, GETOPT)) != -1)
200 switch (ch) {
201 case 'a':
202 bindanyflag = 1;
203 break;
204 case 'n':
205 nfsdcnt = atoi(optarg);
206 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
207 warnx("nfsd count %d; reset to %d", nfsdcnt,
208 DEFNFSDCNT);
209 nfsdcnt = DEFNFSDCNT;
210 }
211 break;
212 case 'h':
213 bindhostc++;
214 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
215 if (bindhost == NULL)
216 errx(1, "Out of memory");
217 bindhost[bindhostc-1] = strdup(optarg);
218 if (bindhost[bindhostc-1] == NULL)
219 errx(1, "Out of memory");
220 break;
221 case 'r':
222 reregister = 1;
223 break;
224 case 'd':
225 unregister = 1;
226 break;
224 case 't':
225 tcpflag = 1;
226 break;
227 case 'u':
228 udpflag = 1;
229 break;
227 case 't':
228 tcpflag = 1;
229 break;
230 case 'u':
231 udpflag = 1;
232 break;
230#ifdef ISO
231 case 'c':
232 cltpflag = 1;
233 break;
234#ifdef notyet
235 case 'i':
236 tp4cnt = 1;
237 break;
238 case 'p':
239 tpipcnt = 1;
240 break;
241#endif /* notyet */
242#endif /* ISO */
243 default:
244 case '?':
245 usage();
246 };
247 if (!tcpflag && !udpflag)
248 udpflag = 1;
249 argv += optind;
250 argc -= optind;
251
252 /*
253 * XXX
254 * Backward compatibility, trailing number is the count of daemons.
255 */
256 if (argc > 1)
257 usage();
258 if (argc == 1) {
259 nfsdcnt = atoi(argv[0]);
260 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
261 warnx("nfsd count %d; reset to %d", nfsdcnt,
262 DEFNFSDCNT);
263 nfsdcnt = DEFNFSDCNT;
264 }
265 }
233 default:
234 case '?':
235 usage();
236 };
237 if (!tcpflag && !udpflag)
238 udpflag = 1;
239 argv += optind;
240 argc -= optind;
241
242 /*
243 * XXX
244 * Backward compatibility, trailing number is the count of daemons.
245 */
246 if (argc > 1)
247 usage();
248 if (argc == 1) {
249 nfsdcnt = atoi(argv[0]);
250 if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
251 warnx("nfsd count %d; reset to %d", nfsdcnt,
252 DEFNFSDCNT);
253 nfsdcnt = DEFNFSDCNT;
254 }
255 }
256 ip6flag = 1;
257 s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
258 if (s < 0 && (errno == EPROTONOSUPPORT ||
259 errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
260 ip6flag = 0;
261 else
262 close(s);
266
267 if (bindhostc == 0 || bindanyflag) {
268 bindhostc++;
269 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
270 if (bindhost == NULL)
271 errx(1, "Out of memory");
272 bindhost[bindhostc-1] = strdup("*");
273 if (bindhost[bindhostc-1] == NULL)
274 errx(1, "Out of memory");
275 }
276
277 if (debug == 0) {
278 daemon(0, 0);
279 (void)signal(SIGHUP, SIG_IGN);
280 (void)signal(SIGINT, SIG_IGN);
263
264 if (bindhostc == 0 || bindanyflag) {
265 bindhostc++;
266 bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
267 if (bindhost == NULL)
268 errx(1, "Out of memory");
269 bindhost[bindhostc-1] = strdup("*");
270 if (bindhost[bindhostc-1] == NULL)
271 errx(1, "Out of memory");
272 }
273
274 if (debug == 0) {
275 daemon(0, 0);
276 (void)signal(SIGHUP, SIG_IGN);
277 (void)signal(SIGINT, SIG_IGN);
281 (void)signal(SIGQUIT, SIG_IGN);
282 (void)signal(SIGSYS, nonfs);
278 (void)signal(SIGSYS, nonfs);
279 (void)signal(SIGUSR1, cleanup);
280 /*
281 * nfsd sits in the kernel most of the time. It needs
282 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
283 * as possible during a shutdown, otherwise loopback
284 * mounts will not be able to unmount.
285 */
283 (void)signal(SIGTERM, SIG_IGN);
286 (void)signal(SIGTERM, SIG_IGN);
287 (void)signal(SIGQUIT, SIG_IGN);
284 }
285 (void)signal(SIGCHLD, reapchild);
288 }
289 (void)signal(SIGCHLD, reapchild);
286
290 if (unregister) {
291 unregistration();
292 exit (0);
293 }
287 if (reregister) {
294 if (reregister) {
288 if (udpflag &&
289 (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
290 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
291 err(1, "can't register with portmap for UDP");
292 if (tcpflag &&
293 (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
294 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
295 err(1, "can't register with portmap for TCP");
296 exit(0);
295 if (udpflag) {
296 memset(&hints, 0, sizeof hints);
297 hints.ai_flags = AI_PASSIVE;
298 hints.ai_family = AF_INET;
299 hints.ai_socktype = SOCK_DGRAM;
300 hints.ai_protocol = IPPROTO_UDP;
301 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
302 if (ecode != 0) {
303 syslog(LOG_ERR, "getaddrinfo udp: %s",
304 gai_strerror(ecode));
305 exit(1);
306 }
307 nconf_udp = getnetconfigent("udp");
308 if (nconf_udp == NULL)
309 err(1, "getnetconfigent udp failed");
310 nb_udp.buf = ai_udp->ai_addr;
311 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
312 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
313 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
314 err(1, "rpcb_set udp failed");
315 freeaddrinfo(ai_udp);
316 }
317 if (udpflag && ip6flag) {
318 memset(&hints, 0, sizeof hints);
319 hints.ai_flags = AI_PASSIVE;
320 hints.ai_family = AF_INET6;
321 hints.ai_socktype = SOCK_DGRAM;
322 hints.ai_protocol = IPPROTO_UDP;
323 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
324 if (ecode != 0) {
325 syslog(LOG_ERR, "getaddrinfo udp6: %s",
326 gai_strerror(ecode));
327 exit(1);
328 }
329 nconf_udp6 = getnetconfigent("udp6");
330 if (nconf_udp6 == NULL)
331 err(1, "getnetconfigent udp6 failed");
332 nb_udp6.buf = ai_udp6->ai_addr;
333 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
334 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
335 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
336 err(1, "rpcb_set udp6 failed");
337 freeaddrinfo(ai_udp6);
338 }
339 if (tcpflag) {
340 memset(&hints, 0, sizeof hints);
341 hints.ai_flags = AI_PASSIVE;
342 hints.ai_family = AF_INET;
343 hints.ai_socktype = SOCK_STREAM;
344 hints.ai_protocol = IPPROTO_TCP;
345 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
346 if (ecode != 0) {
347 syslog(LOG_ERR, "getaddrinfo tcp: %s",
348 gai_strerror(ecode));
349 exit(1);
350 }
351 nconf_tcp = getnetconfigent("tcp");
352 if (nconf_tcp == NULL)
353 err(1, "getnetconfigent tcp failed");
354 nb_tcp.buf = ai_tcp->ai_addr;
355 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
356 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
357 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
358 err(1, "rpcb_set tcp failed");
359 freeaddrinfo(ai_tcp);
360 }
361 if (tcpflag && ip6flag) {
362 memset(&hints, 0, sizeof hints);
363 hints.ai_flags = AI_PASSIVE;
364 hints.ai_family = AF_INET6;
365 hints.ai_socktype = SOCK_STREAM;
366 hints.ai_protocol = IPPROTO_TCP;
367 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
368 if (ecode != 0) {
369 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
370 gai_strerror(ecode));
371 exit(1);
372 }
373 nconf_tcp6 = getnetconfigent("tcp6");
374 if (nconf_tcp6 == NULL)
375 err(1, "getnetconfigent tcp6 failed");
376 nb_tcp6.buf = ai_tcp6->ai_addr;
377 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
378 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
379 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
380 err(1, "rpcb_set tcp6 failed");
381 freeaddrinfo(ai_tcp6);
382 }
383 exit (0);
297 }
384 }
385
298 openlog("nfsd:", LOG_PID, LOG_DAEMON);
299
300 for (i = 0; i < nfsdcnt; i++) {
386 openlog("nfsd:", LOG_PID, LOG_DAEMON);
387
388 for (i = 0; i < nfsdcnt; i++) {
301 switch (fork()) {
389 switch ((pid = fork())) {
302 case -1:
303 syslog(LOG_ERR, "fork: %m");
390 case -1:
391 syslog(LOG_ERR, "fork: %m");
392 killchildren();
304 exit (1);
305 case 0:
306 break;
307 default:
393 exit (1);
394 case 0:
395 break;
396 default:
397 children[i] = pid;
308 continue;
309 }
310
311 setproctitle("server");
312 nfssvc_flag = NFSSVC_NFSD;
313 nsd.nsd_nfsd = NULL;
314#ifdef NFSKERB
315 if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
316 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
317 syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
318 nsd.nsd_authstr = (u_char *)&kt;
319 nsd.nsd_authlen = sizeof (kt);
320 nsd.nsd_verfstr = (u_char *)&kverf;
321 nsd.nsd_verflen = sizeof (kverf);
322#endif
323 while (nfssvc(nfssvc_flag, &nsd) < 0) {
324 if (errno != ENEEDAUTH) {
325 syslog(LOG_ERR, "nfssvc: %m");
326 exit(1);
327 }
328 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
329#ifdef NFSKERB
330 /*
331 * Get the Kerberos ticket out of the authenticator
332 * verify it and convert the principal name to a user
333 * name. The user name is then converted to a set of
334 * user credentials via the password and group file.
335 * Finally, decrypt the timestamp and validate it.
336 * For more info see the IETF Draft "Authentication
337 * in ONC RPC".
338 */
339 kt.length = ntohl(kt.length);
340 if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
341 kt.length > 0 && kt.length <=
342 (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
343 kin.w1 = NFS_KERBW1(kt);
344 kt.mbz = 0;
345 (void)strcpy(inst, "*");
346 if (krb_rd_req(&kt, NFS_KERBSRV,
347 inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
348 krb_kntoln(&kauth, lnam) == KSUCCESS &&
349 (pwd = getpwnam(lnam)) != NULL) {
350 cr = &nsd.nsd_cr;
351 cr->cr_uid = pwd->pw_uid;
352 cr->cr_groups[0] = pwd->pw_gid;
353 cr->cr_ngroups = 1;
354 setgrent();
355 while ((grp = getgrent()) != NULL) {
356 if (grp->gr_gid == cr->cr_groups[0])
357 continue;
358 for (cpp = grp->gr_mem;
359 *cpp != NULL; ++cpp)
360 if (!strcmp(*cpp, lnam))
361 break;
362 if (*cpp == NULL)
363 continue;
364 cr->cr_groups[cr->cr_ngroups++]
365 = grp->gr_gid;
366 if (cr->cr_ngroups == NGROUPS)
367 break;
368 }
369 endgrent();
370
371 /*
372 * Get the timestamp verifier out of the
373 * authenticator and verifier strings.
374 */
375 kin.t1 = kverf.t1;
376 kin.t2 = kverf.t2;
377 kin.w2 = kverf.w2;
378 bzero((caddr_t)kivec, sizeof (kivec));
379 bcopy((caddr_t)kauth.session,
380 (caddr_t)nsd.nsd_key,sizeof(kauth.session));
381
382 /*
383 * Decrypt the timestamp verifier in CBC mode.
384 */
385 XXX
386
387 /*
388 * Validate the timestamp verifier, to
389 * check that the session key is ok.
390 */
391 nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
392 nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
393 nsd.nsd_ttl = ntohl(kout.w1);
394 if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
395 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
396 }
397#endif /* NFSKERB */
398 }
399 exit(0);
400 }
401
398 continue;
399 }
400
401 setproctitle("server");
402 nfssvc_flag = NFSSVC_NFSD;
403 nsd.nsd_nfsd = NULL;
404#ifdef NFSKERB
405 if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
406 sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
407 syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
408 nsd.nsd_authstr = (u_char *)&kt;
409 nsd.nsd_authlen = sizeof (kt);
410 nsd.nsd_verfstr = (u_char *)&kverf;
411 nsd.nsd_verflen = sizeof (kverf);
412#endif
413 while (nfssvc(nfssvc_flag, &nsd) < 0) {
414 if (errno != ENEEDAUTH) {
415 syslog(LOG_ERR, "nfssvc: %m");
416 exit(1);
417 }
418 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
419#ifdef NFSKERB
420 /*
421 * Get the Kerberos ticket out of the authenticator
422 * verify it and convert the principal name to a user
423 * name. The user name is then converted to a set of
424 * user credentials via the password and group file.
425 * Finally, decrypt the timestamp and validate it.
426 * For more info see the IETF Draft "Authentication
427 * in ONC RPC".
428 */
429 kt.length = ntohl(kt.length);
430 if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
431 kt.length > 0 && kt.length <=
432 (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
433 kin.w1 = NFS_KERBW1(kt);
434 kt.mbz = 0;
435 (void)strcpy(inst, "*");
436 if (krb_rd_req(&kt, NFS_KERBSRV,
437 inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
438 krb_kntoln(&kauth, lnam) == KSUCCESS &&
439 (pwd = getpwnam(lnam)) != NULL) {
440 cr = &nsd.nsd_cr;
441 cr->cr_uid = pwd->pw_uid;
442 cr->cr_groups[0] = pwd->pw_gid;
443 cr->cr_ngroups = 1;
444 setgrent();
445 while ((grp = getgrent()) != NULL) {
446 if (grp->gr_gid == cr->cr_groups[0])
447 continue;
448 for (cpp = grp->gr_mem;
449 *cpp != NULL; ++cpp)
450 if (!strcmp(*cpp, lnam))
451 break;
452 if (*cpp == NULL)
453 continue;
454 cr->cr_groups[cr->cr_ngroups++]
455 = grp->gr_gid;
456 if (cr->cr_ngroups == NGROUPS)
457 break;
458 }
459 endgrent();
460
461 /*
462 * Get the timestamp verifier out of the
463 * authenticator and verifier strings.
464 */
465 kin.t1 = kverf.t1;
466 kin.t2 = kverf.t2;
467 kin.w2 = kverf.w2;
468 bzero((caddr_t)kivec, sizeof (kivec));
469 bcopy((caddr_t)kauth.session,
470 (caddr_t)nsd.nsd_key,sizeof(kauth.session));
471
472 /*
473 * Decrypt the timestamp verifier in CBC mode.
474 */
475 XXX
476
477 /*
478 * Validate the timestamp verifier, to
479 * check that the session key is ok.
480 */
481 nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
482 nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
483 nsd.nsd_ttl = ntohl(kout.w1);
484 if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
485 nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
486 }
487#endif /* NFSKERB */
488 }
489 exit(0);
490 }
491
402 /* If we are serving udp, set up the socket. */
403 for (i = 0; udpflag && i < bindhostc; i++) {
404 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
405 syslog(LOG_ERR, "can't create udp socket");
406 exit(1);
492 if (atexit(killchildren) == -1) {
493 syslog(LOG_ERR, "atexit: %s", strerror(errno));
494 exit(1);
495 }
496 FD_ZERO(&v4bits);
497 FD_ZERO(&v6bits);
498
499 rpcbregcnt = 0;
500 /* Set up the socket for udp and rpcb register it. */
501 if (udpflag) {
502 rpcbreg = 0;
503 for (i = 0; i < bindhostc; i++) {
504 memset(&hints, 0, sizeof hints);
505 hints.ai_flags = AI_PASSIVE;
506 hints.ai_family = AF_INET;
507 hints.ai_socktype = SOCK_DGRAM;
508 hints.ai_protocol = IPPROTO_UDP;
509 if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
510 rpcbreg = 1;
511 rpcbregcnt++;
512 if ((sock = socket(ai_udp->ai_family,
513 ai_udp->ai_socktype,
514 ai_udp->ai_protocol)) < 0) {
515 syslog(LOG_ERR,
516 "can't create udp socket");
517 exit(1);
518 }
519 if (bind(sock, ai_udp->ai_addr,
520 ai_udp->ai_addrlen) < 0) {
521 syslog(LOG_ERR,
522 "can't bind udp addr %s: %m",
523 bindhost[i]);
524 exit(1);
525 }
526 freeaddrinfo(ai_udp);
527 nfsdargs.sock = sock;
528 nfsdargs.name = NULL;
529 nfsdargs.namelen = 0;
530 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
531 syslog(LOG_ERR, "can't Add UDP socket");
532 exit(1);
533 }
534 (void)close(sock);
535 }
407 }
536 }
408 setbindhost(&inetaddr, bindhost[i]);
409 if (bind(sock,
410 (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
411 syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]);
412 exit(1);
537 if (rpcbreg == 1) {
538 memset(&hints, 0, sizeof hints);
539 hints.ai_flags = AI_PASSIVE;
540 hints.ai_family = AF_INET;
541 hints.ai_socktype = SOCK_DGRAM;
542 hints.ai_protocol = IPPROTO_UDP;
543 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
544 if (ecode != 0) {
545 syslog(LOG_ERR, "getaddrinfo udp: %s",
546 gai_strerror(ecode));
547 exit(1);
548 }
549 nconf_udp = getnetconfigent("udp");
550 if (nconf_udp == NULL)
551 err(1, "getnetconfigent udp failed");
552 nb_udp.buf = ai_udp->ai_addr;
553 nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
554 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
555 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
556 err(1, "rpcb_set udp failed");
557 freeaddrinfo(ai_udp);
413 }
558 }
414 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
415 !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
416 syslog(LOG_ERR, "can't register with udp portmap");
417 exit(1);
418 }
419 nfsdargs.sock = sock;
420 nfsdargs.name = NULL;
421 nfsdargs.namelen = 0;
422 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
423 syslog(LOG_ERR, "can't Add UDP socket");
424 exit(1);
425 }
426 (void)close(sock);
427 }
428
559 }
560
429#ifdef ISO
430 /* If we are serving cltp, set up the socket. */
431 if (cltpflag) {
432 if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
433 syslog(LOG_ERR, "can't create cltp socket");
434 exit(1);
561 /* Set up the socket for udp6 and rpcb register it. */
562 if (udpflag && ip6flag) {
563 rpcbreg = 0;
564 for (i = 0; i < bindhostc; i++) {
565 memset(&hints, 0, sizeof hints);
566 hints.ai_flags = AI_PASSIVE;
567 hints.ai_family = AF_INET6;
568 hints.ai_socktype = SOCK_DGRAM;
569 hints.ai_protocol = IPPROTO_UDP;
570 if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
571 rpcbreg = 1;
572 rpcbregcnt++;
573 if ((sock = socket(ai_udp6->ai_family,
574 ai_udp6->ai_socktype,
575 ai_udp6->ai_protocol)) < 0) {
576 syslog(LOG_ERR,
577 "can't create udp6 socket");
578 exit(1);
579 }
580 if (setsockopt(sock, IPPROTO_IPV6,
581 IPV6_BINDV6ONLY,
582 &on, sizeof on) < 0) {
583 syslog(LOG_ERR,
584 "can't set v6-only binding for "
585 "udp6 socket: %m");
586 exit(1);
587 }
588 if (bind(sock, ai_udp6->ai_addr,
589 ai_udp6->ai_addrlen) < 0) {
590 syslog(LOG_ERR,
591 "can't bind udp6 addr %s: %m",
592 bindhost[i]);
593 exit(1);
594 }
595 freeaddrinfo(ai_udp6);
596 nfsdargs.sock = sock;
597 nfsdargs.name = NULL;
598 nfsdargs.namelen = 0;
599 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
600 syslog(LOG_ERR,
601 "can't add UDP6 socket");
602 exit(1);
603 }
604 (void)close(sock);
605 }
435 }
606 }
436 memset(&isoaddr, 0, sizeof(isoaddr));
437 isoaddr.siso_family = AF_ISO;
438 isoaddr.siso_tlen = 2;
439 cp = TSEL(&isoaddr);
440 *cp++ = (NFS_PORT >> 8);
441 *cp = (NFS_PORT & 0xff);
442 isoaddr.siso_len = sizeof(isoaddr);
443 if (bind(sock,
444 (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
445 syslog(LOG_ERR, "can't bind cltp addr");
446 exit(1);
607 if (rpcbreg == 1) {
608 memset(&hints, 0, sizeof hints);
609 hints.ai_flags = AI_PASSIVE;
610 hints.ai_family = AF_INET6;
611 hints.ai_socktype = SOCK_DGRAM;
612 hints.ai_protocol = IPPROTO_UDP;
613 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
614 if (ecode != 0) {
615 syslog(LOG_ERR, "getaddrinfo udp6: %s",
616 gai_strerror(ecode));
617 exit(1);
618 }
619 nconf_udp6 = getnetconfigent("udp6");
620 if (nconf_udp6 == NULL)
621 err(1, "getnetconfigent udp6 failed");
622 nb_udp6.buf = ai_udp6->ai_addr;
623 nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
624 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
625 (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
626 err(1, "rpcb_set udp6 failed");
627 freeaddrinfo(ai_udp6);
447 }
628 }
448#ifdef notyet
449 /*
450 * XXX
451 * Someday this should probably use "rpcbind", the son of
452 * portmap.
453 */
454 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
455 syslog(LOG_ERR, "can't register with udp portmap");
456 exit(1);
457 }
458#endif /* notyet */
459 nfsdargs.sock = sock;
460 nfsdargs.name = NULL;
461 nfsdargs.namelen = 0;
462 if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
463 syslog(LOG_ERR, "can't add UDP socket");
464 exit(1);
465 }
466 close(sock);
467 }
629 }
468#endif /* ISO */
469
630
470 /* Now set up the master server socket waiting for tcp connections. */
471 on = 1;
472 FD_ZERO(&sockbits);
473 connect_type_cnt = 0;
474 for (i = 0; tcpflag && i < bindhostc; i++) {
475 if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
476 syslog(LOG_ERR, "can't create tcp socket");
477 exit(1);
631 /* Set up the socket for tcp and rpcb register it. */
632 if (tcpflag) {
633 rpcbreg = 0;
634 for (i = 0; i < bindhostc; i++) {
635 memset(&hints, 0, sizeof hints);
636 hints.ai_flags = AI_PASSIVE;
637 hints.ai_family = AF_INET;
638 hints.ai_socktype = SOCK_STREAM;
639 hints.ai_protocol = IPPROTO_TCP;
640 if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
641 rpcbreg = 1;
642 rpcbregcnt++;
643 if ((tcpsock = socket(AF_INET, SOCK_STREAM,
644 0)) < 0) {
645 syslog(LOG_ERR,
646 "can't create tpc socket");
647 exit(1);
648 }
649 if (setsockopt(tcpsock, SOL_SOCKET,
650 SO_REUSEADDR,
651 (char *)&on, sizeof(on)) < 0)
652 syslog(LOG_ERR,
653 "setsockopt SO_REUSEADDR: %m");
654 if (bind(tcpsock, ai_tcp->ai_addr,
655 ai_tcp->ai_addrlen) < 0) {
656 syslog(LOG_ERR,
657 "can't bind tcp addr %s: %m",
658 bindhost[i]);
659 exit(1);
660 }
661 if (listen(tcpsock, 5) < 0) {
662 syslog(LOG_ERR, "listen failed");
663 exit(1);
664 }
665 freeaddrinfo(ai_tcp);
666 FD_SET(tcpsock, &sockbits);
667 FD_SET(tcpsock, &v4bits);
668 maxsock = tcpsock;
669 connect_type_cnt++;
670 }
478 }
671 }
479 if (setsockopt(tcpsock,
480 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
481 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
482 setbindhost(&inetaddr, bindhost[i]);
483 if (bind(tcpsock,
484 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
485 syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
486 exit(1);
672 if (rpcbreg == 1) {
673 memset(&hints, 0, sizeof hints);
674 hints.ai_flags = AI_PASSIVE;
675 hints.ai_family = AF_INET;
676 hints.ai_socktype = SOCK_STREAM;
677 hints.ai_protocol = IPPROTO_TCP;
678 ecode = getaddrinfo(NULL, "nfs", &hints,
679 &ai_tcp);
680 if (ecode != 0) {
681 syslog(LOG_ERR, "getaddrinfo tcp: %s",
682 gai_strerror(ecode));
683 exit(1);
684 }
685 nconf_tcp = getnetconfigent("tcp");
686 if (nconf_tcp == NULL)
687 err(1, "getnetconfigent tcp failed");
688 nb_tcp.buf = ai_tcp->ai_addr;
689 nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
690 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
691 &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
692 nconf_tcp, &nb_tcp)))
693 err(1, "rpcb_set tcp failed");
694 freeaddrinfo(ai_tcp);
487 }
695 }
488 if (listen(tcpsock, 5) < 0) {
489 syslog(LOG_ERR, "listen failed");
490 exit(1);
491 }
492 if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
493 !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
494 syslog(LOG_ERR, "can't register tcp with portmap");
495 exit(1);
496 }
497 FD_SET(tcpsock, &sockbits);
498 maxsock = tcpsock;
499 connect_type_cnt++;
500 }
501
696 }
697
502#ifdef notyet
503 /* Now set up the master server socket waiting for tp4 connections. */
504 if (tp4flag) {
505 if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
506 syslog(LOG_ERR, "can't create tp4 socket");
507 exit(1);
698 /* Set up the socket for tcp6 and rpcb register it. */
699 if (tcpflag && ip6flag) {
700 rpcbreg = 0;
701 for (i = 0; i < bindhostc; i++) {
702 memset(&hints, 0, sizeof hints);
703 hints.ai_flags = AI_PASSIVE;
704 hints.ai_family = AF_INET6;
705 hints.ai_socktype = SOCK_STREAM;
706 hints.ai_protocol = IPPROTO_TCP;
707 if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
708 rpcbreg = 1;
709 rpcbregcnt++;
710 if ((tcp6sock = socket(ai_tcp6->ai_family,
711 ai_tcp6->ai_socktype,
712 ai_tcp6->ai_protocol)) < 0) {
713 syslog(LOG_ERR,
714 "can't create tcp6 socket");
715 exit(1);
716 }
717 if (setsockopt(tcp6sock, SOL_SOCKET,
718 SO_REUSEADDR,
719 (char *)&on, sizeof(on)) < 0)
720 syslog(LOG_ERR,
721 "setsockopt SO_REUSEADDR: %m");
722 if (setsockopt(tcp6sock, IPPROTO_IPV6,
723 IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
724 syslog(LOG_ERR,
725 "can't set v6-only binding for tcp6 "
726 "socket: %m");
727 exit(1);
728 }
729 if (bind(tcp6sock, ai_tcp6->ai_addr,
730 ai_tcp6->ai_addrlen) < 0) {
731 syslog(LOG_ERR,
732 "can't bind tcp6 addr %s: %m",
733 bindhost[i]);
734 exit(1);
735 }
736 if (listen(tcp6sock, 5) < 0) {
737 syslog(LOG_ERR, "listen failed");
738 exit(1);
739 }
740 freeaddrinfo(ai_tcp6);
741 FD_SET(tcp6sock, &sockbits);
742 FD_SET(tcp6sock, &v6bits);
743 if (maxsock < tcp6sock)
744 maxsock = tcp6sock;
745 connect_type_cnt++;
746 }
508 }
747 }
509 if (setsockopt(tp4sock,
510 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
511 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
512 memset(&isoaddr, 0, sizeof(isoaddr));
513 isoaddr.siso_family = AF_ISO;
514 isoaddr.siso_tlen = 2;
515 cp = TSEL(&isoaddr);
516 *cp++ = (NFS_PORT >> 8);
517 *cp = (NFS_PORT & 0xff);
518 isoaddr.siso_len = sizeof(isoaddr);
519 if (bind(tp4sock,
520 (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
521 syslog(LOG_ERR, "can't bind tp4 addr");
522 exit(1);
748 if (rpcbreg == 1) {
749 memset(&hints, 0, sizeof hints);
750 hints.ai_flags = AI_PASSIVE;
751 hints.ai_family = AF_INET6;
752 hints.ai_socktype = SOCK_STREAM;
753 hints.ai_protocol = IPPROTO_TCP;
754 ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
755 if (ecode != 0) {
756 syslog(LOG_ERR, "getaddrinfo tcp6: %s",
757 gai_strerror(ecode));
758 exit(1);
759 }
760 nconf_tcp6 = getnetconfigent("tcp6");
761 if (nconf_tcp6 == NULL)
762 err(1, "getnetconfigent tcp6 failed");
763 nb_tcp6.buf = ai_tcp6->ai_addr;
764 nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
765 if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
766 (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
767 err(1, "rpcb_set tcp6 failed");
768 freeaddrinfo(ai_tcp6);
523 }
769 }
524 if (listen(tp4sock, 5) < 0) {
525 syslog(LOG_ERR, "listen failed");
526 exit(1);
527 }
528 /*
529 * XXX
530 * Someday this should probably use "rpcbind", the son of
531 * portmap.
532 */
533 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
534 syslog(LOG_ERR, "can't register tcp with portmap");
535 exit(1);
536 }
537 FD_SET(tp4sock, &sockbits);
538 maxsock = tp4sock;
539 connect_type_cnt++;
540 }
541
770 }
771
542 /* Now set up the master server socket waiting for tpip connections. */
543 for (i = 0; tpipflag && i < bindhostc; i++) {
544 if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
545 syslog(LOG_ERR, "can't create tpip socket");
546 exit(1);
547 }
548 if (setsockopt(tpipsock,
549 SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
550 syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
551 setbindhost(&inetaddr, bindhost[i]);
552 if (bind(tpipsock,
553 (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
554 syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
555 exit(1);
556 }
557 if (listen(tpipsock, 5) < 0) {
558 syslog(LOG_ERR, "listen failed");
559 exit(1);
560 }
561 /*
562 * XXX
563 * Someday this should probably use "rpcbind", the son of
564 * portmap.
565 */
566 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
567 syslog(LOG_ERR, "can't register tcp with portmap");
568 exit(1);
569 }
570 FD_SET(tpipsock, &sockbits);
571 maxsock = tpipsock;
572 connect_type_cnt++;
772 if (rpcbregcnt == 0) {
773 syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
774 exit(1);
573 }
775 }
574#endif /* notyet */
575
776
576 if (connect_type_cnt == 0)
577 exit(0);
777 if ((tcpflag) && (connect_type_cnt == 0)) {
778 syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
779 exit(1);
780 }
578
579 setproctitle("master");
580
581 /*
582 * Loop forever accepting connections and passing the sockets
583 * into the kernel for the mounts.
584 */
585 for (;;) {
586 ready = sockbits;
587 if (connect_type_cnt > 1) {
588 if (select(maxsock + 1,
589 &ready, NULL, NULL, NULL) < 1) {
590 syslog(LOG_ERR, "select failed: %m");
591 exit(1);
592 }
593 }
781
782 setproctitle("master");
783
784 /*
785 * Loop forever accepting connections and passing the sockets
786 * into the kernel for the mounts.
787 */
788 for (;;) {
789 ready = sockbits;
790 if (connect_type_cnt > 1) {
791 if (select(maxsock + 1,
792 &ready, NULL, NULL, NULL) < 1) {
793 syslog(LOG_ERR, "select failed: %m");
794 exit(1);
795 }
796 }
594 if (tcpflag && FD_ISSET(tcpsock, &ready)) {
595 len = sizeof(inetpeer);
596 if ((msgsock = accept(tcpsock,
597 (struct sockaddr *)&inetpeer, &len)) < 0) {
598 syslog(LOG_ERR, "accept failed: %m");
599 exit(1);
797 for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
798 if (FD_ISSET(tcpsock, &ready)) {
799 if (FD_ISSET(tcpsock, &v4bits)) {
800 len = sizeof(inetpeer);
801 if ((msgsock = accept(tcpsock,
802 (struct sockaddr *)&inetpeer, &len)) < 0) {
803 syslog(LOG_ERR, "accept failed: %m");
804 exit(1);
805 }
806 memset(inetpeer.sin_zero, 0,
807 sizeof(inetpeer.sin_zero));
808 if (setsockopt(msgsock, SOL_SOCKET,
809 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
810 syslog(LOG_ERR,
811 "setsockopt SO_KEEPALIVE: %m");
812 nfsdargs.sock = msgsock;
813 nfsdargs.name = (caddr_t)&inetpeer;
814 nfsdargs.namelen = sizeof(inetpeer);
815 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
816 (void)close(msgsock);
817 } else if (FD_ISSET(tcpsock, &v6bits)) {
818 len = sizeof(inet6peer);
819 if ((msgsock = accept(tcpsock,
820 (struct sockaddr *)&inet6peer,
821 &len)) < 0) {
822 syslog(LOG_ERR,
823 "accept failed: %m");
824 exit(1);
825 }
826 if (setsockopt(msgsock, SOL_SOCKET,
827 SO_KEEPALIVE, (char *)&on,
828 sizeof(on)) < 0)
829 syslog(LOG_ERR, "setsockopt "
830 "SO_KEEPALIVE: %m");
831 nfsdargs.sock = msgsock;
832 nfsdargs.name = (caddr_t)&inet6peer;
833 nfsdargs.namelen = sizeof(inet6peer);
834 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
835 (void)close(msgsock);
836 }
600 }
837 }
601 memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
602 if (setsockopt(msgsock, SOL_SOCKET,
603 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
604 syslog(LOG_ERR,
605 "setsockopt SO_KEEPALIVE: %m");
606 nfsdargs.sock = msgsock;
607 nfsdargs.name = (caddr_t)&inetpeer;
608 nfsdargs.namelen = sizeof(inetpeer);
609 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
610 (void)close(msgsock);
611 }
838 }
612#ifdef notyet
613 if (tp4flag && FD_ISSET(tp4sock, &ready)) {
614 len = sizeof(isopeer);
615 if ((msgsock = accept(tp4sock,
616 (struct sockaddr *)&isopeer, &len)) < 0) {
617 syslog(LOG_ERR, "accept failed: %m");
618 exit(1);
619 }
620 if (setsockopt(msgsock, SOL_SOCKET,
621 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
622 syslog(LOG_ERR,
623 "setsockopt SO_KEEPALIVE: %m");
624 nfsdargs.sock = msgsock;
625 nfsdargs.name = (caddr_t)&isopeer;
626 nfsdargs.namelen = len;
627 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
628 (void)close(msgsock);
629 }
630 if (tpipflag && FD_ISSET(tpipsock, &ready)) {
631 len = sizeof(inetpeer);
632 if ((msgsock = accept(tpipsock,
633 (struct sockaddr *)&inetpeer, &len)) < 0) {
634 syslog(LOG_ERR, "accept failed: %m");
635 exit(1);
636 }
637 if (setsockopt(msgsock, SOL_SOCKET,
638 SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
639 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
640 nfsdargs.sock = msgsock;
641 nfsdargs.name = (caddr_t)&inetpeer;
642 nfsdargs.namelen = len;
643 nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
644 (void)close(msgsock);
645 }
646#endif /* notyet */
647 }
648}
649
839 }
840}
841
650void
651setbindhost(struct sockaddr_in *ia, const char *bindhost)
842int
843setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
652{
844{
653 ia->sin_family = AF_INET;
654 ia->sin_port = htons(NFS_PORT);
655 ia->sin_len = sizeof(*ia);
656 if (bindhost == NULL || strcmp(bindhost,"*") == 0) {
657 ia->sin_addr.s_addr = INADDR_ANY;
658 } else {
659 if (inet_aton(bindhost, &ia->sin_addr) == 0) {
660 struct hostent *he;
845 int ecode;
846 u_int32_t host_addr[4]; /* IPv4 or IPv6 */
847 const char *hostptr;
661
848
662 he = gethostbyname2(bindhost, ia->sin_family);
663 if (he == NULL) {
664 syslog(LOG_ERR, "gethostbyname of %s failed", bindhost);
665 exit(1);
849 if (bindhost == NULL || strcmp("*", bindhost) == 0)
850 hostptr = NULL;
851 else
852 hostptr = bindhost;
853
854 if (hostptr != NULL) {
855 switch (hints.ai_family) {
856 case AF_INET:
857 if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
858 hints.ai_flags = AI_NUMERICHOST;
859 } else {
860 if (inet_pton(AF_INET6, hostptr,
861 host_addr) == 1)
862 return (1);
666 }
863 }
667 bcopy(he->h_addr, &ia->sin_addr, he->h_length);
864 break;
865 case AF_INET6:
866 if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
867 hints.ai_flags = AI_NUMERICHOST;
868 } else {
869 if (inet_pton(AF_INET, hostptr,
870 host_addr) == 1)
871 return (1);
872 }
873 break;
874 default:
668 }
669 }
875 }
876 }
877
878 ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
879 if (ecode != 0) {
880 syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
881 gai_strerror(ecode));
882 return (1);
883 }
884 return (0);
670}
671
672void
673usage()
674{
675 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
676 exit(1);
677}
678
679void
680nonfs(signo)
681 int signo;
682{
683 syslog(LOG_ERR, "missing system call: NFS not available");
684}
685
686void
687reapchild(signo)
688 int signo;
689{
690
691 while (wait3(NULL, WNOHANG, NULL) > 0);
692}
693
885}
886
887void
888usage()
889{
890 (void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
891 exit(1);
892}
893
894void
895nonfs(signo)
896 int signo;
897{
898 syslog(LOG_ERR, "missing system call: NFS not available");
899}
900
901void
902reapchild(signo)
903 int signo;
904{
905
906 while (wait3(NULL, WNOHANG, NULL) > 0);
907}
908
909void
910unregistration()
911{
912 if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
913 (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
914 syslog(LOG_ERR, "rpcb_unset failed");
915}
916
917void
918killchildren()
919{
920 int i;
921 sigset_t sigs;
922
923 sigemptyset(&sigs);
924 /*
925 * Block SIGCHLD to avoid killing a reaped process (although it is
926 * unlikely, the pid might have been reused).
927 */
928 sigaddset(&sigs, SIGCHLD);
929 if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) {
930 syslog(LOG_ERR, "sigprocmask: %s",
931 strerror(errno));
932 return;
933 }
934 for (i = 0; i < nfsdcnt; i++) {
935 if (children[i] > 0)
936 kill(children[i], SIGKILL);
937 }
938 if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) {
939 syslog(LOG_ERR, "sigprocmask: %s", strerror(errno));
940 }
941 unregistration();
942}
943
944void
945cleanup(signo)
946{
947 killchildren();
948 exit (0);
949}
950
694#ifdef OLD_SETPROCTITLE
695#ifdef __FreeBSD__
696void
697setproctitle(a)
698 char *a;
699{
700 register char *cp;
701 char buf[80];
702
703 cp = Argv[0];
704 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
705 (void)strncpy(cp, buf, LastArg - cp);
706 cp += strlen(cp);
707 while (cp < LastArg)
708 *cp++ = '\0';
709 Argv[1] = NULL;
710}
711#endif /* __FreeBSD__ */
712#endif
951#ifdef OLD_SETPROCTITLE
952#ifdef __FreeBSD__
953void
954setproctitle(a)
955 char *a;
956{
957 register char *cp;
958 char buf[80];
959
960 cp = Argv[0];
961 (void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
962 (void)strncpy(cp, buf, LastArg - cp);
963 cp += strlen(cp);
964 while (cp < LastArg)
965 *cp++ = '\0';
966 Argv[1] = NULL;
967}
968#endif /* __FreeBSD__ */
969#endif