18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 388fae3551SRodney W. Grimes static char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 418fae3551SRodney W. Grimes #endif not lint 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 448fae3551SRodney W. Grimes static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94"; 458fae3551SRodney W. Grimes #endif not lint 468fae3551SRodney W. Grimes 478fae3551SRodney W. Grimes #include <sys/param.h> 488fae3551SRodney W. Grimes #include <sys/syslog.h> 498fae3551SRodney W. Grimes #include <sys/ioctl.h> 508fae3551SRodney W. Grimes #include <sys/stat.h> 518fae3551SRodney W. Grimes #include <sys/wait.h> 528fae3551SRodney W. Grimes #include <sys/uio.h> 538fae3551SRodney W. Grimes #include <sys/ucred.h> 548fae3551SRodney W. Grimes #include <sys/mount.h> 558fae3551SRodney W. Grimes #include <sys/socket.h> 568fae3551SRodney W. Grimes #include <sys/socketvar.h> 578fae3551SRodney W. Grimes 588fae3551SRodney W. Grimes #include <rpc/rpc.h> 598fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 608fae3551SRodney W. Grimes #include <rpc/pmap_prot.h> 618fae3551SRodney W. Grimes 628fae3551SRodney W. Grimes #ifdef ISO 638fae3551SRodney W. Grimes #include <netiso/iso.h> 648fae3551SRodney W. Grimes #endif 658fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 668fae3551SRodney W. Grimes #include <nfs/nfsv2.h> 678fae3551SRodney W. Grimes #include <nfs/nfs.h> 688fae3551SRodney W. Grimes 698fae3551SRodney W. Grimes #ifdef KERBEROS 708fae3551SRodney W. Grimes #include <kerberosIV/des.h> 718fae3551SRodney W. Grimes #include <kerberosIV/krb.h> 728fae3551SRodney W. Grimes #endif 738fae3551SRodney W. Grimes 748fae3551SRodney W. Grimes #include <err.h> 758fae3551SRodney W. Grimes #include <errno.h> 768fae3551SRodney W. Grimes #include <fcntl.h> 778fae3551SRodney W. Grimes #include <grp.h> 788fae3551SRodney W. Grimes #include <pwd.h> 798fae3551SRodney W. Grimes #include <signal.h> 808fae3551SRodney W. Grimes #include <stdio.h> 818fae3551SRodney W. Grimes #include <stdlib.h> 828fae3551SRodney W. Grimes #include <strings.h> 838fae3551SRodney W. Grimes #include <unistd.h> 848fae3551SRodney W. Grimes 858fae3551SRodney W. Grimes /* Global defs */ 868fae3551SRodney W. Grimes #ifdef DEBUG 878fae3551SRodney W. Grimes #define syslog(e, s) fprintf(stderr,(s)) 888fae3551SRodney W. Grimes int debug = 1; 898fae3551SRodney W. Grimes #else 908fae3551SRodney W. Grimes int debug = 0; 918fae3551SRodney W. Grimes #endif 928fae3551SRodney W. Grimes 938fae3551SRodney W. Grimes struct nfsd_srvargs nsd; 948fae3551SRodney W. Grimes char **Argv = NULL; /* pointer to argument vector */ 958fae3551SRodney W. Grimes char *LastArg = NULL; /* end of argv */ 968fae3551SRodney W. Grimes 978fae3551SRodney W. Grimes #ifdef KERBEROS 988fae3551SRodney W. Grimes char lnam[ANAME_SZ]; 998fae3551SRodney W. Grimes KTEXT_ST kt; 1008fae3551SRodney W. Grimes AUTH_DAT auth; 1018fae3551SRodney W. Grimes char inst[INST_SZ]; 1028fae3551SRodney W. Grimes #endif 1038fae3551SRodney W. Grimes 1048fae3551SRodney W. Grimes void nonfs __P((int)); 1058fae3551SRodney W. Grimes void reapchild __P((int)); 1068fae3551SRodney W. Grimes void setproctitle __P((char *)); 1078fae3551SRodney W. Grimes void usage __P((void)); 1088fae3551SRodney W. Grimes 1098fae3551SRodney W. Grimes /* 1108fae3551SRodney W. Grimes * Nfs server daemon mostly just a user context for nfssvc() 1118fae3551SRodney W. Grimes * 1128fae3551SRodney W. Grimes * 1 - do file descriptor and signal cleanup 1138fae3551SRodney W. Grimes * 2 - fork the nfsd(s) 1148fae3551SRodney W. Grimes * 3 - create server socket(s) 1158fae3551SRodney W. Grimes * 4 - register socket with portmap 1168fae3551SRodney W. Grimes * 1178fae3551SRodney W. Grimes * For connectionless protocols, just pass the socket into the kernel via. 1188fae3551SRodney W. Grimes * nfssvc(). 1198fae3551SRodney W. Grimes * For connection based sockets, loop doing accepts. When you get a new 1208fae3551SRodney W. Grimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1218fae3551SRodney W. Grimes * The arguments are: 1228fae3551SRodney W. Grimes * -c - support iso cltp clients 1238fae3551SRodney W. Grimes * -r - reregister with portmapper 1248fae3551SRodney W. Grimes * -t - support tcp nfs clients 1258fae3551SRodney W. Grimes * -u - support udp nfs clients 1268fae3551SRodney W. Grimes * followed by "n" which is the number of nfsds' to fork off 1278fae3551SRodney W. Grimes */ 1288fae3551SRodney W. Grimes int 1298fae3551SRodney W. Grimes main(argc, argv, envp) 1308fae3551SRodney W. Grimes int argc; 1318fae3551SRodney W. Grimes char *argv[], *envp[]; 1328fae3551SRodney W. Grimes { 1338fae3551SRodney W. Grimes extern int optind; 1348fae3551SRodney W. Grimes struct group *grp; 1358fae3551SRodney W. Grimes struct nfsd_args nfsdargs; 1368fae3551SRodney W. Grimes struct passwd *pwd; 1378fae3551SRodney W. Grimes struct ucred *cr; 1388fae3551SRodney W. Grimes struct sockaddr_in inetaddr, inetpeer; 1398fae3551SRodney W. Grimes #ifdef ISO 1408fae3551SRodney W. Grimes struct sockaddr_iso isoaddr, isopeer; 1418fae3551SRodney W. Grimes #endif 1428fae3551SRodney W. Grimes fd_set ready, sockbits; 1438fae3551SRodney W. Grimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 1448fae3551SRodney W. Grimes int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; 1458fae3551SRodney W. Grimes int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; 1468fae3551SRodney W. Grimes char *cp, **cpp; 1478fae3551SRodney W. Grimes 1488fae3551SRodney W. Grimes /* Save start and extent of argv for setproctitle. */ 1498fae3551SRodney W. Grimes Argv = argv; 1508fae3551SRodney W. Grimes if (envp == 0 || *envp == 0) 1518fae3551SRodney W. Grimes envp = argv; 1528fae3551SRodney W. Grimes while (*envp) 1538fae3551SRodney W. Grimes envp++; 1548fae3551SRodney W. Grimes LastArg = envp[-1] + strlen(envp[-1]); 1558fae3551SRodney W. Grimes 1568fae3551SRodney W. Grimes #define MAXNFSDCNT 20 1578fae3551SRodney W. Grimes #define DEFNFSDCNT 4 1588fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 1598fae3551SRodney W. Grimes cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; 1608fae3551SRodney W. Grimes tpipflag = udpflag = 0; 1618fae3551SRodney W. Grimes #ifdef ISO 1628fae3551SRodney W. Grimes #define GETOPT "cn:rtu" 1638fae3551SRodney W. Grimes #define USAGE "[-crtu] [-n num_servers]" 1648fae3551SRodney W. Grimes #else 1658fae3551SRodney W. Grimes #define GETOPT "n:rtu" 1668fae3551SRodney W. Grimes #define USAGE "[-rtu] [-n num_servers]" 1678fae3551SRodney W. Grimes #endif 1688fae3551SRodney W. Grimes while ((ch = getopt(argc, argv, GETOPT)) != EOF) 1698fae3551SRodney W. Grimes switch (ch) { 1708fae3551SRodney W. Grimes case 'n': 1718fae3551SRodney W. Grimes nfsdcnt = atoi(optarg); 1728fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 1738fae3551SRodney W. Grimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 1748fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 1758fae3551SRodney W. Grimes } 1768fae3551SRodney W. Grimes break; 1778fae3551SRodney W. Grimes case 'r': 1788fae3551SRodney W. Grimes reregister = 1; 1798fae3551SRodney W. Grimes break; 1808fae3551SRodney W. Grimes case 't': 1818fae3551SRodney W. Grimes tcpflag = 1; 1828fae3551SRodney W. Grimes break; 1838fae3551SRodney W. Grimes case 'u': 1848fae3551SRodney W. Grimes udpflag = 1; 1858fae3551SRodney W. Grimes break; 1868fae3551SRodney W. Grimes #ifdef ISO 1878fae3551SRodney W. Grimes case 'c': 1888fae3551SRodney W. Grimes cltpflag = 1; 1898fae3551SRodney W. Grimes break; 1908fae3551SRodney W. Grimes #ifdef notyet 1918fae3551SRodney W. Grimes case 'i': 1928fae3551SRodney W. Grimes tp4cnt = 1; 1938fae3551SRodney W. Grimes break; 1948fae3551SRodney W. Grimes case 'p': 1958fae3551SRodney W. Grimes tpipcnt = 1; 1968fae3551SRodney W. Grimes break; 1978fae3551SRodney W. Grimes #endif /* notyet */ 1988fae3551SRodney W. Grimes #endif /* ISO */ 1998fae3551SRodney W. Grimes default: 2008fae3551SRodney W. Grimes case '?': 2018fae3551SRodney W. Grimes usage(); 2028fae3551SRodney W. Grimes }; 2038fae3551SRodney W. Grimes argv += optind; 2048fae3551SRodney W. Grimes argc -= optind; 2058fae3551SRodney W. Grimes 2068fae3551SRodney W. Grimes /* 2078fae3551SRodney W. Grimes * XXX 2088fae3551SRodney W. Grimes * Backward compatibility, trailing number is the count of daemons. 2098fae3551SRodney W. Grimes */ 2108fae3551SRodney W. Grimes if (argc > 1) 2118fae3551SRodney W. Grimes usage(); 2128fae3551SRodney W. Grimes if (argc == 1) { 2138fae3551SRodney W. Grimes nfsdcnt = atoi(argv[0]); 2148fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2158fae3551SRodney W. Grimes warnx("nfsd count %d; reset to %d", DEFNFSDCNT); 2168fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 2178fae3551SRodney W. Grimes } 2188fae3551SRodney W. Grimes } 2198fae3551SRodney W. Grimes 2208fae3551SRodney W. Grimes if (debug == 0) { 2218fae3551SRodney W. Grimes daemon(0, 0); 2228fae3551SRodney W. Grimes (void)signal(SIGHUP, SIG_IGN); 2238fae3551SRodney W. Grimes (void)signal(SIGINT, SIG_IGN); 2248fae3551SRodney W. Grimes (void)signal(SIGQUIT, SIG_IGN); 2258fae3551SRodney W. Grimes (void)signal(SIGSYS, nonfs); 2268fae3551SRodney W. Grimes (void)signal(SIGTERM, SIG_IGN); 2278fae3551SRodney W. Grimes } 2288fae3551SRodney W. Grimes (void)signal(SIGCHLD, reapchild); 2298fae3551SRodney W. Grimes 2308fae3551SRodney W. Grimes if (reregister) { 2318fae3551SRodney W. Grimes if (udpflag && 2328fae3551SRodney W. Grimes !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) 2338fae3551SRodney W. Grimes err(1, "can't register with portmap for UDP."); 2348fae3551SRodney W. Grimes if (tcpflag && 2358fae3551SRodney W. Grimes !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) 2368fae3551SRodney W. Grimes err(1, "can't register with portmap for TCP."); 2378fae3551SRodney W. Grimes exit(0); 2388fae3551SRodney W. Grimes } 2398fae3551SRodney W. Grimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 2408fae3551SRodney W. Grimes 2418fae3551SRodney W. Grimes for (i = 0; i < nfsdcnt; i++) { 2428fae3551SRodney W. Grimes switch (fork()) { 2438fae3551SRodney W. Grimes case -1: 2448fae3551SRodney W. Grimes syslog(LOG_ERR, "fork: %m"); 2458fae3551SRodney W. Grimes exit (1); 2468fae3551SRodney W. Grimes case 0: 2478fae3551SRodney W. Grimes break; 2488fae3551SRodney W. Grimes default: 2498fae3551SRodney W. Grimes continue; 2508fae3551SRodney W. Grimes } 2518fae3551SRodney W. Grimes 2528fae3551SRodney W. Grimes setproctitle("nfsd-srv"); 2538fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD; 2548fae3551SRodney W. Grimes nsd.nsd_nfsd = NULL; 2558fae3551SRodney W. Grimes #ifdef KERBEROS 2568fae3551SRodney W. Grimes nsd.nsd_authstr = (char *)kt.dat; 2578fae3551SRodney W. Grimes #endif 2588fae3551SRodney W. Grimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 2598fae3551SRodney W. Grimes if (errno != ENEEDAUTH) { 2608fae3551SRodney W. Grimes syslog(LOG_ERR, "nfssvc: %m"); 2618fae3551SRodney W. Grimes exit(1); 2628fae3551SRodney W. Grimes } 2638fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 2648fae3551SRodney W. Grimes #ifdef KERBEROS 2658fae3551SRodney W. Grimes kt.length = nsd.nsd_authlen; 2668fae3551SRodney W. Grimes kt.mbz = 0; 2678fae3551SRodney W. Grimes (void)strcpy(inst, "*"); 2688fae3551SRodney W. Grimes if (krb_rd_req(&kt, "rcmd", 2698fae3551SRodney W. Grimes inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK && 2708fae3551SRodney W. Grimes krb_kntoln(&auth, lnam) == KSUCCESS && 2718fae3551SRodney W. Grimes (pwd = getpwnam(lnam)) != NULL) { 2728fae3551SRodney W. Grimes cr = &nsd.nsd_cr; 2738fae3551SRodney W. Grimes cr->cr_uid = pwd->pw_uid; 2748fae3551SRodney W. Grimes cr->cr_groups[0] = pwd->pw_gid; 2758fae3551SRodney W. Grimes cr->cr_ngroups = 1; 2768fae3551SRodney W. Grimes setgrent(); 2778fae3551SRodney W. Grimes while ((grp = getgrent()) != NULL) { 2788fae3551SRodney W. Grimes if (grp->gr_gid == cr->cr_groups[0]) 2798fae3551SRodney W. Grimes continue; 2808fae3551SRodney W. Grimes for (cpp = grp->gr_mem; 2818fae3551SRodney W. Grimes *cpp != NULL; ++cpp) 2828fae3551SRodney W. Grimes if (!strcmp(*cpp, lnam)) 2838fae3551SRodney W. Grimes break; 2848fae3551SRodney W. Grimes if (*cpp == NULL) 2858fae3551SRodney W. Grimes continue; 2868fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] 2878fae3551SRodney W. Grimes = grp->gr_gid; 2888fae3551SRodney W. Grimes if (cr->cr_ngroups == NGROUPS) 2898fae3551SRodney W. Grimes break; 2908fae3551SRodney W. Grimes } 2918fae3551SRodney W. Grimes endgrent(); 2928fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 2938fae3551SRodney W. Grimes } 2948fae3551SRodney W. Grimes #endif /* KERBEROS */ 2958fae3551SRodney W. Grimes } 2968fae3551SRodney W. Grimes exit(0); 2978fae3551SRodney W. Grimes } 2988fae3551SRodney W. Grimes 2998fae3551SRodney W. Grimes /* If we are serving udp, set up the socket. */ 3008fae3551SRodney W. Grimes if (udpflag) { 3018fae3551SRodney W. Grimes if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 3028fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create udp socket"); 3038fae3551SRodney W. Grimes exit(1); 3048fae3551SRodney W. Grimes } 3058fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 3068fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3078fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 3088fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 3098fae3551SRodney W. Grimes if (bind(sock, 3108fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { 3118fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind udp addr"); 3128fae3551SRodney W. Grimes exit(1); 3138fae3551SRodney W. Grimes } 3148fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 3158fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register with udp portmap"); 3168fae3551SRodney W. Grimes exit(1); 3178fae3551SRodney W. Grimes } 3188fae3551SRodney W. Grimes nfsdargs.sock = sock; 3198fae3551SRodney W. Grimes nfsdargs.name = NULL; 3208fae3551SRodney W. Grimes nfsdargs.namelen = 0; 3218fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 3228fae3551SRodney W. Grimes syslog(LOG_ERR, "can't Add UDP socket"); 3238fae3551SRodney W. Grimes exit(1); 3248fae3551SRodney W. Grimes } 3258fae3551SRodney W. Grimes (void)close(sock); 3268fae3551SRodney W. Grimes } 3278fae3551SRodney W. Grimes 3288fae3551SRodney W. Grimes #ifdef ISO 3298fae3551SRodney W. Grimes /* If we are serving cltp, set up the socket. */ 3308fae3551SRodney W. Grimes if (cltpflag) { 3318fae3551SRodney W. Grimes if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { 3328fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create cltp socket"); 3338fae3551SRodney W. Grimes exit(1); 3348fae3551SRodney W. Grimes } 3358fae3551SRodney W. Grimes memset(&isoaddr, 0, sizeof(isoaddr)); 3368fae3551SRodney W. Grimes isoaddr.siso_family = AF_ISO; 3378fae3551SRodney W. Grimes isoaddr.siso_tlen = 2; 3388fae3551SRodney W. Grimes cp = TSEL(&isoaddr); 3398fae3551SRodney W. Grimes *cp++ = (NFS_PORT >> 8); 3408fae3551SRodney W. Grimes *cp = (NFS_PORT & 0xff); 3418fae3551SRodney W. Grimes isoaddr.siso_len = sizeof(isoaddr); 3428fae3551SRodney W. Grimes if (bind(sock, 3438fae3551SRodney W. Grimes (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { 3448fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind cltp addr"); 3458fae3551SRodney W. Grimes exit(1); 3468fae3551SRodney W. Grimes } 3478fae3551SRodney W. Grimes #ifdef notyet 3488fae3551SRodney W. Grimes /* 3498fae3551SRodney W. Grimes * XXX 3508fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 3518fae3551SRodney W. Grimes * portmap. 3528fae3551SRodney W. Grimes */ 3538fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 3548fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register with udp portmap"); 3558fae3551SRodney W. Grimes exit(1); 3568fae3551SRodney W. Grimes } 3578fae3551SRodney W. Grimes #endif /* notyet */ 3588fae3551SRodney W. Grimes nfsdargs.sock = sock; 3598fae3551SRodney W. Grimes nfsdargs.name = NULL; 3608fae3551SRodney W. Grimes nfsdargs.namelen = 0; 3618fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 3628fae3551SRodney W. Grimes syslog(LOG_ERR, "can't add UDP socket"); 3638fae3551SRodney W. Grimes exit(1); 3648fae3551SRodney W. Grimes } 3658fae3551SRodney W. Grimes close(sock); 3668fae3551SRodney W. Grimes } 3678fae3551SRodney W. Grimes #endif /* ISO */ 3688fae3551SRodney W. Grimes 3698fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tcp connections. */ 3708fae3551SRodney W. Grimes on = 1; 3718fae3551SRodney W. Grimes FD_ZERO(&sockbits); 3728fae3551SRodney W. Grimes connect_type_cnt = 0; 3738fae3551SRodney W. Grimes if (tcpflag) { 3748fae3551SRodney W. Grimes if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 3758fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tcp socket"); 3768fae3551SRodney W. Grimes exit(1); 3778fae3551SRodney W. Grimes } 3788fae3551SRodney W. Grimes if (setsockopt(tcpsock, 3798fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 3808fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 3818fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 3828fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 3838fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 3848fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 3858fae3551SRodney W. Grimes if (bind(tcpsock, 3868fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 3878fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tcp addr"); 3888fae3551SRodney W. Grimes exit(1); 3898fae3551SRodney W. Grimes } 3908fae3551SRodney W. Grimes if (listen(tcpsock, 5) < 0) { 3918fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 3928fae3551SRodney W. Grimes exit(1); 3938fae3551SRodney W. Grimes } 3948fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 3958fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 3968fae3551SRodney W. Grimes exit(1); 3978fae3551SRodney W. Grimes } 3988fae3551SRodney W. Grimes FD_SET(tcpsock, &sockbits); 3998fae3551SRodney W. Grimes maxsock = tcpsock; 4008fae3551SRodney W. Grimes connect_type_cnt++; 4018fae3551SRodney W. Grimes } 4028fae3551SRodney W. Grimes 4038fae3551SRodney W. Grimes #ifdef notyet 4048fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tp4 connections. */ 4058fae3551SRodney W. Grimes if (tp4flag) { 4068fae3551SRodney W. Grimes if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { 4078fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tp4 socket"); 4088fae3551SRodney W. Grimes exit(1); 4098fae3551SRodney W. Grimes } 4108fae3551SRodney W. Grimes if (setsockopt(tp4sock, 4118fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4128fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4138fae3551SRodney W. Grimes memset(&isoaddr, 0, sizeof(isoaddr)); 4148fae3551SRodney W. Grimes isoaddr.siso_family = AF_ISO; 4158fae3551SRodney W. Grimes isoaddr.siso_tlen = 2; 4168fae3551SRodney W. Grimes cp = TSEL(&isoaddr); 4178fae3551SRodney W. Grimes *cp++ = (NFS_PORT >> 8); 4188fae3551SRodney W. Grimes *cp = (NFS_PORT & 0xff); 4198fae3551SRodney W. Grimes isoaddr.siso_len = sizeof(isoaddr); 4208fae3551SRodney W. Grimes if (bind(tp4sock, 4218fae3551SRodney W. Grimes (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { 4228fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tp4 addr"); 4238fae3551SRodney W. Grimes exit(1); 4248fae3551SRodney W. Grimes } 4258fae3551SRodney W. Grimes if (listen(tp4sock, 5) < 0) { 4268fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 4278fae3551SRodney W. Grimes exit(1); 4288fae3551SRodney W. Grimes } 4298fae3551SRodney W. Grimes /* 4308fae3551SRodney W. Grimes * XXX 4318fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 4328fae3551SRodney W. Grimes * portmap. 4338fae3551SRodney W. Grimes */ 4348fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 4358fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 4368fae3551SRodney W. Grimes exit(1); 4378fae3551SRodney W. Grimes } 4388fae3551SRodney W. Grimes FD_SET(tp4sock, &sockbits); 4398fae3551SRodney W. Grimes maxsock = tp4sock; 4408fae3551SRodney W. Grimes connect_type_cnt++; 4418fae3551SRodney W. Grimes } 4428fae3551SRodney W. Grimes 4438fae3551SRodney W. Grimes /* Now set up the master server socket waiting for tpip connections. */ 4448fae3551SRodney W. Grimes if (tpipflag) { 4458fae3551SRodney W. Grimes if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { 4468fae3551SRodney W. Grimes syslog(LOG_ERR, "can't create tpip socket"); 4478fae3551SRodney W. Grimes exit(1); 4488fae3551SRodney W. Grimes } 4498fae3551SRodney W. Grimes if (setsockopt(tpipsock, 4508fae3551SRodney W. Grimes SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) 4518fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); 4528fae3551SRodney W. Grimes inetaddr.sin_family = AF_INET; 4538fae3551SRodney W. Grimes inetaddr.sin_addr.s_addr = INADDR_ANY; 4548fae3551SRodney W. Grimes inetaddr.sin_port = htons(NFS_PORT); 4558fae3551SRodney W. Grimes inetaddr.sin_len = sizeof(inetaddr); 4568fae3551SRodney W. Grimes if (bind(tpipsock, 4578fae3551SRodney W. Grimes (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { 4588fae3551SRodney W. Grimes syslog(LOG_ERR, "can't bind tcp addr"); 4598fae3551SRodney W. Grimes exit(1); 4608fae3551SRodney W. Grimes } 4618fae3551SRodney W. Grimes if (listen(tpipsock, 5) < 0) { 4628fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 4638fae3551SRodney W. Grimes exit(1); 4648fae3551SRodney W. Grimes } 4658fae3551SRodney W. Grimes /* 4668fae3551SRodney W. Grimes * XXX 4678fae3551SRodney W. Grimes * Someday this should probably use "rpcbind", the son of 4688fae3551SRodney W. Grimes * portmap. 4698fae3551SRodney W. Grimes */ 4708fae3551SRodney W. Grimes if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 4718fae3551SRodney W. Grimes syslog(LOG_ERR, "can't register tcp with portmap"); 4728fae3551SRodney W. Grimes exit(1); 4738fae3551SRodney W. Grimes } 4748fae3551SRodney W. Grimes FD_SET(tpipsock, &sockbits); 4758fae3551SRodney W. Grimes maxsock = tpipsock; 4768fae3551SRodney W. Grimes connect_type_cnt++; 4778fae3551SRodney W. Grimes } 4788fae3551SRodney W. Grimes #endif /* notyet */ 4798fae3551SRodney W. Grimes 4808fae3551SRodney W. Grimes if (connect_type_cnt == 0) 4818fae3551SRodney W. Grimes exit(0); 4828fae3551SRodney W. Grimes 4838fae3551SRodney W. Grimes setproctitle("nfsd-master"); 4848fae3551SRodney W. Grimes 4858fae3551SRodney W. Grimes /* 4868fae3551SRodney W. Grimes * Loop forever accepting connections and passing the sockets 4878fae3551SRodney W. Grimes * into the kernel for the mounts. 4888fae3551SRodney W. Grimes */ 4898fae3551SRodney W. Grimes for (;;) { 4908fae3551SRodney W. Grimes ready = sockbits; 4918fae3551SRodney W. Grimes if (connect_type_cnt > 1) { 4928fae3551SRodney W. Grimes if (select(maxsock + 1, 4938fae3551SRodney W. Grimes &ready, NULL, NULL, NULL) < 1) { 4948fae3551SRodney W. Grimes syslog(LOG_ERR, "select failed: %m"); 4958fae3551SRodney W. Grimes exit(1); 4968fae3551SRodney W. Grimes } 4978fae3551SRodney W. Grimes } 4988fae3551SRodney W. Grimes if (tcpflag && FD_ISSET(tcpsock, &ready)) { 4998fae3551SRodney W. Grimes len = sizeof(inetpeer); 5008fae3551SRodney W. Grimes if ((msgsock = accept(tcpsock, 5018fae3551SRodney W. Grimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5028fae3551SRodney W. Grimes syslog(LOG_ERR, "accept failed: %m"); 5038fae3551SRodney W. Grimes exit(1); 5048fae3551SRodney W. Grimes } 5058fae3551SRodney W. Grimes memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); 5068fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 5078fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5088fae3551SRodney W. Grimes syslog(LOG_ERR, 5098fae3551SRodney W. Grimes "setsockopt SO_KEEPALIVE: %m"); 5108fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 5118fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&inetpeer; 5128fae3551SRodney W. Grimes nfsdargs.namelen = sizeof(inetpeer); 5138fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5148fae3551SRodney W. Grimes (void)close(msgsock); 5158fae3551SRodney W. Grimes } 5168fae3551SRodney W. Grimes #ifdef notyet 5178fae3551SRodney W. Grimes if (tp4flag && FD_ISSET(tp4sock, &ready)) { 5188fae3551SRodney W. Grimes len = sizeof(isopeer); 5198fae3551SRodney W. Grimes if ((msgsock = accept(tp4sock, 5208fae3551SRodney W. Grimes (struct sockaddr *)&isopeer, &len)) < 0) { 5218fae3551SRodney W. Grimes syslog(LOG_ERR, "accept failed: %m"); 5228fae3551SRodney W. Grimes exit(1); 5238fae3551SRodney W. Grimes } 5248fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 5258fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5268fae3551SRodney W. Grimes syslog(LOG_ERR, 5278fae3551SRodney W. Grimes "setsockopt SO_KEEPALIVE: %m"); 5288fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 5298fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&isopeer; 5308fae3551SRodney W. Grimes nfsdargs.namelen = len; 5318fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5328fae3551SRodney W. Grimes (void)close(msgsock); 5338fae3551SRodney W. Grimes } 5348fae3551SRodney W. Grimes if (tpipflag && FD_ISSET(tpipsock, &ready)) { 5358fae3551SRodney W. Grimes len = sizeof(inetpeer); 5368fae3551SRodney W. Grimes if ((msgsock = accept(tpipsock, 5378fae3551SRodney W. Grimes (struct sockaddr *)&inetpeer, &len)) < 0) { 5388fae3551SRodney W. Grimes syslog(LOG_ERR, "Accept failed: %m"); 5398fae3551SRodney W. Grimes exit(1); 5408fae3551SRodney W. Grimes } 5418fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 5428fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 5438fae3551SRodney W. Grimes syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); 5448fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 5458fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&inetpeer; 5468fae3551SRodney W. Grimes nfsdargs.namelen = len; 5478fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 5488fae3551SRodney W. Grimes (void)close(msgsock); 5498fae3551SRodney W. Grimes } 5508fae3551SRodney W. Grimes #endif /* notyet */ 5518fae3551SRodney W. Grimes } 5528fae3551SRodney W. Grimes } 5538fae3551SRodney W. Grimes 5548fae3551SRodney W. Grimes void 5558fae3551SRodney W. Grimes usage() 5568fae3551SRodney W. Grimes { 5578fae3551SRodney W. Grimes (void)fprintf(stderr, "nfsd %s\n", USAGE); 5588fae3551SRodney W. Grimes exit(1); 5598fae3551SRodney W. Grimes } 5608fae3551SRodney W. Grimes 5618fae3551SRodney W. Grimes void 5628fae3551SRodney W. Grimes nonfs(signo) 5638fae3551SRodney W. Grimes int signo; 5648fae3551SRodney W. Grimes { 5658fae3551SRodney W. Grimes syslog(LOG_ERR, "missing system call: NFS not available."); 5668fae3551SRodney W. Grimes } 5678fae3551SRodney W. Grimes 5688fae3551SRodney W. Grimes void 5698fae3551SRodney W. Grimes reapchild(signo) 5708fae3551SRodney W. Grimes int signo; 5718fae3551SRodney W. Grimes { 5728fae3551SRodney W. Grimes 5738fae3551SRodney W. Grimes while (wait3(NULL, WNOHANG, NULL)); 5748fae3551SRodney W. Grimes } 5758fae3551SRodney W. Grimes 5768fae3551SRodney W. Grimes void 5778fae3551SRodney W. Grimes setproctitle(a) 5788fae3551SRodney W. Grimes char *a; 5798fae3551SRodney W. Grimes { 5808fae3551SRodney W. Grimes register char *cp; 5818fae3551SRodney W. Grimes char buf[80]; 5828fae3551SRodney W. Grimes 5838fae3551SRodney W. Grimes cp = Argv[0]; 5848fae3551SRodney W. Grimes (void)snprintf(buf, sizeof(buf), "%s", a); 5858fae3551SRodney W. Grimes (void)strncpy(cp, buf, LastArg - cp); 5868fae3551SRodney W. Grimes cp += strlen(cp); 5878fae3551SRodney W. Grimes while (cp < LastArg) 5888fae3551SRodney W. Grimes *cp++ = ' '; 5898fae3551SRodney W. Grimes } 590