nfsd.c revision 13141
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> 8413141Speter#include <libutil.h> 851558Srgrimes 861558Srgrimes/* Global defs */ 871558Srgrimes#ifdef DEBUG 881558Srgrimes#define syslog(e, s) fprintf(stderr,(s)) 891558Srgrimesint debug = 1; 901558Srgrimes#else 911558Srgrimesint debug = 0; 921558Srgrimes#endif 931558Srgrimes 941558Srgrimesstruct nfsd_srvargs nsd; 9513141Speter#ifdef OLD_SETPROCTITLE 961558Srgrimeschar **Argv = NULL; /* pointer to argument vector */ 971558Srgrimeschar *LastArg = NULL; /* end of argv */ 9813141Speter#endif 991558Srgrimes 1009336Sdfr#ifdef NFSKERB 1011558Srgrimeschar lnam[ANAME_SZ]; 1021558SrgrimesKTEXT_ST kt; 1039336SdfrAUTH_DAT kauth; 1041558Srgrimeschar inst[INST_SZ]; 1059336Sdfrstruct nfsrpc_fullblock kin, kout; 1069336Sdfrstruct nfsrpc_fullverf kverf; 1079336SdfrNFSKERBKEY_T kivec; 1089336Sdfrstruct timeval ktv; 1099336SdfrNFSKERBKEYSCHED_T kerb_keysched; 1101558Srgrimes#endif 1111558Srgrimes 1121558Srgrimesvoid nonfs __P((int)); 1131558Srgrimesvoid reapchild __P((int)); 11413141Speter#ifdef OLD_SETPROCTITLE 1159336Sdfr#ifdef __FreeBSD__ 1161558Srgrimesvoid setproctitle __P((char *)); 1179336Sdfr#endif 11813141Speter#endif 1191558Srgrimesvoid usage __P((void)); 1201558Srgrimes 1211558Srgrimes/* 1221558Srgrimes * Nfs server daemon mostly just a user context for nfssvc() 1231558Srgrimes * 1241558Srgrimes * 1 - do file descriptor and signal cleanup 1251558Srgrimes * 2 - fork the nfsd(s) 1261558Srgrimes * 3 - create server socket(s) 1271558Srgrimes * 4 - register socket with portmap 1281558Srgrimes * 1291558Srgrimes * For connectionless protocols, just pass the socket into the kernel via. 1301558Srgrimes * nfssvc(). 1311558Srgrimes * For connection based sockets, loop doing accepts. When you get a new 1321558Srgrimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1331558Srgrimes * The arguments are: 1341558Srgrimes * -c - support iso cltp clients 1351558Srgrimes * -r - reregister with portmapper 1361558Srgrimes * -t - support tcp nfs clients 1371558Srgrimes * -u - support udp nfs clients 1381558Srgrimes * followed by "n" which is the number of nfsds' to fork off 1391558Srgrimes */ 1401558Srgrimesint 1411558Srgrimesmain(argc, argv, envp) 1421558Srgrimes int argc; 1431558Srgrimes char *argv[], *envp[]; 1441558Srgrimes{ 1451558Srgrimes extern int optind; 1461558Srgrimes struct group *grp; 1471558Srgrimes struct nfsd_args nfsdargs; 1481558Srgrimes struct passwd *pwd; 1491558Srgrimes struct ucred *cr; 1501558Srgrimes struct sockaddr_in inetaddr, inetpeer; 1511558Srgrimes#ifdef ISO 1521558Srgrimes struct sockaddr_iso isoaddr, isopeer; 1531558Srgrimes#endif 1549336Sdfr struct timeval ktv; 1551558Srgrimes fd_set ready, sockbits; 1561558Srgrimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 1571558Srgrimes int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 1581558Srgrimes int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; 1591558Srgrimes char *cp, **cpp; 1609336Sdfr#ifdef __FreeBSD__ 1612999Swollman struct vfsconf *vfc; 1621558Srgrimes 1632999Swollman vfc = getvfsbyname("nfs"); 1642999Swollman if(!vfc && vfsisloadable("nfs")) { 1652999Swollman if(vfsload("nfs")) 1662999Swollman err(1, "vfsload(nfs)"); 1672999Swollman endvfsent(); /* flush cache */ 1682999Swollman vfc = getvfsbyname("nfs"); /* probably unnecessary */ 1692999Swollman } 1702999Swollman if(!vfc) { 1712999Swollman errx(1, "NFS is not available in the running kernel"); 1722999Swollman } 1739336Sdfr#endif 1742999Swollman 17513141Speter#ifdef OLD_SETPROCTITLE 1761558Srgrimes /* Save start and extent of argv for setproctitle. */ 1771558Srgrimes Argv = argv; 1781558Srgrimes if (envp == 0 || *envp == 0) 1791558Srgrimes envp = argv; 1801558Srgrimes while (*envp) 1811558Srgrimes envp++; 1821558Srgrimes LastArg = envp[-1] + strlen(envp[-1]); 18313141Speter#endif 1841558Srgrimes 1851558Srgrimes#define MAXNFSDCNT 20 1861558Srgrimes#define DEFNFSDCNT 4 1871558Srgrimes nfsdcnt = DEFNFSDCNT; 1881558Srgrimes cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 1891558Srgrimes tpipflag = udpflag = 0; 1901558Srgrimes#ifdef ISO 1911558Srgrimes#define GETOPT "cn:rtu" 1921558Srgrimes#define USAGE "[-crtu] [-n num_servers]" 1931558Srgrimes#else 1941558Srgrimes#define GETOPT "n:rtu" 1951558Srgrimes#define USAGE "[-rtu] [-n num_servers]" 1961558Srgrimes#endif 1971558Srgrimes while ((ch = getopt(argc, argv, GETOPT)) != EOF) 1981558Srgrimes switch (ch) { 1991558Srgrimes case 'n': 2001558Srgrimes nfsdcnt = atoi(optarg); 2011558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2021558Srgrimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 2031558Srgrimes nfsdcnt = DEFNFSDCNT; 2041558Srgrimes } 2051558Srgrimes break; 2061558Srgrimes case 'r': 2071558Srgrimes reregister = 1; 2081558Srgrimes break; 2091558Srgrimes case 't': 2101558Srgrimes tcpflag = 1; 2111558Srgrimes break; 2121558Srgrimes case 'u': 2131558Srgrimes udpflag = 1; 2141558Srgrimes break; 2151558Srgrimes#ifdef ISO 2161558Srgrimes case 'c': 2171558Srgrimes cltpflag = 1; 2181558Srgrimes break; 2191558Srgrimes#ifdef notyet 2201558Srgrimes case 'i': 2211558Srgrimes tp4cnt = 1; 2221558Srgrimes break; 2231558Srgrimes case 'p': 2241558Srgrimes tpipcnt = 1; 2251558Srgrimes break; 2261558Srgrimes#endif /* notyet */ 2271558Srgrimes#endif /* ISO */ 2281558Srgrimes default: 2291558Srgrimes case '?': 2301558Srgrimes usage(); 2311558Srgrimes }; 2321558Srgrimes argv += optind; 2331558Srgrimes argc -= optind; 2341558Srgrimes 2351558Srgrimes /* 2361558Srgrimes * XXX 2371558Srgrimes * Backward compatibility, trailing number is the count of daemons. 2381558Srgrimes */ 2391558Srgrimes if (argc > 1) 2401558Srgrimes usage(); 2411558Srgrimes if (argc == 1) { 2421558Srgrimes nfsdcnt = atoi(argv[0]); 2431558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2441558Srgrimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 2451558Srgrimes nfsdcnt = DEFNFSDCNT; 2461558Srgrimes } 2471558Srgrimes } 2481558Srgrimes 2491558Srgrimes if (debug == 0) { 2501558Srgrimes daemon(0, 0); 2511558Srgrimes (void)signal(SIGHUP, SIG_IGN); 2521558Srgrimes (void)signal(SIGINT, SIG_IGN); 2531558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 2541558Srgrimes (void)signal(SIGSYS, nonfs); 2551558Srgrimes (void)signal(SIGTERM, SIG_IGN); 2561558Srgrimes } 2571558Srgrimes (void)signal(SIGCHLD, reapchild); 2581558Srgrimes 2591558Srgrimes if (reregister) { 2601558Srgrimes if (udpflag && 2619336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 2629336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) 2631558Srgrimes err(1, "can't register with portmap for UDP."); 2641558Srgrimes if (tcpflag && 2659336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 2669336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) 2671558Srgrimes err(1, "can't register with portmap for TCP."); 2681558Srgrimes exit(0); 2691558Srgrimes } 2701558Srgrimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 2711558Srgrimes 2721558Srgrimes for (i = 0; i < nfsdcnt; i++) { 2731558Srgrimes switch (fork()) { 2741558Srgrimes case -1: 2751558Srgrimes syslog(LOG_ERR, "fork: %m"); 2761558Srgrimes exit (1); 2771558Srgrimes case 0: 2781558Srgrimes break; 2791558Srgrimes default: 2801558Srgrimes continue; 2811558Srgrimes } 2821558Srgrimes 2839336Sdfr setproctitle("server"); 2841558Srgrimes nfssvc_flag = NFSSVC_NFSD; 2851558Srgrimes nsd.nsd_nfsd = NULL; 2869336Sdfr#ifdef NFSKERB 2879336Sdfr if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 2889336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 2899336Sdfr syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 2909336Sdfr nsd.nsd_authstr = (u_char *)&kt; 2919336Sdfr nsd.nsd_authlen = sizeof (kt); 2929336Sdfr nsd.nsd_verfstr = (u_char *)&kverf; 2939336Sdfr nsd.nsd_verflen = sizeof (kverf); 2941558Srgrimes#endif 2951558Srgrimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 2961558Srgrimes if (errno != ENEEDAUTH) { 2971558Srgrimes syslog(LOG_ERR, "nfssvc: %m"); 2981558Srgrimes exit(1); 2991558Srgrimes } 3001558Srgrimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 3019336Sdfr#ifdef NFSKERB 3029336Sdfr /* 3039336Sdfr * Get the Kerberos ticket out of the authenticator 3049336Sdfr * verify it and convert the principal name to a user 3059336Sdfr * name. The user name is then converted to a set of 3069336Sdfr * user credentials via the password and group file. 3079336Sdfr * Finally, decrypt the timestamp and validate it. 3089336Sdfr * For more info see the IETF Draft "Authentication 3099336Sdfr * in ONC RPC". 3109336Sdfr */ 3119336Sdfr kt.length = ntohl(kt.length); 3129336Sdfr if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 3139336Sdfr kt.length > 0 && kt.length <= 3149336Sdfr (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 3159336Sdfr kin.w1 = NFS_KERBW1(kt); 3169336Sdfr kt.mbz = 0; 3179336Sdfr (void)strcpy(inst, "*"); 3189336Sdfr if (krb_rd_req(&kt, NFS_KERBSRV, 3199336Sdfr inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 3209336Sdfr krb_kntoln(&kauth, lnam) == KSUCCESS && 3219336Sdfr (pwd = getpwnam(lnam)) != NULL) { 3221558Srgrimes cr = &nsd.nsd_cr; 3231558Srgrimes cr->cr_uid = pwd->pw_uid; 3241558Srgrimes cr->cr_groups[0] = pwd->pw_gid; 3251558Srgrimes cr->cr_ngroups = 1; 3261558Srgrimes setgrent(); 3271558Srgrimes while ((grp = getgrent()) != NULL) { 3281558Srgrimes if (grp->gr_gid == cr->cr_groups[0]) 3291558Srgrimes continue; 3301558Srgrimes for (cpp = grp->gr_mem; 3311558Srgrimes *cpp != NULL; ++cpp) 3321558Srgrimes if (!strcmp(*cpp, lnam)) 3331558Srgrimes break; 3341558Srgrimes if (*cpp == NULL) 3351558Srgrimes continue; 3361558Srgrimes cr->cr_groups[cr->cr_ngroups++] 3371558Srgrimes = grp->gr_gid; 3381558Srgrimes if (cr->cr_ngroups == NGROUPS) 3391558Srgrimes break; 3401558Srgrimes } 3411558Srgrimes endgrent(); 3429336Sdfr 3439336Sdfr /* 3449336Sdfr * Get the timestamp verifier out of the 3459336Sdfr * authenticator and verifier strings. 3469336Sdfr */ 3479336Sdfr kin.t1 = kverf.t1; 3489336Sdfr kin.t2 = kverf.t2; 3499336Sdfr kin.w2 = kverf.w2; 3509336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 3519336Sdfr bcopy((caddr_t)kauth.session, 3529336Sdfr (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 3539336Sdfr 3549336Sdfr /* 3559336Sdfr * Decrypt the timestamp verifier in CBC mode. 3569336Sdfr */ 3579336Sdfr XXX 3589336Sdfr 3599336Sdfr /* 3609336Sdfr * Validate the timestamp verifier, to 3619336Sdfr * check that the session key is ok. 3629336Sdfr */ 3639336Sdfr nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 3649336Sdfr nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 3659336Sdfr nsd.nsd_ttl = ntohl(kout.w1); 3669336Sdfr if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 3679336Sdfr nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 3681558Srgrimes } 3699336Sdfr#endif /* NFSKERB */ 3701558Srgrimes } 3711558Srgrimes exit(0); 3721558Srgrimes } 3731558Srgrimes 3741558Srgrimes /* If we are serving udp, set up the socket. */ 3751558Srgrimes if (udpflag) { 3761558Srgrimes if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 3771558Srgrimes syslog(LOG_ERR, "can't create udp socket"); 3781558Srgrimes exit(1); 3791558Srgrimes } 3801558Srgrimes inetaddr.sin_family = AF_INET; 3811558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3821558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 3831558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 3841558Srgrimes if (bind(sock, 3851558Srgrimes (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 3861558Srgrimes syslog(LOG_ERR, "can't bind udp addr"); 3871558Srgrimes exit(1); 3881558Srgrimes } 3899336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 3909336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { 3911558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 3921558Srgrimes exit(1); 3931558Srgrimes } 3941558Srgrimes nfsdargs.sock = sock; 3951558Srgrimes nfsdargs.name = NULL; 3961558Srgrimes nfsdargs.namelen = 0; 3971558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 3981558Srgrimes syslog(LOG_ERR, "can't Add UDP socket"); 3991558Srgrimes exit(1); 4001558Srgrimes } 4011558Srgrimes (void)close(sock); 4021558Srgrimes } 4031558Srgrimes 4041558Srgrimes#ifdef ISO 4051558Srgrimes /* If we are serving cltp, set up the socket. */ 4061558Srgrimes if (cltpflag) { 4071558Srgrimes if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 4081558Srgrimes syslog(LOG_ERR, "can't create cltp socket"); 4091558Srgrimes exit(1); 4101558Srgrimes } 4111558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4121558Srgrimes isoaddr.siso_family = AF_ISO; 4131558Srgrimes isoaddr.siso_tlen = 2; 4141558Srgrimes cp = TSEL(&isoaddr); 4151558Srgrimes *cp++ = (NFS_PORT >> 8); 4161558Srgrimes *cp = (NFS_PORT & 0xff); 4171558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 4181558Srgrimes if (bind(sock, 4191558Srgrimes (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 4201558Srgrimes syslog(LOG_ERR, "can't bind cltp addr"); 4211558Srgrimes exit(1); 4221558Srgrimes } 4231558Srgrimes#ifdef notyet 4241558Srgrimes /* 4251558Srgrimes * XXX 4261558Srgrimes * Someday this should probably use "rpcbind", the son of 4271558Srgrimes * portmap. 4281558Srgrimes */ 4291558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 4301558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 4311558Srgrimes exit(1); 4321558Srgrimes } 4331558Srgrimes#endif /* notyet */ 4341558Srgrimes nfsdargs.sock = sock; 4351558Srgrimes nfsdargs.name = NULL; 4361558Srgrimes nfsdargs.namelen = 0; 4371558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 4381558Srgrimes syslog(LOG_ERR, "can't add UDP socket"); 4391558Srgrimes exit(1); 4401558Srgrimes } 4411558Srgrimes close(sock); 4421558Srgrimes } 4431558Srgrimes#endif /* ISO */ 4441558Srgrimes 4451558Srgrimes /* Now set up the master server socket waiting for tcp connections. */ 4461558Srgrimes on = 1; 4471558Srgrimes FD_ZERO(&sockbits); 4481558Srgrimes connect_type_cnt = 0; 4491558Srgrimes if (tcpflag) { 4501558Srgrimes if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 4511558Srgrimes syslog(LOG_ERR, "can't create tcp socket"); 4521558Srgrimes exit(1); 4531558Srgrimes } 4541558Srgrimes if (setsockopt(tcpsock, 4551558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4561558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4571558Srgrimes inetaddr.sin_family = AF_INET; 4581558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 4591558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 4601558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 4611558Srgrimes if (bind(tcpsock, 4621558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 4631558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 4641558Srgrimes exit(1); 4651558Srgrimes } 4661558Srgrimes if (listen(tcpsock, 5) < 0) { 4671558Srgrimes syslog(LOG_ERR, "listen failed"); 4681558Srgrimes exit(1); 4691558Srgrimes } 4709336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 4719336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { 4721558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 4731558Srgrimes exit(1); 4741558Srgrimes } 4751558Srgrimes FD_SET(tcpsock, &sockbits); 4761558Srgrimes maxsock = tcpsock; 4771558Srgrimes connect_type_cnt++; 4781558Srgrimes } 4791558Srgrimes 4801558Srgrimes#ifdef notyet 4811558Srgrimes /* Now set up the master server socket waiting for tp4 connections. */ 4821558Srgrimes if (tp4flag) { 4831558Srgrimes if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 4841558Srgrimes syslog(LOG_ERR, "can't create tp4 socket"); 4851558Srgrimes exit(1); 4861558Srgrimes } 4871558Srgrimes if (setsockopt(tp4sock, 4881558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4891558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4901558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4911558Srgrimes isoaddr.siso_family = AF_ISO; 4921558Srgrimes isoaddr.siso_tlen = 2; 4931558Srgrimes cp = TSEL(&isoaddr); 4941558Srgrimes *cp++ = (NFS_PORT >> 8); 4951558Srgrimes *cp = (NFS_PORT & 0xff); 4961558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 4971558Srgrimes if (bind(tp4sock, 4981558Srgrimes (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 4991558Srgrimes syslog(LOG_ERR, "can't bind tp4 addr"); 5001558Srgrimes exit(1); 5011558Srgrimes } 5021558Srgrimes if (listen(tp4sock, 5) < 0) { 5031558Srgrimes syslog(LOG_ERR, "listen failed"); 5041558Srgrimes exit(1); 5051558Srgrimes } 5061558Srgrimes /* 5071558Srgrimes * XXX 5081558Srgrimes * Someday this should probably use "rpcbind", the son of 5091558Srgrimes * portmap. 5101558Srgrimes */ 5111558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5121558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5131558Srgrimes exit(1); 5141558Srgrimes } 5151558Srgrimes FD_SET(tp4sock, &sockbits); 5161558Srgrimes maxsock = tp4sock; 5171558Srgrimes connect_type_cnt++; 5181558Srgrimes } 5191558Srgrimes 5201558Srgrimes /* Now set up the master server socket waiting for tpip connections. */ 5211558Srgrimes if (tpipflag) { 5221558Srgrimes if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 5231558Srgrimes syslog(LOG_ERR, "can't create tpip socket"); 5241558Srgrimes exit(1); 5251558Srgrimes } 5261558Srgrimes if (setsockopt(tpipsock, 5271558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 5281558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 5291558Srgrimes inetaddr.sin_family = AF_INET; 5301558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 5311558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 5321558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 5331558Srgrimes if (bind(tpipsock, 5341558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 5351558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 5361558Srgrimes exit(1); 5371558Srgrimes } 5381558Srgrimes if (listen(tpipsock, 5) < 0) { 5391558Srgrimes syslog(LOG_ERR, "listen failed"); 5401558Srgrimes exit(1); 5411558Srgrimes } 5421558Srgrimes /* 5431558Srgrimes * XXX 5441558Srgrimes * Someday this should probably use "rpcbind", the son of 5451558Srgrimes * portmap. 5461558Srgrimes */ 5471558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5481558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5491558Srgrimes exit(1); 5501558Srgrimes } 5511558Srgrimes FD_SET(tpipsock, &sockbits); 5521558Srgrimes maxsock = tpipsock; 5531558Srgrimes connect_type_cnt++; 5541558Srgrimes } 5551558Srgrimes#endif /* notyet */ 5561558Srgrimes 5571558Srgrimes if (connect_type_cnt == 0) 5581558Srgrimes exit(0); 5591558Srgrimes 5609336Sdfr setproctitle("master"); 5611558Srgrimes 5621558Srgrimes /* 5631558Srgrimes * Loop forever accepting connections and passing the sockets 5641558Srgrimes * into the kernel for the mounts. 5651558Srgrimes */ 5661558Srgrimes for (;;) { 5671558Srgrimes ready = sockbits; 5681558Srgrimes if (connect_type_cnt > 1) { 5691558Srgrimes if (select(maxsock + 1, 5701558Srgrimes &ready, NULL, NULL, NULL) < 1) { 5711558Srgrimes syslog(LOG_ERR, "select failed: %m"); 5721558Srgrimes exit(1); 5731558Srgrimes } 5741558Srgrimes } 5751558Srgrimes if (tcpflag && FD_ISSET(tcpsock, &ready)) { 5761558Srgrimes len = sizeof(inetpeer); 5771558Srgrimes if ((msgsock = accept(tcpsock, 5781558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5791558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 5801558Srgrimes exit(1); 5811558Srgrimes } 5821558Srgrimes memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 5831558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 5841558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5851558Srgrimes syslog(LOG_ERR, 5861558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 5871558Srgrimes nfsdargs.sock = msgsock; 5881558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 5891558Srgrimes nfsdargs.namelen = sizeof(inetpeer); 5901558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5911558Srgrimes (void)close(msgsock); 5921558Srgrimes } 5931558Srgrimes#ifdef notyet 5941558Srgrimes if (tp4flag && FD_ISSET(tp4sock, &ready)) { 5951558Srgrimes len = sizeof(isopeer); 5961558Srgrimes if ((msgsock = accept(tp4sock, 5971558Srgrimes (struct sockaddr *)&isopeer, &len)) < 0) { 5981558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 5991558Srgrimes exit(1); 6001558Srgrimes } 6011558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 6021558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6031558Srgrimes syslog(LOG_ERR, 6041558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 6051558Srgrimes nfsdargs.sock = msgsock; 6061558Srgrimes nfsdargs.name = (caddr_t)&isopeer; 6071558Srgrimes nfsdargs.namelen = len; 6081558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6091558Srgrimes (void)close(msgsock); 6101558Srgrimes } 6111558Srgrimes if (tpipflag && FD_ISSET(tpipsock, &ready)) { 6121558Srgrimes len = sizeof(inetpeer); 6131558Srgrimes if ((msgsock = accept(tpipsock, 6141558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 6151558Srgrimes syslog(LOG_ERR, "Accept failed: %m"); 6161558Srgrimes exit(1); 6171558Srgrimes } 6181558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 6191558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6201558Srgrimes syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 6211558Srgrimes nfsdargs.sock = msgsock; 6221558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 6231558Srgrimes nfsdargs.namelen = len; 6241558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6251558Srgrimes (void)close(msgsock); 6261558Srgrimes } 6271558Srgrimes#endif /* notyet */ 6281558Srgrimes } 6291558Srgrimes} 6301558Srgrimes 6311558Srgrimesvoid 6321558Srgrimesusage() 6331558Srgrimes{ 6349336Sdfr (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 6351558Srgrimes exit(1); 6361558Srgrimes} 6371558Srgrimes 6381558Srgrimesvoid 6391558Srgrimesnonfs(signo) 6401558Srgrimes int signo; 6411558Srgrimes{ 6421558Srgrimes syslog(LOG_ERR, "missing system call: NFS not available."); 6431558Srgrimes} 6441558Srgrimes 6451558Srgrimesvoid 6461558Srgrimesreapchild(signo) 6471558Srgrimes int signo; 6481558Srgrimes{ 6491558Srgrimes 6509336Sdfr while (wait3(NULL, WNOHANG, NULL) > 0); 6511558Srgrimes} 6521558Srgrimes 65313141Speter#ifdef OLD_SETPROCTITLE 6549336Sdfr#ifdef __FreeBSD__ 6551558Srgrimesvoid 6561558Srgrimessetproctitle(a) 6571558Srgrimes char *a; 6581558Srgrimes{ 6591558Srgrimes register char *cp; 6601558Srgrimes char buf[80]; 6611558Srgrimes 6621558Srgrimes cp = Argv[0]; 6639336Sdfr (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 6641558Srgrimes (void)strncpy(cp, buf, LastArg - cp); 6651558Srgrimes cp += strlen(cp); 6661558Srgrimes while (cp < LastArg) 6672030Sdg *cp++ = '\0'; 66812869Speter Argv[1] = NULL; 6691558Srgrimes} 6709336Sdfr#endif /* __FreeBSD__ */ 67113141Speter#endif 672