4 * This is the user level part of nfsd. This is very primitive, because
5 * all the work is now done in the kernel module.
7 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
31 * IPv6 support for nfsd was finished before some of the other daemons (mountd
32 * and statd in particular). That could be a problem in the future if someone
33 * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For
34 * now, hardcode the IPv6 switch into the off position until the other daemons
39 static void usage(const char *);
41 static struct option longopts[] =
43 { "host", 1, 0, 'H' },
44 { "help", 0, 0, 'h' },
45 { "no-nfs-version", 1, 0, 'N' },
46 { "no-tcp", 0, 0, 'T' },
47 { "no-udp", 0, 0, 'U' },
48 { "port", 1, 0, 'P' },
49 { "port", 1, 0, 'p' },
50 { "debug", 0, 0, 'd' },
51 { "syslog", 0, 0, 's' },
55 /* given a family and ctlbits, disable any that aren't listed in netconfig */
58 nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
60 struct netconfig *nconf;
61 unsigned int *famproto;
64 xlog(D_GENERAL, "Checking netconfig for visible protocols.");
66 handle = setnetconfig();
67 while((nconf = getnetconfig(handle))) {
68 if (!(nconf->nc_flag & NC_VISIBLE))
71 if (!strcmp(nconf->nc_protofmly, NC_INET))
73 else if (!strcmp(nconf->nc_protofmly, NC_INET6))
78 if (!strcmp(nconf->nc_proto, NC_TCP))
79 NFSCTL_TCPSET(*famproto);
80 else if (!strcmp(nconf->nc_proto, NC_UDP))
81 NFSCTL_UDPSET(*famproto);
83 xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
89 #else /* HAVE_LIBTIRPC */
91 nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
93 /* Enable all IPv4 protocols if no TIRPC support */
94 *proto4 = NFSCTL_ALLBITS;
97 #endif /* HAVE_LIBTIRPC */
100 main(int argc, char **argv)
102 int count = 1, c, error = 0, portnum = 0, fd, found_one;
103 char *p, *progname, *port;
106 int minorvers4 = NFSD_MAXMINORVERS4; /* nfsv4 minor version */
107 unsigned int versbits = NFSCTL_ALLBITS;
108 unsigned int protobits = NFSCTL_ALLBITS;
109 unsigned int proto4 = 0;
110 unsigned int proto6 = 0;
112 progname = strdup(basename(argv[0]));
114 fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
118 port = strdup("nfs");
120 fprintf(stderr, "%s: unable to allocate memory.\n", progname);
127 while ((c = getopt_long(argc, argv, "dH:hN:p:P:sTU", longopts, NULL)) != EOF) {
130 xlog_config(D_ALL, 1);
134 * for now, this only handles one -H option. Use the
135 * last one specified.
138 haddr = strdup(optarg);
140 fprintf(stderr, "%s: unable to allocate "
141 "memory.\n", progname);
145 case 'P': /* XXX for nfs-server compatibility */
147 /* only the last -p option has any effect */
148 portnum = atoi(optarg);
149 if (portnum <= 0 || portnum > 65535) {
150 fprintf(stderr, "%s: bad port number: %s\n",
155 port = strdup(optarg);
157 fprintf(stderr, "%s: unable to allocate "
158 "memory.\n", progname);
163 switch((c = strtol(optarg, &p, 0))) {
166 minorvers4 = -atoi(p + 1);
171 NFSCTL_VERUNSET(versbits, c);
174 fprintf(stderr, "%s: Unsupported version\n", optarg);
183 NFSCTL_TCPUNSET(protobits);
186 NFSCTL_UDPUNSET(protobits);
189 fprintf(stderr, "Invalid argument: '%c'\n", c);
196 if ((count = atoi(argv[optind])) < 0) {
197 /* insane # of servers */
199 "%s: invalid server count (%d), using 1\n",
202 } else if (count == 0) {
204 * don't bother setting anything else if the threads
205 * are coming down anyway.
214 nfsd_enable_protos(&proto4, &proto6);
216 if (!NFSCTL_TCPISSET(protobits)) {
217 NFSCTL_TCPUNSET(proto4);
218 NFSCTL_TCPUNSET(proto6);
221 if (!NFSCTL_UDPISSET(protobits)) {
222 NFSCTL_UDPUNSET(proto4);
223 NFSCTL_UDPUNSET(proto6);
226 /* make sure that at least one version is enabled */
228 for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
229 if (NFSCTL_VERISSET(versbits, c))
233 xlog(L_ERROR, "no version specified");
237 if (NFSCTL_VERISSET(versbits, 4) &&
238 !NFSCTL_TCPISSET(proto4) &&
239 !NFSCTL_TCPISSET(proto6)) {
240 xlog(L_ERROR, "version 4 requires the TCP protocol");
244 if (chdir(NFS_STATEDIR)) {
245 xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
249 /* can only change number of threads if nfsd is already up */
250 if (nfssvc_inuse()) {
256 * must set versions before the fd's so that the right versions get
257 * registered with rpcbind. Note that on older kernels w/o the right
258 * interfaces, these are a no-op.
260 nfssvc_setvers(versbits, minorvers4);
262 error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
266 #ifdef IPV6_SUPPORTED
267 error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port);
270 #endif /* IPV6_SUPPORTED */
273 /* don't start any threads if unable to hand off any sockets */
275 xlog(L_ERROR, "unable to set any sockets for nfsd");
282 * Some kernels let nfsd kernel threads inherit open files
283 * from the program that spawns them (i.e. us). So close
284 * everything before spawning kernel threads. --Chip
286 fd = open("/dev/null", O_RDWR);
288 xlog(L_ERROR, "Unable to open /dev/null: %m");
290 /* switch xlog output to syslog since stderr is being closed */
299 if ((error = nfssvc_threads(portnum, count)) < 0)
300 xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
309 usage(const char *prog)
311 fprintf(stderr, "Usage:\n"
312 "%s [-d|--debug] [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] nrservs\n",