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