X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fnfsd%2Fnfssvc.c;h=ea36399261b5d23f969269a141f0f6d67159ef67;hp=106f6e7621305c43b34bb713ee7287f1fae73405;hb=706bfd7c94d48659a1411fdef2a3a61d4719f1aa;hpb=094b26031a376050d8610d055eb01c7949ad6547 diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c index 106f6e7..ea36399 100644 --- a/utils/nfsd/nfssvc.c +++ b/utils/nfsd/nfssvc.c @@ -15,16 +15,22 @@ #include #include #include +#include #include #include #include +#include #include "nfslib.h" #include "xlog.h" -#define NFSD_PORTS_FILE "/proc/fs/nfsd/portlist" -#define NFSD_VERS_FILE "/proc/fs/nfsd/versions" -#define NFSD_THREAD_FILE "/proc/fs/nfsd/threads" +#ifndef NFSD_FS_DIR +#define NFSD_FS_DIR "/proc/fs/nfsd" +#endif + +#define NFSD_PORTS_FILE NFSD_FS_DIR "/portlist" +#define NFSD_VERS_FILE NFSD_FS_DIR "/versions" +#define NFSD_THREAD_FILE NFSD_FS_DIR "/threads" /* * declaring a common static scratch buffer here keeps us from having to @@ -34,6 +40,46 @@ */ char buf[128]; +/* + * Using the "new" interfaces for nfsd requires that /proc/fs/nfsd is + * actually mounted. Make an attempt to mount it here if it doesn't appear + * to be. If the mount attempt fails, no big deal -- fall back to using nfsctl + * instead. + */ +void +nfssvc_mount_nfsdfs(char *progname) +{ + int err; + struct stat statbuf; + + err = stat(NFSD_THREAD_FILE, &statbuf); + if (err == 0) + return; + + if (errno != ENOENT) { + xlog(L_ERROR, "Unable to stat %s: errno %d (%m)", + NFSD_THREAD_FILE, errno); + return; + } + + /* + * this call can return an error if modprobe is set up to automatically + * mount nfsdfs when nfsd.ko is plugged in. So, ignore the return + * code from it and just check for the "threads" file afterward. + */ + system("/bin/mount -t nfsd nfsd " NFSD_FS_DIR " >/dev/null 2>&1"); + + err = stat(NFSD_THREAD_FILE, &statbuf); + if (err == 0) + return; + + xlog(L_WARNING, "Unable to access " NFSD_FS_DIR " errno %d (%m)." + "\nPlease try, as root, 'mount -t nfsd nfsd " NFSD_FS_DIR + "' and then restart %s to correct the problem", errno, progname); + + return; +} + /* * Are there already sockets configured? If not, then it is safe to try to * open some and pass them through. @@ -81,6 +127,11 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port) case AF_INET: family = "inet"; break; +#ifdef IPV6_SUPPORTED + case AF_INET6: + family = "inet6"; + break; +#endif /* IPV6_SUPPORTED */ default: xlog(L_ERROR, "Unknown address family specified: %d\n", hints->ai_family); @@ -128,6 +179,15 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port) rc = errno; goto error; } +#ifdef IPV6_SUPPORTED + if (addr->ai_family == AF_INET6 && + setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) { + xlog(L_ERROR, "unable to set IPV6_V6ONLY: " + "errno %d (%m)\n", errno); + rc = errno; + goto error; + } +#endif /* IPV6_SUPPORTED */ if (addr->ai_protocol == IPPROTO_TCP && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { xlog(L_ERROR, "unable to set SO_REUSEADDR on %s " @@ -158,7 +218,7 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port) } snprintf(buf, sizeof(buf), "%d\n", sockfd); - if (write(fd, buf, strlen(buf)) != strlen(buf)) { + if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) { /* * this error may be common on older kernels that don't * support IPv6, so turn into a debug message. @@ -189,7 +249,7 @@ int nfssvc_set_sockets(const int family, const unsigned int protobits, const char *host, const char *port) { - struct addrinfo hints = { .ai_flags = AI_PASSIVE | AI_ADDRCONFIG }; + struct addrinfo hints = { .ai_flags = AI_PASSIVE }; hints.ai_family = family; @@ -215,20 +275,20 @@ nfssvc_setvers(unsigned int ctlbits, int minorvers4) if (fd < 0) return; + n = minorvers4 >= 0 ? minorvers4 : -minorvers4; + if (n >= NFSD_MINMINORVERS4 && n <= NFSD_MAXMINORVERS4) + off += snprintf(ptr+off, sizeof(buf) - off, "%c4.%d ", + minorvers4 > 0 ? '+' : '-', + n); for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) { if (NFSCTL_VERISSET(ctlbits, n)) off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n); else off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n); } - n = minorvers4 >= 0 ? minorvers4 : -minorvers4; - if (n >= NFSD_MINMINORVERS4 && n <= NFSD_MAXMINORVERS4) - off += snprintf(ptr+off, sizeof(buf) - off, "%c4.%d", - minorvers4 > 0 ? '+' : '-', - n); xlog(D_GENERAL, "Writing version string to kernel: %s", buf); snprintf(ptr+off, sizeof(buf) - off, "\n"); - if (write(fd, buf, strlen(buf)) != strlen(buf)) + if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno); close(fd); @@ -254,7 +314,7 @@ nfssvc_threads(unsigned short port, const int nrservs) snprintf(buf, sizeof(buf), "%d\n", nrservs); n = write(fd, buf, strlen(buf)); close(fd); - if (n != strlen(buf)) + if (n != (ssize_t)strlen(buf)) return -1; else return 0;