add nsellength processing for GOSIP, default 1;
[unix-history] / usr / src / sbin / nfsd / nfsd.c
CommitLineData
e3ab21d9
KM
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 *
70ab3c27 8 * %sccs.include.redist.c%
e3ab21d9
KM
9 */
10
11#ifndef lint
12char 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
70ab3c27 18static char sccsid[] = "@(#)nfsd.c 5.6 (Berkeley) %G%";
e3ab21d9
KM
19#endif not lint
20
e3ab21d9 21#include <sys/types.h>
38dde0cd 22#include <sys/signal.h>
e3ab21d9
KM
23#include <sys/ioctl.h>
24#include <sys/stat.h>
af62051f 25#include <sys/wait.h>
e3ab21d9
KM
26#include <sys/mount.h>
27#include <sys/socket.h>
28#include <sys/socketvar.h>
38dde0cd
KB
29#include <stdio.h>
30#include <syslog.h>
31#include <fcntl.h>
32#include <string.h>
e3ab21d9
KM
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))
43int debug = 1;
44#else
45int debug = 0;
46#endif
af62051f
KM
47struct hadr {
48 u_long ha_sad;
49 struct hadr *ha_next;
50};
51struct hadr hphead;
e3ab21d9
KM
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
af62051f
KM
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
e3ab21d9
KM
67 */
68main(argc, argv)
69 int argc;
af62051f 70 char **argv;
e3ab21d9
KM
71{
72 register int i;
af62051f
KM
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;
e3ab21d9 81
af62051f
KM
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 }
e3ab21d9
KM
144 if (debug == 0) {
145 if (fork())
146 exit(0);
147 { int s;
148 for (s = 0; s < 10; s++)
149 (void) close(s);
150 }
1b3a818d
KM
151 (void) open("/dev/null", O_RDONLY);
152 (void) open("/dev/null", O_WRONLY);
153 (void) dup2(1, 2);
e3ab21d9
KM
154 { int tt = open("/dev/tty", O_RDWR);
155 if (tt > 0) {
156 ioctl(tt, TIOCNOTTY, (char *)0);
157 close(tt);
158 }
159 }
160 (void) setpgrp(0, 0);
161 signal(SIGTSTP, SIG_IGN);
162 signal(SIGTTIN, SIG_IGN);
163 signal(SIGTTOU, SIG_IGN);
164 signal(SIGINT, SIG_IGN);
165 signal(SIGQUIT, SIG_IGN);
166 signal(SIGTERM, SIG_IGN);
167 signal(SIGHUP, SIG_IGN);
168 }
169 openlog("nfsd:", LOG_PID, LOG_DAEMON);
e3ab21d9 170 pmap_unset(RPCPROG_NFS, NFS_VER2);
af62051f
KM
171 if (udpflag) {
172 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
173 syslog(LOG_ERR, "Can't create socket");
174 exit(1);
175 }
176 saddr.sin_family = AF_INET;
177 saddr.sin_addr.s_addr = INADDR_ANY;
178 saddr.sin_port = htons(NFS_PORT);
179 if (bind(sock, &saddr, sizeof(saddr)) < 0) {
180 syslog(LOG_ERR, "Can't bind addr");
181 exit(1);
182 }
183 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
184 syslog(LOG_ERR, "Can't register with portmap");
185 exit(1);
186 }
187
188 /*
189 * Send the nfs datagram servers right down into the kernel
190 */
191 for (i = 0; i < udpcnt; i++)
192 if (fork() == 0) {
193 ret = nfssvc(sock, &msk, sizeof(msk),
194 &mtch, sizeof(mtch));
195 if (ret < 0)
196 syslog(LOG_ERR, "nfssvc() failed %m");
197 exit();
198 }
199 close(sock);
e3ab21d9 200 }
af62051f
KM
201
202 /*
203 * Now set up the master STREAM server waiting for tcp connections.
204 */
205 if (tcpflag) {
206 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
207 syslog(LOG_ERR, "Can't create socket");
208 exit(1);
209 }
210 saddr.sin_family = AF_INET;
211 saddr.sin_addr.s_addr = INADDR_ANY;
212 saddr.sin_port = htons(NFS_PORT);
213 if (bind(sock, &saddr, sizeof(saddr)) < 0) {
214 syslog(LOG_ERR, "Can't bind addr");
215 exit(1);
216 }
217 if (listen(sock, 5) < 0) {
218 syslog(LOG_ERR, "Listen failed");
219 exit(1);
220 }
221 if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
222 syslog(LOG_ERR, "Can't register with portmap");
223 exit(1);
224 }
225 /*
226 * Loop forever accepting connections and sending the children
227 * into the kernel to service the mounts.
228 */
229 for (;;) {
230 if ((msgsock = accept(sock, (struct sockaddr *)0,
231 (int *)0)) < 0) {
232 syslog(LOG_ERR, "Accept failed: %m");
233 exit(1);
234 }
235 /*
236 * Grab child termination status' just so defuncts
237 * are not left lying about.
238 */
239 while (wait3(&chldstat, WNOHANG, (struct rusage *)0))
240 ;
241 len = sizeof(peername);
242 if (getsockname(msgsock, &peername, &len) < 0) {
243 syslog(LOG_ERR, "Getsockname failed\n");
244 exit(1);
245 }
246 if ((peername.sin_addr.s_addr & msk.sin_addr.s_addr)
247 != mtch.sin_addr.s_addr) {
248 hp = hphead.ha_next;
249 while (hp) {
250 if (peername.sin_addr.s_addr ==
251 hp->ha_sad)
252 break;
253 hp = hp->ha_next;
254 }
255 if (hp == NULL) {
256 shutdown(msgsock, 2);
257 close(msgsock);
258 continue;
259 }
260 }
261 if (fork() == 0) {
262 close(sock);
263 ret = nfssvc(msgsock, &msk, sizeof(msk),
264 &mtch, sizeof(mtch));
265 shutdown(msgsock, 2);
266 if (ret < 0)
267 syslog(LOG_ERR, "Nfssvc STREAM Failed");
268 exit();
269 }
270 close(msgsock);
271 }
1b3a818d 272 }
af62051f
KM
273}
274
275usage()
276{
277 fprintf(stderr, "nfsd [-t msk,mtch[,addrs]] [-u msk,mtch,numprocs]\n");
278 exit(1);
e3ab21d9 279}