nfsd.c revision 9336
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1989, 1993, 1994 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * This code is derived from software contributed to Berkeley by 61558Srgrimes * Rick Macklem at The University of Guelph. 71558Srgrimes * 81558Srgrimes * Redistribution and use in source and binary forms, with or without 91558Srgrimes * modification, are permitted provided that the following conditions 101558Srgrimes * are met: 111558Srgrimes * 1. Redistributions of source code must retain the above copyright 121558Srgrimes * notice, this list of conditions and the following disclaimer. 131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141558Srgrimes * notice, this list of conditions and the following disclaimer in the 151558Srgrimes * documentation and/or other materials provided with the distribution. 161558Srgrimes * 3. All advertising materials mentioning features or use of this software 171558Srgrimes * must display the following acknowledgement: 181558Srgrimes * This product includes software developed by the University of 191558Srgrimes * California, Berkeley and its contributors. 201558Srgrimes * 4. Neither the name of the University nor the names of its contributors 211558Srgrimes * may be used to endorse or promote products derived from this software 221558Srgrimes * without specific prior written permission. 231558Srgrimes * 241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341558Srgrimes * SUCH DAMAGE. 351558Srgrimes */ 361558Srgrimes 371558Srgrimes#ifndef lint 381558Srgrimesstatic char copyright[] = 391558Srgrimes"@(#) Copyright (c) 1989, 1993, 1994\n\ 401558Srgrimes The Regents of the University of California. All rights reserved.\n"; 411558Srgrimes#endif not lint 421558Srgrimes 431558Srgrimes#ifndef lint 441558Srgrimesstatic char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94"; 451558Srgrimes#endif not lint 461558Srgrimes 471558Srgrimes#include <sys/param.h> 481558Srgrimes#include <sys/syslog.h> 491558Srgrimes#include <sys/ioctl.h> 501558Srgrimes#include <sys/stat.h> 511558Srgrimes#include <sys/wait.h> 521558Srgrimes#include <sys/uio.h> 531558Srgrimes#include <sys/ucred.h> 541558Srgrimes#include <sys/mount.h> 551558Srgrimes#include <sys/socket.h> 561558Srgrimes#include <sys/socketvar.h> 571558Srgrimes 581558Srgrimes#include <rpc/rpc.h> 591558Srgrimes#include <rpc/pmap_clnt.h> 601558Srgrimes#include <rpc/pmap_prot.h> 611558Srgrimes 621558Srgrimes#ifdef ISO 631558Srgrimes#include <netiso/iso.h> 641558Srgrimes#endif 651558Srgrimes#include <nfs/rpcv2.h> 669336Sdfr#include <nfs/nfsproto.h> 671558Srgrimes#include <nfs/nfs.h> 681558Srgrimes 699336Sdfr#ifdef NFSKERB 701558Srgrimes#include <kerberosIV/des.h> 711558Srgrimes#include <kerberosIV/krb.h> 721558Srgrimes#endif 731558Srgrimes 741558Srgrimes#include <err.h> 751558Srgrimes#include <errno.h> 761558Srgrimes#include <fcntl.h> 771558Srgrimes#include <grp.h> 781558Srgrimes#include <pwd.h> 791558Srgrimes#include <signal.h> 801558Srgrimes#include <stdio.h> 811558Srgrimes#include <stdlib.h> 821558Srgrimes#include <strings.h> 831558Srgrimes#include <unistd.h> 841558Srgrimes 851558Srgrimes/* Global defs */ 861558Srgrimes#ifdef DEBUG 871558Srgrimes#define syslog(e, s) fprintf(stderr,(s)) 881558Srgrimesint debug = 1; 891558Srgrimes#else 901558Srgrimesint debug = 0; 911558Srgrimes#endif 921558Srgrimes 931558Srgrimesstruct nfsd_srvargs nsd; 941558Srgrimeschar **Argv = NULL; /* pointer to argument vector */ 951558Srgrimeschar *LastArg = NULL; /* end of argv */ 961558Srgrimes 979336Sdfr#ifdef NFSKERB 981558Srgrimeschar lnam[ANAME_SZ]; 991558SrgrimesKTEXT_ST kt; 1009336SdfrAUTH_DAT kauth; 1011558Srgrimeschar inst[INST_SZ]; 1029336Sdfrstruct nfsrpc_fullblock kin, kout; 1039336Sdfrstruct nfsrpc_fullverf kverf; 1049336SdfrNFSKERBKEY_T kivec; 1059336Sdfrstruct timeval ktv; 1069336SdfrNFSKERBKEYSCHED_T kerb_keysched; 1071558Srgrimes#endif 1081558Srgrimes 1091558Srgrimesvoid nonfs __P((int)); 1101558Srgrimesvoid reapchild __P((int)); 1119336Sdfr#ifdef __FreeBSD__ 1121558Srgrimesvoid setproctitle __P((char *)); 1139336Sdfr#endif 1141558Srgrimesvoid usage __P((void)); 1151558Srgrimes 1161558Srgrimes/* 1171558Srgrimes * Nfs server daemon mostly just a user context for nfssvc() 1181558Srgrimes * 1191558Srgrimes * 1 - do file descriptor and signal cleanup 1201558Srgrimes * 2 - fork the nfsd(s) 1211558Srgrimes * 3 - create server socket(s) 1221558Srgrimes * 4 - register socket with portmap 1231558Srgrimes * 1241558Srgrimes * For connectionless protocols, just pass the socket into the kernel via. 1251558Srgrimes * nfssvc(). 1261558Srgrimes * For connection based sockets, loop doing accepts. When you get a new 1271558Srgrimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1281558Srgrimes * The arguments are: 1291558Srgrimes * -c - support iso cltp clients 1301558Srgrimes * -r - reregister with portmapper 1311558Srgrimes * -t - support tcp nfs clients 1321558Srgrimes * -u - support udp nfs clients 1331558Srgrimes * followed by "n" which is the number of nfsds' to fork off 1341558Srgrimes */ 1351558Srgrimesint 1361558Srgrimesmain(argc, argv, envp) 1371558Srgrimes int argc; 1381558Srgrimes char *argv[], *envp[]; 1391558Srgrimes{ 1401558Srgrimes extern int optind; 1411558Srgrimes struct group *grp; 1421558Srgrimes struct nfsd_args nfsdargs; 1431558Srgrimes struct passwd *pwd; 1441558Srgrimes struct ucred *cr; 1451558Srgrimes struct sockaddr_in inetaddr, inetpeer; 1461558Srgrimes#ifdef ISO 1471558Srgrimes struct sockaddr_iso isoaddr, isopeer; 1481558Srgrimes#endif 1499336Sdfr struct timeval ktv; 1501558Srgrimes fd_set ready, sockbits; 1511558Srgrimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 1521558Srgrimes int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 1531558Srgrimes int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; 1541558Srgrimes char *cp, **cpp; 1559336Sdfr#ifdef __FreeBSD__ 1562999Swollman struct vfsconf *vfc; 1571558Srgrimes 1582999Swollman vfc = getvfsbyname("nfs"); 1592999Swollman if(!vfc && vfsisloadable("nfs")) { 1602999Swollman if(vfsload("nfs")) 1612999Swollman err(1, "vfsload(nfs)"); 1622999Swollman endvfsent(); /* flush cache */ 1632999Swollman vfc = getvfsbyname("nfs"); /* probably unnecessary */ 1642999Swollman } 1652999Swollman if(!vfc) { 1662999Swollman errx(1, "NFS is not available in the running kernel"); 1672999Swollman } 1689336Sdfr#endif 1692999Swollman 1701558Srgrimes /* Save start and extent of argv for setproctitle. */ 1711558Srgrimes Argv = argv; 1721558Srgrimes if (envp == 0 || *envp == 0) 1731558Srgrimes envp = argv; 1741558Srgrimes while (*envp) 1751558Srgrimes envp++; 1761558Srgrimes LastArg = envp[-1] + strlen(envp[-1]); 1771558Srgrimes 1781558Srgrimes#define MAXNFSDCNT 20 1791558Srgrimes#define DEFNFSDCNT 4 1801558Srgrimes nfsdcnt = DEFNFSDCNT; 1811558Srgrimes cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 1821558Srgrimes tpipflag = udpflag = 0; 1831558Srgrimes#ifdef ISO 1841558Srgrimes#define GETOPT "cn:rtu" 1851558Srgrimes#define USAGE "[-crtu] [-n num_servers]" 1861558Srgrimes#else 1871558Srgrimes#define GETOPT "n:rtu" 1881558Srgrimes#define USAGE "[-rtu] [-n num_servers]" 1891558Srgrimes#endif 1901558Srgrimes while ((ch = getopt(argc, argv, GETOPT)) != EOF) 1911558Srgrimes switch (ch) { 1921558Srgrimes case 'n': 1931558Srgrimes nfsdcnt = atoi(optarg); 1941558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 1951558Srgrimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 1961558Srgrimes nfsdcnt = DEFNFSDCNT; 1971558Srgrimes } 1981558Srgrimes break; 1991558Srgrimes case 'r': 2001558Srgrimes reregister = 1; 2011558Srgrimes break; 2021558Srgrimes case 't': 2031558Srgrimes tcpflag = 1; 2041558Srgrimes break; 2051558Srgrimes case 'u': 2061558Srgrimes udpflag = 1; 2071558Srgrimes break; 2081558Srgrimes#ifdef ISO 2091558Srgrimes case 'c': 2101558Srgrimes cltpflag = 1; 2111558Srgrimes break; 2121558Srgrimes#ifdef notyet 2131558Srgrimes case 'i': 2141558Srgrimes tp4cnt = 1; 2151558Srgrimes break; 2161558Srgrimes case 'p': 2171558Srgrimes tpipcnt = 1; 2181558Srgrimes break; 2191558Srgrimes#endif /* notyet */ 2201558Srgrimes#endif /* ISO */ 2211558Srgrimes default: 2221558Srgrimes case '?': 2231558Srgrimes usage(); 2241558Srgrimes }; 2251558Srgrimes argv += optind; 2261558Srgrimes argc -= optind; 2271558Srgrimes 2281558Srgrimes /* 2291558Srgrimes * XXX 2301558Srgrimes * Backward compatibility, trailing number is the count of daemons. 2311558Srgrimes */ 2321558Srgrimes if (argc > 1) 2331558Srgrimes usage(); 2341558Srgrimes if (argc == 1) { 2351558Srgrimes nfsdcnt = atoi(argv[0]); 2361558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2371558Srgrimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 2381558Srgrimes nfsdcnt = DEFNFSDCNT; 2391558Srgrimes } 2401558Srgrimes } 2411558Srgrimes 2421558Srgrimes if (debug == 0) { 2431558Srgrimes daemon(0, 0); 2441558Srgrimes (void)signal(SIGHUP, SIG_IGN); 2451558Srgrimes (void)signal(SIGINT, SIG_IGN); 2461558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 2471558Srgrimes (void)signal(SIGSYS, nonfs); 2481558Srgrimes (void)signal(SIGTERM, SIG_IGN); 2491558Srgrimes } 2501558Srgrimes (void)signal(SIGCHLD, reapchild); 2511558Srgrimes 2521558Srgrimes if (reregister) { 2531558Srgrimes if (udpflag && 2549336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 2559336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) 2561558Srgrimes err(1, "can't register with portmap for UDP."); 2571558Srgrimes if (tcpflag && 2589336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 2599336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) 2601558Srgrimes err(1, "can't register with portmap for TCP."); 2611558Srgrimes exit(0); 2621558Srgrimes } 2631558Srgrimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 2641558Srgrimes 2651558Srgrimes for (i = 0; i < nfsdcnt; i++) { 2661558Srgrimes switch (fork()) { 2671558Srgrimes case -1: 2681558Srgrimes syslog(LOG_ERR, "fork: %m"); 2691558Srgrimes exit (1); 2701558Srgrimes case 0: 2711558Srgrimes break; 2721558Srgrimes default: 2731558Srgrimes continue; 2741558Srgrimes } 2751558Srgrimes 2769336Sdfr setproctitle("server"); 2771558Srgrimes nfssvc_flag = NFSSVC_NFSD; 2781558Srgrimes nsd.nsd_nfsd = NULL; 2799336Sdfr#ifdef NFSKERB 2809336Sdfr if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 2819336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 2829336Sdfr syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 2839336Sdfr nsd.nsd_authstr = (u_char *)&kt; 2849336Sdfr nsd.nsd_authlen = sizeof (kt); 2859336Sdfr nsd.nsd_verfstr = (u_char *)&kverf; 2869336Sdfr nsd.nsd_verflen = sizeof (kverf); 2871558Srgrimes#endif 2881558Srgrimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 2891558Srgrimes if (errno != ENEEDAUTH) { 2901558Srgrimes syslog(LOG_ERR, "nfssvc: %m"); 2911558Srgrimes exit(1); 2921558Srgrimes } 2931558Srgrimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 2949336Sdfr#ifdef NFSKERB 2959336Sdfr /* 2969336Sdfr * Get the Kerberos ticket out of the authenticator 2979336Sdfr * verify it and convert the principal name to a user 2989336Sdfr * name. The user name is then converted to a set of 2999336Sdfr * user credentials via the password and group file. 3009336Sdfr * Finally, decrypt the timestamp and validate it. 3019336Sdfr * For more info see the IETF Draft "Authentication 3029336Sdfr * in ONC RPC". 3039336Sdfr */ 3049336Sdfr kt.length = ntohl(kt.length); 3059336Sdfr if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 3069336Sdfr kt.length > 0 && kt.length <= 3079336Sdfr (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 3089336Sdfr kin.w1 = NFS_KERBW1(kt); 3099336Sdfr kt.mbz = 0; 3109336Sdfr (void)strcpy(inst, "*"); 3119336Sdfr if (krb_rd_req(&kt, NFS_KERBSRV, 3129336Sdfr inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 3139336Sdfr krb_kntoln(&kauth, lnam) == KSUCCESS && 3149336Sdfr (pwd = getpwnam(lnam)) != NULL) { 3151558Srgrimes cr = &nsd.nsd_cr; 3161558Srgrimes cr->cr_uid = pwd->pw_uid; 3171558Srgrimes cr->cr_groups[0] = pwd->pw_gid; 3181558Srgrimes cr->cr_ngroups = 1; 3191558Srgrimes setgrent(); 3201558Srgrimes while ((grp = getgrent()) != NULL) { 3211558Srgrimes if (grp->gr_gid == cr->cr_groups[0]) 3221558Srgrimes continue; 3231558Srgrimes for (cpp = grp->gr_mem; 3241558Srgrimes *cpp != NULL; ++cpp) 3251558Srgrimes if (!strcmp(*cpp, lnam)) 3261558Srgrimes break; 3271558Srgrimes if (*cpp == NULL) 3281558Srgrimes continue; 3291558Srgrimes cr->cr_groups[cr->cr_ngroups++] 3301558Srgrimes = grp->gr_gid; 3311558Srgrimes if (cr->cr_ngroups == NGROUPS) 3321558Srgrimes break; 3331558Srgrimes } 3341558Srgrimes endgrent(); 3359336Sdfr 3369336Sdfr /* 3379336Sdfr * Get the timestamp verifier out of the 3389336Sdfr * authenticator and verifier strings. 3399336Sdfr */ 3409336Sdfr kin.t1 = kverf.t1; 3419336Sdfr kin.t2 = kverf.t2; 3429336Sdfr kin.w2 = kverf.w2; 3439336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 3449336Sdfr bcopy((caddr_t)kauth.session, 3459336Sdfr (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 3469336Sdfr 3479336Sdfr /* 3489336Sdfr * Decrypt the timestamp verifier in CBC mode. 3499336Sdfr */ 3509336Sdfr XXX 3519336Sdfr 3529336Sdfr /* 3539336Sdfr * Validate the timestamp verifier, to 3549336Sdfr * check that the session key is ok. 3559336Sdfr */ 3569336Sdfr nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 3579336Sdfr nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 3589336Sdfr nsd.nsd_ttl = ntohl(kout.w1); 3599336Sdfr if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 3609336Sdfr nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 3611558Srgrimes } 3629336Sdfr#endif /* NFSKERB */ 3631558Srgrimes } 3641558Srgrimes exit(0); 3651558Srgrimes } 3661558Srgrimes 3671558Srgrimes /* If we are serving udp, set up the socket. */ 3681558Srgrimes if (udpflag) { 3691558Srgrimes if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 3701558Srgrimes syslog(LOG_ERR, "can't create udp socket"); 3711558Srgrimes exit(1); 3721558Srgrimes } 3731558Srgrimes inetaddr.sin_family = AF_INET; 3741558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3751558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 3761558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 3771558Srgrimes if (bind(sock, 3781558Srgrimes (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 3791558Srgrimes syslog(LOG_ERR, "can't bind udp addr"); 3801558Srgrimes exit(1); 3811558Srgrimes } 3829336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 3839336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { 3841558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 3851558Srgrimes exit(1); 3861558Srgrimes } 3871558Srgrimes nfsdargs.sock = sock; 3881558Srgrimes nfsdargs.name = NULL; 3891558Srgrimes nfsdargs.namelen = 0; 3901558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 3911558Srgrimes syslog(LOG_ERR, "can't Add UDP socket"); 3921558Srgrimes exit(1); 3931558Srgrimes } 3941558Srgrimes (void)close(sock); 3951558Srgrimes } 3961558Srgrimes 3971558Srgrimes#ifdef ISO 3981558Srgrimes /* If we are serving cltp, set up the socket. */ 3991558Srgrimes if (cltpflag) { 4001558Srgrimes if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 4011558Srgrimes syslog(LOG_ERR, "can't create cltp socket"); 4021558Srgrimes exit(1); 4031558Srgrimes } 4041558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4051558Srgrimes isoaddr.siso_family = AF_ISO; 4061558Srgrimes isoaddr.siso_tlen = 2; 4071558Srgrimes cp = TSEL(&isoaddr); 4081558Srgrimes *cp++ = (NFS_PORT >> 8); 4091558Srgrimes *cp = (NFS_PORT & 0xff); 4101558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 4111558Srgrimes if (bind(sock, 4121558Srgrimes (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 4131558Srgrimes syslog(LOG_ERR, "can't bind cltp addr"); 4141558Srgrimes exit(1); 4151558Srgrimes } 4161558Srgrimes#ifdef notyet 4171558Srgrimes /* 4181558Srgrimes * XXX 4191558Srgrimes * Someday this should probably use "rpcbind", the son of 4201558Srgrimes * portmap. 4211558Srgrimes */ 4221558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 4231558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 4241558Srgrimes exit(1); 4251558Srgrimes } 4261558Srgrimes#endif /* notyet */ 4271558Srgrimes nfsdargs.sock = sock; 4281558Srgrimes nfsdargs.name = NULL; 4291558Srgrimes nfsdargs.namelen = 0; 4301558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 4311558Srgrimes syslog(LOG_ERR, "can't add UDP socket"); 4321558Srgrimes exit(1); 4331558Srgrimes } 4341558Srgrimes close(sock); 4351558Srgrimes } 4361558Srgrimes#endif /* ISO */ 4371558Srgrimes 4381558Srgrimes /* Now set up the master server socket waiting for tcp connections. */ 4391558Srgrimes on = 1; 4401558Srgrimes FD_ZERO(&sockbits); 4411558Srgrimes connect_type_cnt = 0; 4421558Srgrimes if (tcpflag) { 4431558Srgrimes if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 4441558Srgrimes syslog(LOG_ERR, "can't create tcp socket"); 4451558Srgrimes exit(1); 4461558Srgrimes } 4471558Srgrimes if (setsockopt(tcpsock, 4481558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4491558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4501558Srgrimes inetaddr.sin_family = AF_INET; 4511558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 4521558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 4531558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 4541558Srgrimes if (bind(tcpsock, 4551558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 4561558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 4571558Srgrimes exit(1); 4581558Srgrimes } 4591558Srgrimes if (listen(tcpsock, 5) < 0) { 4601558Srgrimes syslog(LOG_ERR, "listen failed"); 4611558Srgrimes exit(1); 4621558Srgrimes } 4639336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 4649336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { 4651558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 4661558Srgrimes exit(1); 4671558Srgrimes } 4681558Srgrimes FD_SET(tcpsock, &sockbits); 4691558Srgrimes maxsock = tcpsock; 4701558Srgrimes connect_type_cnt++; 4711558Srgrimes } 4721558Srgrimes 4731558Srgrimes#ifdef notyet 4741558Srgrimes /* Now set up the master server socket waiting for tp4 connections. */ 4751558Srgrimes if (tp4flag) { 4761558Srgrimes if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 4771558Srgrimes syslog(LOG_ERR, "can't create tp4 socket"); 4781558Srgrimes exit(1); 4791558Srgrimes } 4801558Srgrimes if (setsockopt(tp4sock, 4811558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4821558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4831558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4841558Srgrimes isoaddr.siso_family = AF_ISO; 4851558Srgrimes isoaddr.siso_tlen = 2; 4861558Srgrimes cp = TSEL(&isoaddr); 4871558Srgrimes *cp++ = (NFS_PORT >> 8); 4881558Srgrimes *cp = (NFS_PORT & 0xff); 4891558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 4901558Srgrimes if (bind(tp4sock, 4911558Srgrimes (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 4921558Srgrimes syslog(LOG_ERR, "can't bind tp4 addr"); 4931558Srgrimes exit(1); 4941558Srgrimes } 4951558Srgrimes if (listen(tp4sock, 5) < 0) { 4961558Srgrimes syslog(LOG_ERR, "listen failed"); 4971558Srgrimes exit(1); 4981558Srgrimes } 4991558Srgrimes /* 5001558Srgrimes * XXX 5011558Srgrimes * Someday this should probably use "rpcbind", the son of 5021558Srgrimes * portmap. 5031558Srgrimes */ 5041558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5051558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5061558Srgrimes exit(1); 5071558Srgrimes } 5081558Srgrimes FD_SET(tp4sock, &sockbits); 5091558Srgrimes maxsock = tp4sock; 5101558Srgrimes connect_type_cnt++; 5111558Srgrimes } 5121558Srgrimes 5131558Srgrimes /* Now set up the master server socket waiting for tpip connections. */ 5141558Srgrimes if (tpipflag) { 5151558Srgrimes if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 5161558Srgrimes syslog(LOG_ERR, "can't create tpip socket"); 5171558Srgrimes exit(1); 5181558Srgrimes } 5191558Srgrimes if (setsockopt(tpipsock, 5201558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 5211558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 5221558Srgrimes inetaddr.sin_family = AF_INET; 5231558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 5241558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 5251558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 5261558Srgrimes if (bind(tpipsock, 5271558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 5281558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 5291558Srgrimes exit(1); 5301558Srgrimes } 5311558Srgrimes if (listen(tpipsock, 5) < 0) { 5321558Srgrimes syslog(LOG_ERR, "listen failed"); 5331558Srgrimes exit(1); 5341558Srgrimes } 5351558Srgrimes /* 5361558Srgrimes * XXX 5371558Srgrimes * Someday this should probably use "rpcbind", the son of 5381558Srgrimes * portmap. 5391558Srgrimes */ 5401558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5411558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5421558Srgrimes exit(1); 5431558Srgrimes } 5441558Srgrimes FD_SET(tpipsock, &sockbits); 5451558Srgrimes maxsock = tpipsock; 5461558Srgrimes connect_type_cnt++; 5471558Srgrimes } 5481558Srgrimes#endif /* notyet */ 5491558Srgrimes 5501558Srgrimes if (connect_type_cnt == 0) 5511558Srgrimes exit(0); 5521558Srgrimes 5539336Sdfr setproctitle("master"); 5541558Srgrimes 5551558Srgrimes /* 5561558Srgrimes * Loop forever accepting connections and passing the sockets 5571558Srgrimes * into the kernel for the mounts. 5581558Srgrimes */ 5591558Srgrimes for (;;) { 5601558Srgrimes ready = sockbits; 5611558Srgrimes if (connect_type_cnt > 1) { 5621558Srgrimes if (select(maxsock + 1, 5631558Srgrimes &ready, NULL, NULL, NULL) < 1) { 5641558Srgrimes syslog(LOG_ERR, "select failed: %m"); 5651558Srgrimes exit(1); 5661558Srgrimes } 5671558Srgrimes } 5681558Srgrimes if (tcpflag && FD_ISSET(tcpsock, &ready)) { 5691558Srgrimes len = sizeof(inetpeer); 5701558Srgrimes if ((msgsock = accept(tcpsock, 5711558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5721558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 5731558Srgrimes exit(1); 5741558Srgrimes } 5751558Srgrimes memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 5761558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 5771558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5781558Srgrimes syslog(LOG_ERR, 5791558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 5801558Srgrimes nfsdargs.sock = msgsock; 5811558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 5821558Srgrimes nfsdargs.namelen = sizeof(inetpeer); 5831558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5841558Srgrimes (void)close(msgsock); 5851558Srgrimes } 5861558Srgrimes#ifdef notyet 5871558Srgrimes if (tp4flag && FD_ISSET(tp4sock, &ready)) { 5881558Srgrimes len = sizeof(isopeer); 5891558Srgrimes if ((msgsock = accept(tp4sock, 5901558Srgrimes (struct sockaddr *)&isopeer, &len)) < 0) { 5911558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 5921558Srgrimes exit(1); 5931558Srgrimes } 5941558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 5951558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5961558Srgrimes syslog(LOG_ERR, 5971558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 5981558Srgrimes nfsdargs.sock = msgsock; 5991558Srgrimes nfsdargs.name = (caddr_t)&isopeer; 6001558Srgrimes nfsdargs.namelen = len; 6011558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6021558Srgrimes (void)close(msgsock); 6031558Srgrimes } 6041558Srgrimes if (tpipflag && FD_ISSET(tpipsock, &ready)) { 6051558Srgrimes len = sizeof(inetpeer); 6061558Srgrimes if ((msgsock = accept(tpipsock, 6071558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 6081558Srgrimes syslog(LOG_ERR, "Accept failed: %m"); 6091558Srgrimes exit(1); 6101558Srgrimes } 6111558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 6121558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6131558Srgrimes syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 6141558Srgrimes nfsdargs.sock = msgsock; 6151558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 6161558Srgrimes nfsdargs.namelen = len; 6171558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6181558Srgrimes (void)close(msgsock); 6191558Srgrimes } 6201558Srgrimes#endif /* notyet */ 6211558Srgrimes } 6221558Srgrimes} 6231558Srgrimes 6241558Srgrimesvoid 6251558Srgrimesusage() 6261558Srgrimes{ 6279336Sdfr (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 6281558Srgrimes exit(1); 6291558Srgrimes} 6301558Srgrimes 6311558Srgrimesvoid 6321558Srgrimesnonfs(signo) 6331558Srgrimes int signo; 6341558Srgrimes{ 6351558Srgrimes syslog(LOG_ERR, "missing system call: NFS not available."); 6361558Srgrimes} 6371558Srgrimes 6381558Srgrimesvoid 6391558Srgrimesreapchild(signo) 6401558Srgrimes int signo; 6411558Srgrimes{ 6421558Srgrimes 6439336Sdfr while (wait3(NULL, WNOHANG, NULL) > 0); 6441558Srgrimes} 6451558Srgrimes 6469336Sdfr#ifdef __FreeBSD__ 6471558Srgrimesvoid 6481558Srgrimessetproctitle(a) 6491558Srgrimes char *a; 6501558Srgrimes{ 6511558Srgrimes register char *cp; 6521558Srgrimes char buf[80]; 6531558Srgrimes 6541558Srgrimes cp = Argv[0]; 6559336Sdfr (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 6561558Srgrimes (void)strncpy(cp, buf, LastArg - cp); 6571558Srgrimes cp += strlen(cp); 6581558Srgrimes while (cp < LastArg) 6592030Sdg *cp++ = '\0'; 6601558Srgrimes} 6619336Sdfr#endif /* __FreeBSD__ */ 662