X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=utils%2Fmount%2Fnetwork.c;h=223121092bedbbd7e16b8cafacaa88b63355c3b1;hb=14b0dae49afae3fcf05c19ae84829aeef2f6876e;hp=849ce1d6825da3ad0d8865b28876a54d5713a91f;hpb=6ab9cdacd2ea314a837c7affb840aeeec620cb66;p=nfs-utils.git diff --git a/utils/mount/network.c b/utils/mount/network.c index 849ce1d..2231210 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -46,18 +47,26 @@ #include "nls.h" #include "nfs_mount.h" #include "mount_constants.h" +#include "nfsrpc.h" #include "network.h" -#ifdef HAVE_RPCSVC_NFS_PROT_H -#include -#else -#include -#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) @@ -71,6 +80,11 @@ extern int nfs_mount_data_version; extern char *progname; extern int verbose; +static const char *nfs_ns_pgmtbl[] = { + "status", + NULL, +}; + static const unsigned long nfs_to_mnt[] = { 0, 0, @@ -458,7 +472,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 +557,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 +570,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; } @@ -657,24 +675,16 @@ version_fixed: return probe_mntport(mnt_server); } -static int probe_statd(void) +static int nfs_probe_statd(void) { - struct sockaddr_in addr; - unsigned short port; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - port = getport(&addr, 100024, 1, IPPROTO_UDP); - - if (port == 0) - return 0; - addr.sin_port = htons(port); - - if (clnt_ping(&addr, 100024, 1, IPPROTO_UDP, NULL) <= 0) - return 0; + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); - return 1; + return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr), + program, (rpcvers_t)1, IPPROTO_UDP); } /** @@ -688,14 +698,26 @@ int start_statd(void) struct stat stb; #endif - if (probe_statd()) + if (nfs_probe_statd()) return 1; #ifdef START_STATD if (stat(START_STATD, &stb) == 0) { if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) { - system(START_STATD); - if (probe_statd()) + pid_t pid = fork(); + switch (pid) { + case 0: /* child */ + execl(START_STATD, START_STATD, NULL); + exit(1); + case -1: /* error */ + nfs_error(_("fork failed: %s"), + strerror(errno)); + break; + default: /* parent */ + waitpid(pid, NULL,0); + break; + } + if (nfs_probe_statd()) return 1; } } @@ -886,39 +908,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. *