X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fnetwork.c;h=e7bd522ac8da7927a7cfde97e3fc968137d356ab;hp=5b515c30d76d26a79839331d5db7dd2b7840f6e3;hb=12544486ef2de86e4f2dfc920cd2860fb81658d1;hpb=17962b82afb68ca8e6b0d3f432d36c6c7c4980ea diff --git a/utils/mount/network.c b/utils/mount/network.c index 5b515c3..e7bd522 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -16,8 +16,8 @@ * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA * */ @@ -210,9 +210,6 @@ int nfs_lookup(const char *hostname, const sa_family_t family, { struct addrinfo *gai_results; struct addrinfo gai_hint = { -#ifdef HAVE_DECL_AI_ADDRCONFIG - .ai_flags = AI_ADDRCONFIG, -#endif /* HAVE_DECL_AI_ADDRCONFIG */ .ai_family = family, }; socklen_t len = *salen; @@ -1098,7 +1095,7 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen, .sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, }; - int sock; + int sock, result = 0; sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) @@ -1106,28 +1103,26 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen, switch (sap->sa_family) { case AF_INET: - if (bind(sock, SAFE_SOCKADDR(&sin), sizeof(sin)) < 0) { - close(sock); - return 0; - } + if (bind(sock, SAFE_SOCKADDR(&sin), sizeof(sin)) < 0) + goto out; break; case AF_INET6: - if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0) { - close(sock); - return 0; - } + if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0) + goto out; break; default: errno = EAFNOSUPPORT; - return 0; + goto out; } - if (connect(sock, sap, salen) < 0) { - close(sock); - return 0; - } + if (connect(sock, sap, salen) < 0) + goto out; + + result = !getsockname(sock, buf, buflen); - return !getsockname(sock, buf, buflen); +out: + close(sock); + return result; } /* @@ -1349,7 +1344,7 @@ nfs_nfs_port(struct mount_options *options, unsigned long *port) case PO_NOT_FOUND: break; case PO_FOUND: - if (tmp >= 1 && tmp <= 65535) { + if (tmp >= 0 && tmp <= 65535) { *port = tmp; return 1; } @@ -1541,7 +1536,7 @@ nfs_mount_port(struct mount_options *options, unsigned long *port) case PO_NOT_FOUND: break; case PO_FOUND: - if (tmp >= 1 && tmp <= 65535) { + if (tmp >= 0 && tmp <= 65535) { *port = tmp; return 1; } @@ -1629,3 +1624,71 @@ int nfs_options2pmap(struct mount_options *options, return 1; } + +/* + * Discover mount server's hostname/address by examining mount options + * + * Returns a pointer to a string that the caller must free, on + * success; otherwise NULL is returned. + */ +static char *nfs_umount_hostname(struct mount_options *options, + char *hostname) +{ + char *option; + + option = po_get(options, "mountaddr"); + if (option) + goto out; + option = po_get(options, "mounthost"); + if (option) + goto out; + option = po_get(options, "addr"); + if (option) + goto out; + + return hostname; + +out: + free(hostname); + return strdup(option); +} + + +/* + * Returns EX_SUCCESS if mount options and device name have been + * parsed successfully; otherwise EX_FAIL. + */ +int nfs_umount_do_umnt(struct mount_options *options, + char **hostname, char **dirname) +{ + union nfs_sockaddr address; + struct sockaddr *sap = &address.sa; + socklen_t salen = sizeof(address); + struct pmap nfs_pmap, mnt_pmap; + sa_family_t family; + + if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) + return EX_FAIL; + + /* Skip UMNT call for vers=4 mounts */ + if (nfs_pmap.pm_vers == 4) + return EX_SUCCESS; + + *hostname = nfs_umount_hostname(options, *hostname); + if (!*hostname) { + nfs_error(_("%s: out of memory"), progname); + return EX_FAIL; + } + + if (!nfs_mount_proto_family(options, &family)) + return 0; + if (!nfs_lookup(*hostname, family, sap, &salen)) + /* nfs_lookup reports any errors */ + return EX_FAIL; + + if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0) + /* nfs_advise_umount reports any errors */ + return EX_FAIL; + + return EX_SUCCESS; +}