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