nfsd.c revision 31206
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 4423684Speterstatic char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 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 7023684Speter#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__ 16123684Speter struct vfsconf vfc; 16223684Speter int error; 1631558Srgrimes 16423684Speter error = getvfsbyname("nfs", &vfc); 16523684Speter if (error && vfsisloadable("nfs")) { 16623684Speter if (vfsload("nfs")) 1672999Swollman err(1, "vfsload(nfs)"); 1682999Swollman endvfsent(); /* flush cache */ 16923684Speter error = getvfsbyname("nfs", &vfc); 1702999Swollman } 17123684Speter if (error) 1722999Swollman errx(1, "NFS is not available in the running kernel"); 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 19724359Simp while ((ch = getopt(argc, argv, GETOPT)) != -1) 1981558Srgrimes switch (ch) { 1991558Srgrimes case 'n': 2001558Srgrimes nfsdcnt = atoi(optarg); 2011558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 20231206Sjdp warnx("nfsd count %d; reset to %d", nfsdcnt, 20331206Sjdp DEFNFSDCNT); 2041558Srgrimes nfsdcnt = DEFNFSDCNT; 2051558Srgrimes } 2061558Srgrimes break; 2071558Srgrimes case 'r': 2081558Srgrimes reregister = 1; 2091558Srgrimes break; 2101558Srgrimes case 't': 2111558Srgrimes tcpflag = 1; 2121558Srgrimes break; 2131558Srgrimes case 'u': 2141558Srgrimes udpflag = 1; 2151558Srgrimes break; 2161558Srgrimes#ifdef ISO 2171558Srgrimes case 'c': 2181558Srgrimes cltpflag = 1; 2191558Srgrimes break; 2201558Srgrimes#ifdef notyet 2211558Srgrimes case 'i': 2221558Srgrimes tp4cnt = 1; 2231558Srgrimes break; 2241558Srgrimes case 'p': 2251558Srgrimes tpipcnt = 1; 2261558Srgrimes break; 2271558Srgrimes#endif /* notyet */ 2281558Srgrimes#endif /* ISO */ 2291558Srgrimes default: 2301558Srgrimes case '?': 2311558Srgrimes usage(); 2321558Srgrimes }; 23315496Sbde if (!tcpflag && !udpflag) 23415496Sbde udpflag = 1; 2351558Srgrimes argv += optind; 2361558Srgrimes argc -= optind; 2371558Srgrimes 2381558Srgrimes /* 2391558Srgrimes * XXX 2401558Srgrimes * Backward compatibility, trailing number is the count of daemons. 2411558Srgrimes */ 2421558Srgrimes if (argc > 1) 2431558Srgrimes usage(); 2441558Srgrimes if (argc == 1) { 2451558Srgrimes nfsdcnt = atoi(argv[0]); 2461558Srgrimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 24731206Sjdp warnx("nfsd count %d; reset to %d", nfsdcnt, 24831206Sjdp DEFNFSDCNT); 2491558Srgrimes nfsdcnt = DEFNFSDCNT; 2501558Srgrimes } 2511558Srgrimes } 2521558Srgrimes 2531558Srgrimes if (debug == 0) { 2541558Srgrimes daemon(0, 0); 2551558Srgrimes (void)signal(SIGHUP, SIG_IGN); 2561558Srgrimes (void)signal(SIGINT, SIG_IGN); 2571558Srgrimes (void)signal(SIGQUIT, SIG_IGN); 2581558Srgrimes (void)signal(SIGSYS, nonfs); 2591558Srgrimes (void)signal(SIGTERM, SIG_IGN); 2601558Srgrimes } 2611558Srgrimes (void)signal(SIGCHLD, reapchild); 2621558Srgrimes 2631558Srgrimes if (reregister) { 2641558Srgrimes if (udpflag && 2659336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 2669336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) 2671558Srgrimes err(1, "can't register with portmap for UDP."); 2681558Srgrimes if (tcpflag && 2699336Sdfr (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 2709336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) 2711558Srgrimes err(1, "can't register with portmap for TCP."); 2721558Srgrimes exit(0); 2731558Srgrimes } 2741558Srgrimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 2751558Srgrimes 2761558Srgrimes for (i = 0; i < nfsdcnt; i++) { 2771558Srgrimes switch (fork()) { 2781558Srgrimes case -1: 2791558Srgrimes syslog(LOG_ERR, "fork: %m"); 2801558Srgrimes exit (1); 2811558Srgrimes case 0: 2821558Srgrimes break; 2831558Srgrimes default: 2841558Srgrimes continue; 2851558Srgrimes } 2861558Srgrimes 2879336Sdfr setproctitle("server"); 2881558Srgrimes nfssvc_flag = NFSSVC_NFSD; 2891558Srgrimes nsd.nsd_nfsd = NULL; 2909336Sdfr#ifdef NFSKERB 2919336Sdfr if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 2929336Sdfr sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 2939336Sdfr syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 2949336Sdfr nsd.nsd_authstr = (u_char *)&kt; 2959336Sdfr nsd.nsd_authlen = sizeof (kt); 2969336Sdfr nsd.nsd_verfstr = (u_char *)&kverf; 2979336Sdfr nsd.nsd_verflen = sizeof (kverf); 2981558Srgrimes#endif 2991558Srgrimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 3001558Srgrimes if (errno != ENEEDAUTH) { 3011558Srgrimes syslog(LOG_ERR, "nfssvc: %m"); 3021558Srgrimes exit(1); 3031558Srgrimes } 3041558Srgrimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 3059336Sdfr#ifdef NFSKERB 3069336Sdfr /* 3079336Sdfr * Get the Kerberos ticket out of the authenticator 3089336Sdfr * verify it and convert the principal name to a user 3099336Sdfr * name. The user name is then converted to a set of 3109336Sdfr * user credentials via the password and group file. 3119336Sdfr * Finally, decrypt the timestamp and validate it. 3129336Sdfr * For more info see the IETF Draft "Authentication 3139336Sdfr * in ONC RPC". 3149336Sdfr */ 3159336Sdfr kt.length = ntohl(kt.length); 3169336Sdfr if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 3179336Sdfr kt.length > 0 && kt.length <= 3189336Sdfr (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 3199336Sdfr kin.w1 = NFS_KERBW1(kt); 3209336Sdfr kt.mbz = 0; 3219336Sdfr (void)strcpy(inst, "*"); 3229336Sdfr if (krb_rd_req(&kt, NFS_KERBSRV, 3239336Sdfr inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 3249336Sdfr krb_kntoln(&kauth, lnam) == KSUCCESS && 3259336Sdfr (pwd = getpwnam(lnam)) != NULL) { 3261558Srgrimes cr = &nsd.nsd_cr; 3271558Srgrimes cr->cr_uid = pwd->pw_uid; 3281558Srgrimes cr->cr_groups[0] = pwd->pw_gid; 3291558Srgrimes cr->cr_ngroups = 1; 3301558Srgrimes setgrent(); 3311558Srgrimes while ((grp = getgrent()) != NULL) { 3321558Srgrimes if (grp->gr_gid == cr->cr_groups[0]) 3331558Srgrimes continue; 3341558Srgrimes for (cpp = grp->gr_mem; 3351558Srgrimes *cpp != NULL; ++cpp) 3361558Srgrimes if (!strcmp(*cpp, lnam)) 3371558Srgrimes break; 3381558Srgrimes if (*cpp == NULL) 3391558Srgrimes continue; 3401558Srgrimes cr->cr_groups[cr->cr_ngroups++] 3411558Srgrimes = grp->gr_gid; 3421558Srgrimes if (cr->cr_ngroups == NGROUPS) 3431558Srgrimes break; 3441558Srgrimes } 3451558Srgrimes endgrent(); 3469336Sdfr 3479336Sdfr /* 3489336Sdfr * Get the timestamp verifier out of the 3499336Sdfr * authenticator and verifier strings. 3509336Sdfr */ 3519336Sdfr kin.t1 = kverf.t1; 3529336Sdfr kin.t2 = kverf.t2; 3539336Sdfr kin.w2 = kverf.w2; 3549336Sdfr bzero((caddr_t)kivec, sizeof (kivec)); 3559336Sdfr bcopy((caddr_t)kauth.session, 3569336Sdfr (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 3579336Sdfr 3589336Sdfr /* 3599336Sdfr * Decrypt the timestamp verifier in CBC mode. 3609336Sdfr */ 3619336Sdfr XXX 3629336Sdfr 3639336Sdfr /* 3649336Sdfr * Validate the timestamp verifier, to 3659336Sdfr * check that the session key is ok. 3669336Sdfr */ 3679336Sdfr nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 3689336Sdfr nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 3699336Sdfr nsd.nsd_ttl = ntohl(kout.w1); 3709336Sdfr if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 3719336Sdfr nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 3721558Srgrimes } 3739336Sdfr#endif /* NFSKERB */ 3741558Srgrimes } 3751558Srgrimes exit(0); 3761558Srgrimes } 3771558Srgrimes 3781558Srgrimes /* If we are serving udp, set up the socket. */ 3791558Srgrimes if (udpflag) { 3801558Srgrimes if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 3811558Srgrimes syslog(LOG_ERR, "can't create udp socket"); 3821558Srgrimes exit(1); 3831558Srgrimes } 3841558Srgrimes inetaddr.sin_family = AF_INET; 3851558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3861558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 3871558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 3881558Srgrimes if (bind(sock, 3891558Srgrimes (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 3901558Srgrimes syslog(LOG_ERR, "can't bind udp addr"); 3911558Srgrimes exit(1); 3921558Srgrimes } 3939336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || 3949336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { 3951558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 3961558Srgrimes exit(1); 3971558Srgrimes } 3981558Srgrimes nfsdargs.sock = sock; 3991558Srgrimes nfsdargs.name = NULL; 4001558Srgrimes nfsdargs.namelen = 0; 4011558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 4021558Srgrimes syslog(LOG_ERR, "can't Add UDP socket"); 4031558Srgrimes exit(1); 4041558Srgrimes } 4051558Srgrimes (void)close(sock); 4061558Srgrimes } 4071558Srgrimes 4081558Srgrimes#ifdef ISO 4091558Srgrimes /* If we are serving cltp, set up the socket. */ 4101558Srgrimes if (cltpflag) { 4111558Srgrimes if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 4121558Srgrimes syslog(LOG_ERR, "can't create cltp socket"); 4131558Srgrimes exit(1); 4141558Srgrimes } 4151558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4161558Srgrimes isoaddr.siso_family = AF_ISO; 4171558Srgrimes isoaddr.siso_tlen = 2; 4181558Srgrimes cp = TSEL(&isoaddr); 4191558Srgrimes *cp++ = (NFS_PORT >> 8); 4201558Srgrimes *cp = (NFS_PORT & 0xff); 4211558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 4221558Srgrimes if (bind(sock, 4231558Srgrimes (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 4241558Srgrimes syslog(LOG_ERR, "can't bind cltp addr"); 4251558Srgrimes exit(1); 4261558Srgrimes } 4271558Srgrimes#ifdef notyet 4281558Srgrimes /* 4291558Srgrimes * XXX 4301558Srgrimes * Someday this should probably use "rpcbind", the son of 4311558Srgrimes * portmap. 4321558Srgrimes */ 4331558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 4341558Srgrimes syslog(LOG_ERR, "can't register with udp portmap"); 4351558Srgrimes exit(1); 4361558Srgrimes } 4371558Srgrimes#endif /* notyet */ 4381558Srgrimes nfsdargs.sock = sock; 4391558Srgrimes nfsdargs.name = NULL; 4401558Srgrimes nfsdargs.namelen = 0; 4411558Srgrimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 4421558Srgrimes syslog(LOG_ERR, "can't add UDP socket"); 4431558Srgrimes exit(1); 4441558Srgrimes } 4451558Srgrimes close(sock); 4461558Srgrimes } 4471558Srgrimes#endif /* ISO */ 4481558Srgrimes 4491558Srgrimes /* Now set up the master server socket waiting for tcp connections. */ 4501558Srgrimes on = 1; 4511558Srgrimes FD_ZERO(&sockbits); 4521558Srgrimes connect_type_cnt = 0; 4531558Srgrimes if (tcpflag) { 4541558Srgrimes if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 4551558Srgrimes syslog(LOG_ERR, "can't create tcp socket"); 4561558Srgrimes exit(1); 4571558Srgrimes } 4581558Srgrimes if (setsockopt(tcpsock, 4591558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4601558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4611558Srgrimes inetaddr.sin_family = AF_INET; 4621558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 4631558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 4641558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 4651558Srgrimes if (bind(tcpsock, 4661558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 4671558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 4681558Srgrimes exit(1); 4691558Srgrimes } 4701558Srgrimes if (listen(tcpsock, 5) < 0) { 4711558Srgrimes syslog(LOG_ERR, "listen failed"); 4721558Srgrimes exit(1); 4731558Srgrimes } 4749336Sdfr if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || 4759336Sdfr !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { 4761558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 4771558Srgrimes exit(1); 4781558Srgrimes } 4791558Srgrimes FD_SET(tcpsock, &sockbits); 4801558Srgrimes maxsock = tcpsock; 4811558Srgrimes connect_type_cnt++; 4821558Srgrimes } 4831558Srgrimes 4841558Srgrimes#ifdef notyet 4851558Srgrimes /* Now set up the master server socket waiting for tp4 connections. */ 4861558Srgrimes if (tp4flag) { 4871558Srgrimes if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 4881558Srgrimes syslog(LOG_ERR, "can't create tp4 socket"); 4891558Srgrimes exit(1); 4901558Srgrimes } 4911558Srgrimes if (setsockopt(tp4sock, 4921558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4931558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4941558Srgrimes memset(&isoaddr, 0, sizeof(isoaddr)); 4951558Srgrimes isoaddr.siso_family = AF_ISO; 4961558Srgrimes isoaddr.siso_tlen = 2; 4971558Srgrimes cp = TSEL(&isoaddr); 4981558Srgrimes *cp++ = (NFS_PORT >> 8); 4991558Srgrimes *cp = (NFS_PORT & 0xff); 5001558Srgrimes isoaddr.siso_len = sizeof(isoaddr); 5011558Srgrimes if (bind(tp4sock, 5021558Srgrimes (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 5031558Srgrimes syslog(LOG_ERR, "can't bind tp4 addr"); 5041558Srgrimes exit(1); 5051558Srgrimes } 5061558Srgrimes if (listen(tp4sock, 5) < 0) { 5071558Srgrimes syslog(LOG_ERR, "listen failed"); 5081558Srgrimes exit(1); 5091558Srgrimes } 5101558Srgrimes /* 5111558Srgrimes * XXX 5121558Srgrimes * Someday this should probably use "rpcbind", the son of 5131558Srgrimes * portmap. 5141558Srgrimes */ 5151558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5161558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5171558Srgrimes exit(1); 5181558Srgrimes } 5191558Srgrimes FD_SET(tp4sock, &sockbits); 5201558Srgrimes maxsock = tp4sock; 5211558Srgrimes connect_type_cnt++; 5221558Srgrimes } 5231558Srgrimes 5241558Srgrimes /* Now set up the master server socket waiting for tpip connections. */ 5251558Srgrimes if (tpipflag) { 5261558Srgrimes if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 5271558Srgrimes syslog(LOG_ERR, "can't create tpip socket"); 5281558Srgrimes exit(1); 5291558Srgrimes } 5301558Srgrimes if (setsockopt(tpipsock, 5311558Srgrimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 5321558Srgrimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 5331558Srgrimes inetaddr.sin_family = AF_INET; 5341558Srgrimes inetaddr.sin_addr.s_addr = INADDR_ANY; 5351558Srgrimes inetaddr.sin_port = htons(NFS_PORT); 5361558Srgrimes inetaddr.sin_len = sizeof(inetaddr); 5371558Srgrimes if (bind(tpipsock, 5381558Srgrimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 5391558Srgrimes syslog(LOG_ERR, "can't bind tcp addr"); 5401558Srgrimes exit(1); 5411558Srgrimes } 5421558Srgrimes if (listen(tpipsock, 5) < 0) { 5431558Srgrimes syslog(LOG_ERR, "listen failed"); 5441558Srgrimes exit(1); 5451558Srgrimes } 5461558Srgrimes /* 5471558Srgrimes * XXX 5481558Srgrimes * Someday this should probably use "rpcbind", the son of 5491558Srgrimes * portmap. 5501558Srgrimes */ 5511558Srgrimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 5521558Srgrimes syslog(LOG_ERR, "can't register tcp with portmap"); 5531558Srgrimes exit(1); 5541558Srgrimes } 5551558Srgrimes FD_SET(tpipsock, &sockbits); 5561558Srgrimes maxsock = tpipsock; 5571558Srgrimes connect_type_cnt++; 5581558Srgrimes } 5591558Srgrimes#endif /* notyet */ 5601558Srgrimes 5611558Srgrimes if (connect_type_cnt == 0) 5621558Srgrimes exit(0); 5631558Srgrimes 5649336Sdfr setproctitle("master"); 5651558Srgrimes 5661558Srgrimes /* 5671558Srgrimes * Loop forever accepting connections and passing the sockets 5681558Srgrimes * into the kernel for the mounts. 5691558Srgrimes */ 5701558Srgrimes for (;;) { 5711558Srgrimes ready = sockbits; 5721558Srgrimes if (connect_type_cnt > 1) { 5731558Srgrimes if (select(maxsock + 1, 5741558Srgrimes &ready, NULL, NULL, NULL) < 1) { 5751558Srgrimes syslog(LOG_ERR, "select failed: %m"); 5761558Srgrimes exit(1); 5771558Srgrimes } 5781558Srgrimes } 5791558Srgrimes if (tcpflag && FD_ISSET(tcpsock, &ready)) { 5801558Srgrimes len = sizeof(inetpeer); 5811558Srgrimes if ((msgsock = accept(tcpsock, 5821558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5831558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 5841558Srgrimes exit(1); 5851558Srgrimes } 5861558Srgrimes memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 5871558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 5881558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5891558Srgrimes syslog(LOG_ERR, 5901558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 5911558Srgrimes nfsdargs.sock = msgsock; 5921558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 5931558Srgrimes nfsdargs.namelen = sizeof(inetpeer); 5941558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5951558Srgrimes (void)close(msgsock); 5961558Srgrimes } 5971558Srgrimes#ifdef notyet 5981558Srgrimes if (tp4flag && FD_ISSET(tp4sock, &ready)) { 5991558Srgrimes len = sizeof(isopeer); 6001558Srgrimes if ((msgsock = accept(tp4sock, 6011558Srgrimes (struct sockaddr *)&isopeer, &len)) < 0) { 6021558Srgrimes syslog(LOG_ERR, "accept failed: %m"); 6031558Srgrimes exit(1); 6041558Srgrimes } 6051558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 6061558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6071558Srgrimes syslog(LOG_ERR, 6081558Srgrimes "setsockopt SO_KEEPALIVE: %m"); 6091558Srgrimes nfsdargs.sock = msgsock; 6101558Srgrimes nfsdargs.name = (caddr_t)&isopeer; 6111558Srgrimes nfsdargs.namelen = len; 6121558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6131558Srgrimes (void)close(msgsock); 6141558Srgrimes } 6151558Srgrimes if (tpipflag && FD_ISSET(tpipsock, &ready)) { 6161558Srgrimes len = sizeof(inetpeer); 6171558Srgrimes if ((msgsock = accept(tpipsock, 6181558Srgrimes (struct sockaddr *)&inetpeer, &len)) < 0) { 6191558Srgrimes syslog(LOG_ERR, "Accept failed: %m"); 6201558Srgrimes exit(1); 6211558Srgrimes } 6221558Srgrimes if (setsockopt(msgsock, SOL_SOCKET, 6231558Srgrimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 6241558Srgrimes syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 6251558Srgrimes nfsdargs.sock = msgsock; 6261558Srgrimes nfsdargs.name = (caddr_t)&inetpeer; 6271558Srgrimes nfsdargs.namelen = len; 6281558Srgrimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 6291558Srgrimes (void)close(msgsock); 6301558Srgrimes } 6311558Srgrimes#endif /* notyet */ 6321558Srgrimes } 6331558Srgrimes} 6341558Srgrimes 6351558Srgrimesvoid 6361558Srgrimesusage() 6371558Srgrimes{ 6389336Sdfr (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 6391558Srgrimes exit(1); 6401558Srgrimes} 6411558Srgrimes 6421558Srgrimesvoid 6431558Srgrimesnonfs(signo) 6441558Srgrimes int signo; 6451558Srgrimes{ 6461558Srgrimes syslog(LOG_ERR, "missing system call: NFS not available."); 6471558Srgrimes} 6481558Srgrimes 6491558Srgrimesvoid 6501558Srgrimesreapchild(signo) 6511558Srgrimes int signo; 6521558Srgrimes{ 6531558Srgrimes 6549336Sdfr while (wait3(NULL, WNOHANG, NULL) > 0); 6551558Srgrimes} 6561558Srgrimes 65713141Speter#ifdef OLD_SETPROCTITLE 6589336Sdfr#ifdef __FreeBSD__ 6591558Srgrimesvoid 6601558Srgrimessetproctitle(a) 6611558Srgrimes char *a; 6621558Srgrimes{ 6631558Srgrimes register char *cp; 6641558Srgrimes char buf[80]; 6651558Srgrimes 6661558Srgrimes cp = Argv[0]; 6679336Sdfr (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 6681558Srgrimes (void)strncpy(cp, buf, LastArg - cp); 6691558Srgrimes cp += strlen(cp); 6701558Srgrimes while (cp < LastArg) 6712030Sdg *cp++ = '\0'; 67212869Speter Argv[1] = NULL; 6731558Srgrimes} 6749336Sdfr#endif /* __FreeBSD__ */ 67513141Speter#endif 676