]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/network.c
Ensure statd gets started if required when non-root
[nfs-utils.git] / utils / mount / network.c
index 7d3d09aacdfca9ce9992caf788fc6b214e68a61f..806344c399dd92d4f3b5ebe8d8f67ea9099c6061 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
 #include <netinet/in.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include "mount_constants.h"
 #include "network.h"
 
+/*
+ * Earlier versions of glibc's /usr/include/netdb.h exclude these
+ * definitions because it was thought they were not part of a stable
+ * POSIX standard.  However, they are defined by RFC 2553 and 3493
+ * and in POSIX 1003.1-2001, so these definitions were added in later
+ * versions of netdb.h.
+ */
+#ifndef AI_V4MAPPED
+#define AI_V4MAPPED     0x0008  /* IPv4-mapped addresses are acceptable.  */
+#endif /* AI_V4MAPPED */
+#ifndef AI_ALL
+#define AI_ALL          0x0010  /* Return both IPv4 and IPv6 addresses.  */
+#endif /* AI_ALL */
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG   0x0020  /* Use configuration of this host to choose \
+                                  returned address type.  */
+#endif /* AI_ADDRCONFIG */
+
 #define PMAP_TIMEOUT   (10)
 #define CONNECT_TIMEOUT        (20)
 #define MOUNT_TIMEOUT  (30)
@@ -447,7 +466,7 @@ static unsigned short getport(struct sockaddr_in *saddr,
        bind_saddr = *saddr;
        bind_saddr.sin_port = htons(PMAPPORT);
 
-       socket = get_socket(&bind_saddr, proto, PMAP_TIMEOUT, FALSE, FALSE);
+       socket = get_socket(&bind_saddr, proto, PMAP_TIMEOUT, FALSE, TRUE);
        if (socket == RPC_ANYSOCK) {
                if (proto == IPPROTO_TCP &&
                    rpc_createerr.cf_error.re_errno == ETIMEDOUT)
@@ -532,11 +551,11 @@ static int probe_port(clnt_addr_t *server, const unsigned long *versions,
                                 }
                                if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
                                        goto out_ok;
-                               if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
-                                       goto out_bad;
                        }
                }
                if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
+                   rpc_createerr.cf_stat != RPC_TIMEDOUT &&
+                   rpc_createerr.cf_stat != RPC_CANTRECV &&
                    rpc_createerr.cf_stat != RPC_PROGVERSMISMATCH)
                        goto out_bad;
 
@@ -545,6 +564,10 @@ static int probe_port(clnt_addr_t *server, const unsigned long *versions,
                                continue;
                        p_prot = protos;
                }
+               if (rpc_createerr.cf_stat == RPC_TIMEDOUT ||
+                   rpc_createerr.cf_stat == RPC_CANTRECV)
+                       goto out_bad;
+
                if (vers || !*++p_vers)
                        break;
        }
@@ -683,7 +706,18 @@ int start_statd(void)
 #ifdef START_STATD
        if (stat(START_STATD, &stb) == 0) {
                if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
-                       system(START_STATD);
+                       pid_t pid = fork();
+                       switch (pid) {
+                       case 0: /* child */
+                               execl(START_STATD, START_STATD, NULL);
+                               exit(1);
+                       case -1: /* error */
+                               perror("Fork failed");
+                               break;
+                       default: /* parent */
+                               waitpid(pid, NULL,0);
+                               break;
+                       }
                        if (probe_statd())
                                return 1;
                }