X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fstatd%2Fsm-notify.c;h=928d1c56f03bff687ec90adef071d78a0313720b;hp=0dba891ba480b7e37e1e4471ed64d754388e2811;hb=86cfdf1d38da18f9f917c674daba79a4435445a7;hpb=1a1f991870f02b303a05e1d63915226e7cfb9f53 diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c index 0dba891..928d1c5 100644 --- a/utils/statd/sm-notify.c +++ b/utils/statd/sm-notify.c @@ -8,6 +8,7 @@ #include #endif +#include #include #include #include @@ -29,65 +30,38 @@ #include #include "xlog.h" +#include "nsm.h" #include "nfsrpc.h" -#ifndef BASEDIR -# ifdef NFS_STATEDIR -# define BASEDIR NFS_STATEDIR -# else -# define BASEDIR "/var/lib/nfs" -# endif -#endif - -#define DEFAULT_SM_STATE_PATH BASEDIR "/state" -#define DEFAULT_SM_DIR_PATH BASEDIR "/sm" -#define DEFAULT_SM_BAK_PATH DEFAULT_SM_DIR_PATH ".bak" - -char *_SM_BASE_PATH = BASEDIR; -char *_SM_STATE_PATH = DEFAULT_SM_STATE_PATH; -char *_SM_DIR_PATH = DEFAULT_SM_DIR_PATH; -char *_SM_BAK_PATH = DEFAULT_SM_BAK_PATH; - -#define NSM_PROG 100024 -#define NSM_PROGRAM 100024 -#define NSM_VERSION 1 #define NSM_TIMEOUT 2 -#define NSM_NOTIFY 6 #define NSM_MAX_TIMEOUT 120 /* don't make this too big */ -#define MAXMSGSIZE 256 struct nsm_host { struct nsm_host * next; char * name; - char * path; - struct sockaddr_storage addr; struct addrinfo *ai; time_t last_used; time_t send_next; unsigned int timeout; unsigned int retries; - unsigned int xid; + uint32_t xid; }; static char nsm_hostname[256]; -static uint32_t nsm_state; +static int nsm_state; +static int nsm_family = AF_INET; static int opt_debug = 0; -static int opt_update_state = 1; +static _Bool opt_update_state = true; static unsigned int opt_max_retry = 15 * 60; static char * opt_srcaddr = 0; static uint16_t opt_srcport = 0; -static unsigned int nsm_get_state(int); -static void notify(void); +static void notify(const int sock); static int notify_host(int, struct nsm_host *); static void recv_reply(int); -static void backup_hosts(const char *, const char *); -static void get_hosts(const char *); static void insert_host(struct nsm_host *); static struct nsm_host *find_host(uint32_t); static int record_pid(void); -static void drop_privs(void); -static void set_kernel_nsm_state(int state); static struct nsm_host * hosts = NULL; @@ -111,10 +85,39 @@ static struct addrinfo *smn_lookup(const char *name) return ai; } +__attribute_malloc__ +static struct nsm_host * +smn_alloc_host(const char *hostname, const time_t timestamp) +{ + struct nsm_host *host; + + host = calloc(1, sizeof(*host)); + if (host == NULL) + goto out_nomem; + + host->name = strdup(hostname); + if (host->name == NULL) { + free(host); + goto out_nomem; + } + + host->last_used = timestamp; + host->timeout = NSM_TIMEOUT; + host->retries = 100; /* force address retry */ + + return host; + +out_nomem: + xlog_warn("Unable to allocate memory"); + return NULL; +} + static void smn_forget_host(struct nsm_host *host) { - unlink(host->path); - free(host->path); + xlog(D_CALL, "Removing %s from notify list", host->name); + + nsm_delete_notified_host(host->name); + free(host->name); if (host->ai) freeaddrinfo(host->ai); @@ -122,11 +125,190 @@ static void smn_forget_host(struct nsm_host *host) free(host); } +static unsigned int +smn_get_host(const char *hostname, + __attribute__ ((unused)) const struct sockaddr *sap, + __attribute__ ((unused)) const struct mon *m, + const time_t timestamp) +{ + struct nsm_host *host; + + host = smn_alloc_host(hostname, timestamp); + if (host == NULL) + return 0; + + insert_host(host); + xlog(D_GENERAL, "Added host %s to notify list", hostname); + return 1; +} + +#ifdef IPV6_SUPPORTED +static int smn_socket(void) +{ + int sock; + + /* + * Use an AF_INET socket if IPv6 is disabled on the + * local system. + */ + sock = socket(AF_INET6, SOCK_DGRAM, 0); + if (sock == -1) { + if (errno != EAFNOSUPPORT) { + xlog(L_ERROR, "Failed to create RPC socket: %m"); + return -1; + } + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + xlog(L_ERROR, "Failed to create RPC socket: %m"); + return -1; + } + } else + nsm_family = AF_INET6; + + if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { + xlog(L_ERROR, "fcntl(3) on RPC socket failed: %m"); + goto out_close; + } + + /* + * TI-RPC over IPv6 (udp6/tcp6) does not handle IPv4. However, + * since sm-notify open-codes all of its RPC support, it can + * use a single socket and let the local network stack provide + * the correct mapping between address families automatically. + * This is the same thing that is done in the kernel. + */ + if (nsm_family == AF_INET6) { + const int zero = 0; + socklen_t zerolen = (socklen_t)sizeof(zero); + + if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, + (char *)&zero, zerolen) == -1) { + xlog(L_ERROR, "setsockopt(3) on RPC socket failed: %m"); + goto out_close; + } + } + + return sock; + +out_close: + (void)close(sock); + return -1; +} +#else /* !IPV6_SUPPORTED */ +static int smn_socket(void) +{ + int sock; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock == -1) { + xlog(L_ERROR, "Failed to create RPC socket: %m"); + return -1; + } + + if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { + xlog(L_ERROR, "fcntl(3) on RPC socket failed: %m"); + (void)close(sock); + return -1; + } + + return sock; +} +#endif /* !IPV6_SUPPORTED */ + +#ifdef HAVE_LIBTIRPC +static int +smn_bindresvport(int sock, struct sockaddr *sap) +{ + return bindresvport_sa(sock, sap); +} + +#else /* !HAVE_LIBTIRPC */ +static int +smn_bindresvport(int sock, struct sockaddr *sap) +{ + if (sap->sa_family != AF_INET) { + errno = EAFNOSUPPORT; + return -1; + } + + return bindresvport(sock, (struct sockaddr_in *)(char *)sap); +} +#endif /* !HAVE_LIBTIRPC */ + +/* + * Prepare a socket for sending RPC requests + * + * Returns a bound datagram socket file descriptor, or -1 if + * an error occurs. + */ +static int +smn_create_socket(const char *srcaddr, const uint16_t srcport) +{ + struct sockaddr_storage address; + struct sockaddr *local_addr = (struct sockaddr *)&address; + int sock, retry_cnt = 0; + +retry: + sock = smn_socket(); + if (sock == -1) + return -1; + + memset(&address, 0, sizeof(address)); + local_addr->sa_family = AF_INET; /* Default to IPv4 */ + + /* Bind source IP if provided on command line */ + if (srcaddr) { + struct addrinfo *ai = smn_lookup(srcaddr); + if (!ai) { + xlog(L_ERROR, + "Not a valid hostname or address: \"%s\"", + srcaddr); + (void)close(sock); + return -1; + } + + /* We know it's IPv4 at this point */ + memcpy(local_addr, ai->ai_addr, ai->ai_addrlen); + + freeaddrinfo(ai); + } + + /* Use source port if provided on the command line, + * otherwise use bindresvport */ + if (srcport) { + nfs_set_port(local_addr, srcport); + if (bind(sock, local_addr, sizeof(struct sockaddr_in)) < 0) { + xlog(L_ERROR, "Failed to bind RPC socket: %m"); + (void)close(sock); + return -1; + } + } else { + struct servent *se; + struct sockaddr_in *sin = (struct sockaddr_in *)local_addr; + + if (smn_bindresvport(sock, local_addr) == -1) { + xlog(L_ERROR, + "bindresvport on RPC socket failed: %m"); + (void)close(sock); + return -1; + } + + /* try to avoid known ports */ + se = getservbyport(sin->sin_port, "udp"); + if (se && retry_cnt < 100) { + retry_cnt++; + close(sock); + goto retry; + } + } + + return sock; +} + int main(int argc, char **argv) { - int c; - int force = 0; + int c, sock, force = 0; char * progname; progname = strrchr(argv[0], '/'); @@ -147,7 +329,7 @@ main(int argc, char **argv) opt_max_retry = atoi(optarg) * 60; break; case 'n': - opt_update_state = 0; + opt_update_state = false; break; case 'p': opt_srcport = atoi(optarg); @@ -156,20 +338,8 @@ main(int argc, char **argv) opt_srcaddr = optarg; break; case 'P': - _SM_BASE_PATH = strdup(optarg); - _SM_STATE_PATH = malloc(strlen(optarg)+1+sizeof("state")); - _SM_DIR_PATH = malloc(strlen(optarg)+1+sizeof("sm")); - _SM_BAK_PATH = malloc(strlen(optarg)+1+sizeof("sm.bak")); - if (_SM_BASE_PATH == NULL || - _SM_STATE_PATH == NULL || - _SM_DIR_PATH == NULL || - _SM_BAK_PATH == NULL) { - fprintf(stderr, "unable to allocate memory"); + if (!nsm_setup_pathnames(argv[0], optarg)) exit(1); - } - strcat(strcpy(_SM_STATE_PATH, _SM_BASE_PATH), "/state"); - strcat(strcpy(_SM_DIR_PATH, _SM_BASE_PATH), "/sm"); - strcat(strcpy(_SM_BAK_PATH, _SM_BASE_PATH), "/sm.bak"); break; default: @@ -195,8 +365,8 @@ usage: fprintf(stderr, xlog_open(progname); xlog(L_NOTICE, "Version " VERSION " starting"); - if (strcmp(_SM_BASE_PATH, BASEDIR) == 0) { - if (record_pid() == 0 && force == 0 && opt_update_state == 1) { + if (nsm_is_default_parentdir()) { + if (record_pid() == 0 && force == 0 && opt_update_state) { /* already run, don't try again */ xlog(L_NOTICE, "Already notifying clients; Exiting!"); exit(0); @@ -211,18 +381,16 @@ usage: fprintf(stderr, exit(1); } - backup_hosts(_SM_DIR_PATH, _SM_BAK_PATH); - get_hosts(_SM_BAK_PATH); - - /* If there are not hosts to notify, just exit */ - if (!hosts) { + (void)nsm_retire_monitored_hosts(); + if (nsm_load_notify_list(smn_get_host) == 0) { xlog(D_GENERAL, "No hosts to notify; exiting"); return 0; } - /* Get and update the NSM state. This will call sync() */ nsm_state = nsm_get_state(opt_update_state); - set_kernel_nsm_state(nsm_state); + if (nsm_state == 0) + exit(1); + nsm_update_kernel_state(nsm_state); if (!opt_debug) { xlog(L_NOTICE, "Backgrounding to notify hosts...\n"); @@ -237,7 +405,14 @@ usage: fprintf(stderr, close(2); } - notify(); + sock = smn_create_socket(opt_srcaddr, opt_srcport); + if (sock == -1) + exit(1); + + if (!nsm_drop_privileges(-1)) + exit(1); + + notify(sock); if (hosts) { struct nsm_host *hp; @@ -257,67 +432,13 @@ usage: fprintf(stderr, * Notify hosts */ static void -notify(void) +notify(const int sock) { - struct sockaddr_storage address; - struct sockaddr *local_addr = (struct sockaddr *)&address; time_t failtime = 0; - int sock = -1; - int retry_cnt = 0; - - retry: - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - xlog(L_ERROR, "Failed to create RPC socket: %m"); - exit(1); - } - fcntl(sock, F_SETFL, O_NONBLOCK); - - memset(&address, 0, sizeof(address)); - local_addr->sa_family = AF_INET; /* Default to IPv4 */ - - /* Bind source IP if provided on command line */ - if (opt_srcaddr) { - struct addrinfo *ai = smn_lookup(opt_srcaddr); - if (!ai) { - xlog(L_ERROR, - "Not a valid hostname or address: \"%s\"", - opt_srcaddr); - exit(1); - } - - /* We know it's IPv4 at this point */ - memcpy(local_addr, ai->ai_addr, ai->ai_addrlen); - - freeaddrinfo(ai); - } - - /* Use source port if provided on the command line, - * otherwise use bindresvport */ - if (opt_srcport) { - nfs_set_port(local_addr, opt_srcport); - if (bind(sock, local_addr, sizeof(struct sockaddr_in)) < 0) { - xlog(L_ERROR, "Failed to bind RPC socket: %m"); - exit(1); - } - } else { - struct servent *se; - struct sockaddr_in *sin = (struct sockaddr_in *)local_addr; - (void) bindresvport(sock, sin); - /* try to avoid known ports */ - se = getservbyport(sin->sin_port, "udp"); - if (se && retry_cnt < 100) { - retry_cnt++; - close(sock); - goto retry; - } - } if (opt_max_retry) failtime = time(NULL) + opt_max_retry; - drop_privs(); - while (hosts) { struct pollfd pfd; time_t now = time(NULL); @@ -375,17 +496,8 @@ notify(void) static int notify_host(int sock, struct nsm_host *host) { - struct sockaddr_storage address; - struct sockaddr *dest = (struct sockaddr *)&address; - socklen_t destlen = sizeof(address); - static unsigned int xid = 0; - uint32_t msgbuf[MAXMSGSIZE], *p; - unsigned int len; - - if (!xid) - xid = getpid() + time(NULL); - if (!host->xid) - host->xid = xid++; + struct sockaddr *sap; + socklen_t salen; if (host->ai == NULL) { host->ai = smn_lookup(host->name); @@ -396,12 +508,6 @@ notify_host(int sock, struct nsm_host *host) } } - memset(msgbuf, 0, sizeof(msgbuf)); - p = msgbuf; - *p++ = htonl(host->xid); - *p++ = 0; - *p++ = htonl(2); - /* If we retransmitted 4 times, reset the port to force * a new portmap lookup (in case statd was restarted). * We also rotate through multiple IP addresses at this @@ -409,10 +515,7 @@ notify_host(int sock, struct nsm_host *host) */ if (host->retries >= 4) { /* don't rotate if there is only one addrinfo */ - if (host->ai->ai_next == NULL) - memcpy(&host->addr, host->ai->ai_addr, - host->ai->ai_addrlen); - else { + if (host->ai->ai_next != NULL) { struct addrinfo *first = host->ai; struct addrinfo **next = &host->ai; @@ -425,208 +528,100 @@ notify_host(int sock, struct nsm_host *host) next = & (*next)->ai_next; /* put first entry at end */ *next = first; - memcpy(&host->addr, first->ai_addr, - first->ai_addrlen); } - nfs_set_port((struct sockaddr *)&host->addr, 0); + nfs_set_port(host->ai->ai_addr, 0); host->retries = 0; } - memcpy(dest, &host->addr, destlen); - if (nfs_get_port(dest) == 0) { - /* Build a PMAP packet */ - xlog(D_GENERAL, "Sending portmap query to %s", host->name); - - nfs_set_port(dest, 111); - *p++ = htonl(100000); - *p++ = htonl(2); - *p++ = htonl(3); - - /* Auth and verf */ - *p++ = 0; *p++ = 0; - *p++ = 0; *p++ = 0; - - *p++ = htonl(NSM_PROGRAM); - *p++ = htonl(NSM_VERSION); - *p++ = htonl(IPPROTO_UDP); - *p++ = 0; - } else { - /* Build an SM_NOTIFY packet */ - xlog(D_GENERAL, "Sending SM_NOTIFY to %s", host->name); - - *p++ = htonl(NSM_PROGRAM); - *p++ = htonl(NSM_VERSION); - *p++ = htonl(NSM_NOTIFY); - - /* Auth and verf */ - *p++ = 0; *p++ = 0; - *p++ = 0; *p++ = 0; - - /* state change */ - len = strlen(nsm_hostname); - *p++ = htonl(len); - memcpy(p, nsm_hostname, len); - p += (len + 3) >> 2; - *p++ = htonl(nsm_state); - } - len = (p - msgbuf) << 2; + sap = host->ai->ai_addr; + salen = host->ai->ai_addrlen; - if (sendto(sock, msgbuf, len, 0, dest, destlen) < 0) - xlog_warn("Sending Reboot Notification to " - "'%s' failed: errno %d (%m)", host->name, errno); + if (nfs_get_port(sap) == 0) + host->xid = nsm_xmit_rpcbind(sock, sap, SM_PROG, SM_VERS); + else + host->xid = nsm_xmit_notify(sock, sap, salen, + SM_PROG, nsm_hostname, nsm_state); return 0; } /* - * Receive reply from remote host + * Extract the returned port number and set up the SM_NOTIFY call. */ static void -recv_reply(int sock) +recv_rpcbind_reply(struct sockaddr *sap, struct nsm_host *host, XDR *xdr) { - struct nsm_host *hp; - struct sockaddr *sap; - uint32_t msgbuf[MAXMSGSIZE], *p, *end; - uint32_t xid; - int res; + uint16_t port = nsm_recv_rpcbind(sap->sa_family, xdr); - res = recv(sock, msgbuf, sizeof(msgbuf), 0); - if (res < 0) - return; + host->send_next = time(NULL); + host->xid = 0; - xlog(D_GENERAL, "Received packet..."); - - p = msgbuf; - end = p + (res >> 2); - - xid = ntohl(*p++); - if (*p++ != htonl(1) /* must be REPLY */ - || *p++ != htonl(0) /* must be ACCEPTED */ - || *p++ != htonl(0) /* must be NULL verifier */ - || *p++ != htonl(0) - || *p++ != htonl(0)) /* must be SUCCESS */ - return; - - /* Before we look at the data, find the host struct for - this reply */ - if ((hp = find_host(xid)) == NULL) - return; - sap = (struct sockaddr *)&hp->addr; - - if (nfs_get_port(sap) == 0) { - /* This was a portmap request */ - unsigned int port; - - port = ntohl(*p++); - if (p > end) - goto fail; - - hp->send_next = time(NULL); - if (port == 0) { - /* No binding for statd. Delay the next - * portmap query for max timeout */ - xlog(D_GENERAL, "No statd on %s", hp->name); - hp->timeout = NSM_MAX_TIMEOUT; - hp->send_next += NSM_MAX_TIMEOUT; - } else { - nfs_set_port(sap, port); - if (hp->timeout >= NSM_MAX_TIMEOUT / 4) - hp->timeout = NSM_MAX_TIMEOUT / 4; - } - hp->xid = 0; + if (port == 0) { + /* No binding for statd... */ + xlog(D_GENERAL, "No statd on host %s", host->name); + host->timeout = NSM_MAX_TIMEOUT; + host->send_next += NSM_MAX_TIMEOUT; } else { - /* Successful NOTIFY call. Server returns void, - * so nothing we need to do here (except - * check that we didn't read past the end of the - * packet) - */ - if (p <= end) { - xlog(D_GENERAL, "Host %s notified successfully", - hp->name); - smn_forget_host(hp); - return; - } + nfs_set_port(sap, port); + if (host->timeout >= NSM_MAX_TIMEOUT / 4) + host->timeout = NSM_MAX_TIMEOUT / 4; } -fail: /* Re-insert the host */ - insert_host(hp); + insert_host(host); } /* - * Back up all hosts from the sm directory to sm.bak + * Successful NOTIFY call. Server returns void, so nothing + * we need to do here. */ static void -backup_hosts(const char *dirname, const char *bakname) +recv_notify_reply(struct nsm_host *host) { - struct dirent *de; - DIR *dir; - - if (!(dir = opendir(dirname))) { - xlog_warn("Failed to open %s: %m", dirname); - return; - } - - while ((de = readdir(dir)) != NULL) { - char src[1024], dst[1024]; - - if (de->d_name[0] == '.') - continue; + xlog(D_GENERAL, "Host %s notified successfully", host->name); - snprintf(src, sizeof(src), "%s/%s", dirname, de->d_name); - snprintf(dst, sizeof(dst), "%s/%s", bakname, de->d_name); - if (rename(src, dst) < 0) - xlog_warn("Failed to rename %s -> %s: %m", src, dst); - } - closedir(dir); + smn_forget_host(host); } /* - * Get all entries from sm.bak and convert them to host entries + * Receive reply from remote host */ static void -get_hosts(const char *dirname) +recv_reply(int sock) { - struct nsm_host *host; - struct dirent *de; - DIR *dir; + struct nsm_host *hp; + struct sockaddr *sap; + char msgbuf[NSM_MAXMSGSIZE]; + uint32_t xid; + ssize_t msglen; + XDR xdr; - if (!(dir = opendir(dirname))) { - xlog_warn("Failed to open %s: %m", dirname); + memset(msgbuf, 0 , sizeof(msgbuf)); + msglen = recv(sock, msgbuf, sizeof(msgbuf), 0); + if (msglen < 0) return; - } - host = NULL; - while ((de = readdir(dir)) != NULL) { - struct stat stb; - char path[1024]; - - if (de->d_name[0] == '.') - continue; - if (host == NULL) - host = calloc(1, sizeof(*host)); - if (host == NULL) { - xlog_warn("Unable to allocate memory"); - return; - } + xlog(D_GENERAL, "Received packet..."); - snprintf(path, sizeof(path), "%s/%s", dirname, de->d_name); - if (stat(path, &stb) < 0) - continue; + memset(&xdr, 0, sizeof(xdr)); + xdrmem_create(&xdr, msgbuf, (unsigned int)msglen, XDR_DECODE); + xid = nsm_parse_reply(&xdr); + if (xid == 0) + goto out; - host->last_used = stb.st_mtime; - host->timeout = NSM_TIMEOUT; - host->path = strdup(path); - host->name = strdup(de->d_name); - host->retries = 100; /* force address retry */ + /* Before we look at the data, find the host struct for + this reply */ + if ((hp = find_host(xid)) == NULL) + goto out; - insert_host(host); - host = NULL; - } - closedir(dir); + sap = hp->ai->ai_addr; + if (nfs_get_port(sap) == 0) + recv_rpcbind_reply(sap, hp, &xdr); + else + recv_notify_reply(hp); - if (host) - free(host); +out: + xdr_destroy(&xdr); } /* @@ -676,60 +671,6 @@ find_host(uint32_t xid) return NULL; } - -/* - * Retrieve the current NSM state - */ -static unsigned int -nsm_get_state(int update) -{ - char newfile[PATH_MAX]; - int fd, state; - - if ((fd = open(_SM_STATE_PATH, O_RDONLY)) < 0) { - xlog_warn("%s: %m", _SM_STATE_PATH); - xlog_warn("Creating %s, set initial state 1", - _SM_STATE_PATH); - state = 1; - update = 1; - } else { - if (read(fd, &state, sizeof(state)) != sizeof(state)) { - xlog_warn("%s: bad file size, setting state = 1", - _SM_STATE_PATH); - state = 1; - update = 1; - } else { - if (!(state & 1)) - state += 1; - } - close(fd); - } - - if (update) { - state += 2; - snprintf(newfile, sizeof(newfile), - "%s.new", _SM_STATE_PATH); - if ((fd = open(newfile, O_CREAT|O_WRONLY, 0644)) < 0) { - xlog(L_ERROR, "Cannot create %s: %m", newfile); - exit(1); - } - if (write(fd, &state, sizeof(state)) != sizeof(state)) { - xlog(L_ERROR, - "Failed to write state to %s", newfile); - exit(1); - } - close(fd); - if (rename(newfile, _SM_STATE_PATH) < 0) { - xlog(L_ERROR, - "Cannot create %s: %m", _SM_STATE_PATH); - exit(1); - } - sync(); - } - - return state; -} - /* * Record pid in /var/run/sm-notify.pid * This file should remain until a reboot, even if the @@ -756,47 +697,3 @@ static int record_pid(void) (void)close(fd); return 1; } - -/* Drop privileges to match owner of state-directory - * (in case a reply triggers some unknown bug). - */ -static void drop_privs(void) -{ - struct stat st; - - if (stat(_SM_DIR_PATH, &st) == -1 && - stat(_SM_BASE_PATH, &st) == -1) { - st.st_uid = 0; - st.st_gid = 0; - } - - if (st.st_uid == 0) { - xlog_warn("Running as 'root'. " - "chown %s to choose different user", _SM_DIR_PATH); - return; - } - - setgroups(0, NULL); - if (setgid(st.st_gid) == -1 - || setuid(st.st_uid) == -1) { - xlog(L_ERROR, "Fail to drop privileges"); - exit(1); - } -} - -static void set_kernel_nsm_state(int state) -{ - int fd; - const char *file = "/proc/sys/fs/nfs/nsm_local_state"; - - fd = open(file ,O_WRONLY); - if (fd >= 0) { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", state); - if (write(fd, buf, strlen(buf)) != strlen(buf)) { - xlog_warn("Writing to '%s' failed: errno %d (%m)", - file, errno); - } - close(fd); - } -}