]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/network.c
Merge branch 'sid'
[nfs-utils.git] / utils / mount / network.c
index 1759c1cdbc732b341494ee0b7f56aea77bc63e36..4be48cd6a5f0941d3cb1be2b0d40ce9d7ece6d31 100644 (file)
@@ -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
  *
  */
 
@@ -155,9 +155,8 @@ static const unsigned long probe_nfs2_only[] = {
        0,
 };
 
-static const unsigned long probe_nfs3_first[] = {
+static const unsigned long probe_nfs3_only[] = {
        3,
-       2,
        0,
 };
 
@@ -167,10 +166,8 @@ static const unsigned long probe_mnt1_first[] = {
        0,
 };
 
-static const unsigned long probe_mnt3_first[] = {
+static const unsigned long probe_mnt3_only[] = {
        3,
-       1,
-       2,
        0,
 };
 
@@ -210,9 +207,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;
@@ -629,7 +623,7 @@ static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
                probe_proto = nfs_default_proto();
 
                return nfs_probe_port(sap, salen, pmap,
-                                       probe_nfs3_first, probe_proto);
+                                       probe_nfs3_only, probe_proto);
        } else
                return nfs_probe_port(sap, salen, pmap,
                                        probe_nfs2_only, probe_udp_only);
@@ -656,7 +650,7 @@ static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
 
        if (nfs_mount_data_version >= 4)
                return nfs_probe_port(sap, salen, pmap,
-                                       probe_mnt3_first, probe_udp_first);
+                                       probe_mnt3_only, probe_udp_first);
        else
                return nfs_probe_port(sap, salen, pmap,
                                        probe_mnt1_first, probe_udp_only);
@@ -720,7 +714,7 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
        memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
        memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
        probe_vers = (nfs_mount_data_version >= 4) ?
-                       probe_mnt3_first : probe_mnt1_first;
+                       probe_mnt3_only : probe_mnt1_first;
 
        for (; *probe_vers; probe_vers++) {
                nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
@@ -1098,7 +1092,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 +1100,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;
 
-       return !getsockname(sock, buf, buflen);
+       result = !getsockname(sock, buf, buflen);
+
+out:
+       close(sock);
+       return result;
 }
 
 /*
@@ -1349,7 +1341,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;
                }
@@ -1521,7 +1513,11 @@ nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
         * set @protocol to zero.  The pmap protocol value will
         * be filled in later by an rpcbind query in this case.
         */
-       return nfs_nfs_protocol(options, protocol);
+       if (!nfs_nfs_protocol(options, protocol))
+               return 0;
+       if (*protocol == NFSPROTO_RDMA)
+               *protocol = IPPROTO_TCP;
+       return 1;
 }
 
 /*
@@ -1537,7 +1533,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;
                }
@@ -1625,3 +1621,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;
+}