X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fnfsd%2Fnfsd.c;h=1589a9f39dbac530259b298184c3e4738f696168;hp=3a22370a27540c81979656e7fcf97dde85c4ca55;hb=6f25394cb5651e7e44cc3fc0b2b4b2ccba8c3625;hpb=8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9 diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c index 3a22370..1589a9f 100644 --- a/utils/nfsd/nfsd.c +++ b/utils/nfsd/nfsd.c @@ -7,62 +7,197 @@ * Copyright (C) 1995, 1996 Olaf Kirch */ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif #include #include +#include +#include +#include +#include #include +#include +#include +#include +#include + #include "nfslib.h" +#include "nfssvc.h" +#include "xlog.h" static void usage(const char *); +static struct option longopts[] = +{ + { "host", 1, 0, 'H' }, + { "help", 0, 0, 'h' }, + { "no-nfs-version", 1, 0, 'N' }, + { "no-tcp", 0, 0, 'T' }, + { "no-udp", 0, 0, 'U' }, + { "port", 1, 0, 'P' }, + { "port", 1, 0, 'p' }, + { "debug", 0, 0, 'd' }, + { "syslog", 0, 0, 's' }, + { NULL, 0, 0, 0 } +}; +unsigned int protobits = NFSCTL_ALLBITS; +unsigned int versbits = NFSCTL_ALLBITS; +int minorvers4 = NFSD_MAXMINORVERS4; /* nfsv4 minor version */ +char *haddr = NULL; + int main(int argc, char **argv) { - int count = 1, c, error, port; + int count = 1, c, error, port, fd, found_one; + struct servent *ent; + struct hostent *hp; + char *p, *progname; - port = 2049; + ent = getservbyname ("nfs", "udp"); + if (ent != NULL) + port = ntohs (ent->s_port); + else + port = 2049; - /* FIXME: Check for nfs in /etc/services */ + progname = strdup(basename(argv[0])); + if (!progname) { + fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]); + exit(1); + } + + xlog_syslog(0); + xlog_stderr(1); - while ((c = getopt(argc, argv, "hp:P:")) != EOF) { + while ((c = getopt_long(argc, argv, "dH:hN:p:P:sTU", longopts, NULL)) != EOF) { switch(c) { + case 'd': + xlog_config(D_ALL, 1); + break; + case 'H': + if (inet_addr(optarg) != INADDR_NONE) { + haddr = strdup(optarg); + } else if ((hp = gethostbyname(optarg)) != NULL) { + haddr = inet_ntoa((*(struct in_addr*)(hp->h_addr_list[0]))); + } else { + fprintf(stderr, "%s: Unknown hostname: %s\n", + progname, optarg); + usage(progname); + } + break; case 'P': /* XXX for nfs-server compatibility */ case 'p': port = atoi(optarg); if (port <= 0 || port > 65535) { fprintf(stderr, "%s: bad port number: %s\n", - argv[0], optarg); - usage(argv [0]); + progname, optarg); + usage(progname); + } + break; + case 'N': + switch((c = strtol(optarg, &p, 0))) { + case 4: + if (*p == '.') { + minorvers4 = -atoi(p + 1); + break; + } + case 3: + case 2: + NFSCTL_VERUNSET(versbits, c); + break; + default: + fprintf(stderr, "%s: Unsupported version\n", optarg); + exit(1); } break; + case 's': + xlog_syslog(1); + xlog_stderr(0); + break; + case 'T': + NFSCTL_TCPUNSET(protobits); + break; + case 'U': + NFSCTL_UDPUNSET(protobits); break; - case 'h': default: - usage(argv[0]); + fprintf(stderr, "Invalid argument: '%c'\n", c); + case 'h': + usage(progname); } } + xlog_open(progname); + + /* + * Do some sanity checking, if the ctlbits are set + */ + if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) { + xlog(L_ERROR, "invalid protocol specified"); + exit(1); + } + found_one = 0; + for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) { + if (NFSCTL_VERISSET(versbits, c)) + found_one = 1; + } + if (!found_one) { + xlog(L_ERROR, "no version specified"); + exit(1); + } + + if (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(protobits)) { + xlog(L_ERROR, "version 4 requires the TCP protocol"); + exit(1); + } + if (haddr == NULL) { + struct in_addr in = {INADDR_ANY}; + haddr = strdup(inet_ntoa(in)); + } + + if (chdir(NFS_STATEDIR)) { + xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR); + exit(1); + } + if (optind < argc) { if ((count = atoi(argv[optind])) < 0) { /* insane # of servers */ - fprintf(stderr, - "%s: invalid server count (%d), using 1\n", - argv[0], count); + xlog(L_ERROR, "invalid server count (%d), using 1", + count); count = 1; } } + /* KLUDGE ALERT: + Some kernels let nfsd kernel threads inherit open files + from the program that spawns them (i.e. us). So close + everything before spawning kernel threads. --Chip */ + fd = open("/dev/null", O_RDWR); + if (fd == -1) + xlog(L_ERROR, "Unable to open /dev/null: %m"); + else { + /* switch xlog output to syslog since stderr is being closed */ + xlog_syslog(1); + xlog_stderr(0); + (void) dup2(fd, 0); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + } + closeall(3); - if ((error = nfssvc(port, count)) < 0) - perror("nfssvc"); + if ((error = nfssvc(port, count, versbits, minorvers4, protobits, haddr)) < 0) + xlog(L_ERROR, "nfssvc: errno %d (%m)", errno); + free(progname); return (error != 0); } static void usage(const char *prog) { - fprintf(stderr, "usage:\n" - "%s nrservs\n", prog); + fprintf(stderr, "Usage:\n" + "%s [-d|--debug] [-H hostname] [-p|-P|--port port] [-N|--no-nfs-version version ] [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] nrservs\n", + prog); exit(2); }