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>
34 static void usage(const char *);
36 static struct option longopts[] =
38 { "host", 1, 0, 'H' },
39 { "help", 0, 0, 'h' },
40 { "no-nfs-version", 1, 0, 'N' },
41 { "nfs-version", 1, 0, 'V' },
42 { "no-tcp", 0, 0, 'T' },
43 { "no-udp", 0, 0, 'U' },
44 { "port", 1, 0, 'P' },
45 { "port", 1, 0, 'p' },
46 { "debug", 0, 0, 'd' },
47 { "syslog", 0, 0, 's' },
51 /* given a family and ctlbits, disable any that aren't listed in netconfig */
54 nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
56 struct netconfig *nconf;
57 unsigned int *famproto;
60 xlog(D_GENERAL, "Checking netconfig for visible protocols.");
62 handle = setnetconfig();
63 while((nconf = getnetconfig(handle))) {
64 if (!(nconf->nc_flag & NC_VISIBLE))
67 if (!strcmp(nconf->nc_protofmly, NC_INET))
69 else if (!strcmp(nconf->nc_protofmly, NC_INET6))
74 if (!strcmp(nconf->nc_proto, NC_TCP))
75 NFSCTL_TCPSET(*famproto);
76 else if (!strcmp(nconf->nc_proto, NC_UDP))
77 NFSCTL_UDPSET(*famproto);
79 xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
85 #else /* HAVE_LIBTIRPC */
87 nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
89 /* Enable all IPv4 protocols if no TIRPC support */
90 *proto4 = NFSCTL_ALLBITS;
93 #endif /* HAVE_LIBTIRPC */
96 main(int argc, char **argv)
98 int count = NFSD_NPROC, c, error = 0, portnum = 0, fd, found_one;
99 char *p, *progname, *port;
102 int minorvers41 = 0; /* nfsv4 minor version */
103 unsigned int versbits = NFSCTL_ALLBITS;
104 unsigned int protobits = NFSCTL_ALLBITS;
105 unsigned int proto4 = 0;
106 unsigned int proto6 = 0;
108 progname = strdup(basename(argv[0]));
110 fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
114 port = strdup("nfs");
116 fprintf(stderr, "%s: unable to allocate memory.\n", progname);
123 while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:sTU", longopts, NULL)) != EOF) {
126 xlog_config(D_ALL, 1);
130 * for now, this only handles one -H option. Use the
131 * last one specified.
134 haddr = strdup(optarg);
136 fprintf(stderr, "%s: unable to allocate "
137 "memory.\n", progname);
141 case 'P': /* XXX for nfs-server compatibility */
143 /* only the last -p option has any effect */
144 portnum = atoi(optarg);
145 if (portnum <= 0 || portnum > 65535) {
146 fprintf(stderr, "%s: bad port number: %s\n",
151 port = strdup(optarg);
153 fprintf(stderr, "%s: unable to allocate "
154 "memory.\n", progname);
159 switch((c = strtol(optarg, &p, 0))) {
164 fprintf(stderr, "%s: unsupported minor version\n", optarg);
172 NFSCTL_VERUNSET(versbits, c);
175 fprintf(stderr, "%s: Unsupported version\n", optarg);
180 switch((c = strtol(optarg, &p, 0))) {
185 fprintf(stderr, "%s: unsupported minor version\n", optarg);
193 NFSCTL_VERSET(versbits, c);
196 fprintf(stderr, "%s: Unsupported version\n", optarg);
205 NFSCTL_TCPUNSET(protobits);
208 NFSCTL_UDPUNSET(protobits);
211 fprintf(stderr, "Invalid argument: '%c'\n", c);
218 if ((count = atoi(argv[optind])) < 0) {
219 /* insane # of servers */
221 "%s: invalid server count (%d), using 1\n",
224 } else if (count == 0) {
226 * don't bother setting anything else if the threads
227 * are coming down anyway.
236 nfsd_enable_protos(&proto4, &proto6);
238 if (!NFSCTL_TCPISSET(protobits)) {
239 NFSCTL_TCPUNSET(proto4);
240 NFSCTL_TCPUNSET(proto6);
243 if (!NFSCTL_UDPISSET(protobits)) {
244 NFSCTL_UDPUNSET(proto4);
245 NFSCTL_UDPUNSET(proto6);
248 /* make sure that at least one version is enabled */
250 for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
251 if (NFSCTL_VERISSET(versbits, c))
255 xlog(L_ERROR, "no version specified");
259 if (NFSCTL_VERISSET(versbits, 4) &&
260 !NFSCTL_TCPISSET(proto4) &&
261 !NFSCTL_TCPISSET(proto6)) {
262 xlog(L_ERROR, "version 4 requires the TCP protocol");
266 if (chdir(NFS_STATEDIR)) {
267 xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
271 /* make sure nfsdfs is mounted if it's available */
272 nfssvc_mount_nfsdfs(progname);
274 /* can only change number of threads if nfsd is already up */
275 if (nfssvc_inuse()) {
281 * must set versions before the fd's so that the right versions get
282 * registered with rpcbind. Note that on older kernels w/o the right
283 * interfaces, these are a no-op.
285 nfssvc_setvers(versbits, minorvers41);
287 error = nfssvc_set_sockets(AF_INET, proto4, haddr, port);
291 #ifdef IPV6_SUPPORTED
292 error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port);
295 #endif /* IPV6_SUPPORTED */
298 /* don't start any threads if unable to hand off any sockets */
300 xlog(L_ERROR, "unable to set any sockets for nfsd");
307 * Some kernels let nfsd kernel threads inherit open files
308 * from the program that spawns them (i.e. us). So close
309 * everything before spawning kernel threads. --Chip
311 fd = open("/dev/null", O_RDWR);
313 xlog(L_ERROR, "Unable to open /dev/null: %m");
315 /* switch xlog output to syslog since stderr is being closed */
324 if ((error = nfssvc_threads(portnum, count)) < 0)
325 xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
334 usage(const char *prog)
336 fprintf(stderr, "Usage:\n"
337 "%s [-d|--debug] [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version] [-V|--nfs-version version] [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] nrservs\n",