1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 14 All rights reserved.\n"; 15 #endif not lint 16 17 #ifndef lint 18 static char sccsid[] = "@(#)nfsd.c 5.8 (Berkeley) 06/29/90"; 19 #endif not lint 20 21 #include <sys/types.h> 22 #include <sys/signal.h> 23 #include <sys/ioctl.h> 24 #include <sys/stat.h> 25 #include <sys/wait.h> 26 #include <sys/mount.h> 27 #include <sys/socket.h> 28 #include <sys/socketvar.h> 29 #include <stdio.h> 30 #include <syslog.h> 31 #include <fcntl.h> 32 #include <string.h> 33 #include <netdb.h> 34 #include <rpc/rpc.h> 35 #include <rpc/pmap_clnt.h> 36 #include <rpc/pmap_prot.h> 37 #include <nfs/rpcv2.h> 38 #include <nfs/nfsv2.h> 39 40 /* Global defs */ 41 #ifdef DEBUG 42 #define syslog(e, s) fprintf(stderr,(s)) 43 int debug = 1; 44 #else 45 int debug = 0; 46 #endif 47 struct hadr { 48 u_long ha_sad; 49 struct hadr *ha_next; 50 }; 51 struct hadr hphead; 52 53 /* 54 * Nfs server daemon mostly just a user context for nfssvc() 55 * 1 - do file descriptor and signal cleanup 56 * 2 - create server socket 57 * 3 - register socket with portmap 58 * For SOCK_DGRAM, just fork children and send them into the kernel 59 * by calling nfssvc() 60 * For connection based sockets, loop doing accepts. When you get a new socket 61 * from accept, fork a child that drops into the kernel via. nfssvc. 62 * This child will return from nfssvc when the connection is closed, so 63 * just shutdown() and exit(). 64 * The arguments are: 65 * -t - support tcp nfs clients 66 * -u - support udp nfs clients 67 */ 68 main(argc, argv) 69 int argc; 70 char **argv; 71 { 72 register int i; 73 register char *cp, *cp2; 74 register struct hadr *hp; 75 int udpcnt, sock, msgsock, tcpflag = 0, udpflag = 0, ret, len; 76 char opt; 77 union wait chldstat; 78 extern int optind; 79 extern char *optarg; 80 struct sockaddr_in saddr, msk, mtch, peername; 81 82 while ((opt = getopt(argc, argv, "t:u:")) != EOF) 83 switch (opt) { 84 case 't': 85 tcpflag++; 86 if (cp = index(optarg, ',')) { 87 *cp++ = '\0'; 88 msk.sin_addr.s_addr = inet_addr(optarg); 89 if (msk.sin_addr.s_addr == -1) 90 usage(); 91 if (cp2 = index(cp, ',')) 92 *cp2++ = '\0'; 93 mtch.sin_addr.s_addr = inet_addr(cp); 94 if (mtch.sin_addr.s_addr == -1) 95 usage(); 96 cp = cp2; 97 hphead.ha_next = (struct hadr *)0; 98 while (cp) { 99 if (cp2 = index(cp, ',')) 100 *cp2++ = '\0'; 101 hp = (struct hadr *) 102 malloc(sizeof (struct hadr)); 103 hp->ha_sad = inet_addr(cp); 104 if (hp->ha_sad == -1) 105 usage(); 106 hp->ha_next = hphead.ha_next; 107 hphead.ha_next = hp; 108 cp = cp2; 109 } 110 } else 111 usage(); 112 break; 113 case 'u': 114 udpflag++; 115 if (cp = index(optarg, ',')) { 116 *cp++ = '\0'; 117 msk.sin_addr.s_addr = inet_addr(optarg); 118 if (msk.sin_addr.s_addr == -1) 119 usage(); 120 if (cp2 = index(cp, ',')) 121 *cp2++ = '\0'; 122 mtch.sin_addr.s_addr = inet_addr(cp); 123 if (mtch.sin_addr.s_addr == -1) 124 usage(); 125 if (cp2) 126 udpcnt = atoi(cp2); 127 if (udpcnt < 1 || udpcnt > 20) 128 udpcnt = 1; 129 } else 130 usage(); 131 break; 132 default: 133 case '?': 134 usage(); 135 }; 136 if (optind == 1) { 137 if (argc > 1) 138 udpcnt = atoi(*++argv); 139 if (udpcnt < 1 || udpcnt > 20) 140 udpcnt = 1; 141 msk.sin_addr.s_addr = mtch.sin_addr.s_addr = 0; 142 udpflag++; 143 } 144 if (debug == 0) { 145 daemon(0, 0); 146 signal(SIGINT, SIG_IGN); 147 signal(SIGQUIT, SIG_IGN); 148 signal(SIGTERM, SIG_IGN); 149 signal(SIGHUP, SIG_IGN); 150 } 151 openlog("nfsd:", LOG_PID, LOG_DAEMON); 152 pmap_unset(RPCPROG_NFS, NFS_VER2); 153 if (udpflag) { 154 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 155 syslog(LOG_ERR, "Can't create socket"); 156 exit(1); 157 } 158 saddr.sin_family = AF_INET; 159 saddr.sin_addr.s_addr = INADDR_ANY; 160 saddr.sin_port = htons(NFS_PORT); 161 if (bind(sock, &saddr, sizeof(saddr)) < 0) { 162 syslog(LOG_ERR, "Can't bind addr"); 163 exit(1); 164 } 165 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { 166 syslog(LOG_ERR, "Can't register with portmap"); 167 exit(1); 168 } 169 170 /* 171 * Send the nfs datagram servers right down into the kernel 172 */ 173 for (i = 0; i < udpcnt; i++) 174 if (fork() == 0) { 175 ret = nfssvc(sock, &msk, sizeof(msk), 176 &mtch, sizeof(mtch)); 177 if (ret < 0) 178 syslog(LOG_ERR, "nfssvc() failed %m"); 179 exit(); 180 } 181 close(sock); 182 } 183 184 /* 185 * Now set up the master STREAM server waiting for tcp connections. 186 */ 187 if (tcpflag) { 188 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 189 syslog(LOG_ERR, "Can't create socket"); 190 exit(1); 191 } 192 saddr.sin_family = AF_INET; 193 saddr.sin_addr.s_addr = INADDR_ANY; 194 saddr.sin_port = htons(NFS_PORT); 195 if (bind(sock, &saddr, sizeof(saddr)) < 0) { 196 syslog(LOG_ERR, "Can't bind addr"); 197 exit(1); 198 } 199 if (listen(sock, 5) < 0) { 200 syslog(LOG_ERR, "Listen failed"); 201 exit(1); 202 } 203 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { 204 syslog(LOG_ERR, "Can't register with portmap"); 205 exit(1); 206 } 207 /* 208 * Loop forever accepting connections and sending the children 209 * into the kernel to service the mounts. 210 */ 211 for (;;) { 212 if ((msgsock = accept(sock, (struct sockaddr *)0, 213 (int *)0)) < 0) { 214 syslog(LOG_ERR, "Accept failed: %m"); 215 exit(1); 216 } 217 /* 218 * Grab child termination status' just so defuncts 219 * are not left lying about. 220 */ 221 while (wait3(&chldstat, WNOHANG, (struct rusage *)0)) 222 ; 223 len = sizeof(peername); 224 if (getsockname(msgsock, &peername, &len) < 0) { 225 syslog(LOG_ERR, "Getsockname failed\n"); 226 exit(1); 227 } 228 if ((peername.sin_addr.s_addr & msk.sin_addr.s_addr) 229 != mtch.sin_addr.s_addr) { 230 hp = hphead.ha_next; 231 while (hp) { 232 if (peername.sin_addr.s_addr == 233 hp->ha_sad) 234 break; 235 hp = hp->ha_next; 236 } 237 if (hp == NULL) { 238 shutdown(msgsock, 2); 239 close(msgsock); 240 continue; 241 } 242 } 243 if (fork() == 0) { 244 close(sock); 245 ret = nfssvc(msgsock, &msk, sizeof(msk), 246 &mtch, sizeof(mtch)); 247 shutdown(msgsock, 2); 248 if (ret < 0) 249 syslog(LOG_NOTICE, 250 "Nfssvc STREAM Failed"); 251 exit(); 252 } 253 close(msgsock); 254 } 255 } 256 } 257 258 usage() 259 { 260 fprintf(stderr, "nfsd [-t msk,mtch[,addrs]] [-u msk,mtch,numprocs]\n"); 261 exit(1); 262 } 263