]> 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 849ce1d6825da3ad0d8865b28876a54d5713a91f..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"
 
-#ifdef HAVE_RPCSVC_NFS_PROT_H
-#include <rpcsvc/nfs_prot.h>
-#else
-#include <linux/nfs.h>
-#define nfsstat nfs_stat
-#endif
-
-#ifndef NFS_PORT
-#define NFS_PORT 2049
-#endif
+/*
+ * 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)
@@ -458,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)
@@ -543,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;
 
@@ -556,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;
        }
@@ -694,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;
                }
@@ -886,39 +909,6 @@ int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
                return 0;
 }
 
-/**
- * get_client_address - acquire our local network address
- * @saddr: server's address
- * @caddr: filled in with our network address
- *
- * Discover a network address that the server will use to call us back.
- * On multi-homed clients, this address depends on which NIC we use to
- * route requests to the server.
- *
- * Use a connected datagram socket so as not to leave a socket in TIME_WAIT.
- *
- * Returns one if successful, otherwise zero.
- */
-int get_client_address(struct sockaddr_in *saddr, struct sockaddr_in *caddr)
-{
-       socklen_t len = sizeof(*caddr);
-       int socket, err;
-
-       socket = get_socket(saddr, IPPROTO_UDP, CONNECT_TIMEOUT, FALSE, TRUE);
-       if (socket == RPC_ANYSOCK)
-               return 0;
-
-       err = getsockname(socket, caddr, &len);
-       close(socket);
-
-       if (err && verbose) {
-               nfs_error(_("%s: getsockname failed: %s"),
-                               progname, strerror(errno));
-               return 0;
-       }
-       return 1;
-}
-
 /*
  * Try a getsockname() on a connected datagram socket.
  *