]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/stropts.c
mount.nfs: proto=netid forces address family when resolving server names
[nfs-utils.git] / utils / mount / stropts.c
index 008fdbc7c9846f41100b3921ea657cad53adb3a0..9a13509961adeab01c221f57ebeae2d1a21dcd15 100644 (file)
@@ -77,12 +77,18 @@ extern char *progname;
 extern int verbose;
 extern int sloppy;
 
+union nfs_sockaddr {
+       struct sockaddr         sa;
+       struct sockaddr_in      s4;
+       struct sockaddr_in6     s6;
+};
+
 struct nfsmount_info {
        const char              *spec,          /* server:/path */
                                *node,          /* mounted-on dir */
                                *type;          /* "nfs" or "nfs4" */
        char                    *hostname;      /* server's hostname */
-       struct sockaddr_storage address;        /* server's address */
+       union nfs_sockaddr      address;
        socklen_t               salen;          /* size of server's address */
 
        struct mount_options    *options;       /* parsed mount options */
@@ -205,9 +211,9 @@ static int nfs_append_clientaddr_option(const struct sockaddr *sap,
                                        socklen_t salen,
                                        struct mount_options *options)
 {
-       struct sockaddr_storage dummy;
-       struct sockaddr *my_addr = (struct sockaddr *)&dummy;
-       socklen_t my_len = sizeof(dummy);
+       union nfs_sockaddr address;
+       struct sockaddr *my_addr = &address.sa;
+       socklen_t my_len = sizeof(address);
 
        if (po_contains(options, "clientaddr") == PO_FOUND)
                return 1;
@@ -219,21 +225,33 @@ static int nfs_append_clientaddr_option(const struct sockaddr *sap,
 }
 
 /*
- * Resolve the 'mounthost=' hostname and append a new option using
- * the resulting address.
+ * Determine whether to append a 'mountaddr=' option.  The option is needed if:
+ *
+ *   1. "mounthost=" was specified, or
+ *   2. The address families for proto= and mountproto= are different.
  */
-static int nfs_fix_mounthost_option(struct mount_options *options)
+static int nfs_fix_mounthost_option(struct mount_options *options,
+               const char *nfs_hostname)
 {
-       struct sockaddr_storage dummy;
-       struct sockaddr *sap = (struct sockaddr *)&dummy;
-       socklen_t salen = sizeof(dummy);
+       union nfs_sockaddr address;
+       struct sockaddr *sap = &address.sa;
+       socklen_t salen = sizeof(address);
+       sa_family_t nfs_family, mnt_family;
        char *mounthost;
 
+       if (!nfs_nfs_proto_family(options, &nfs_family))
+               return 0;
+       if (!nfs_mount_proto_family(options, &mnt_family))
+               return 0;
+
        mounthost = po_get(options, "mounthost");
-       if (!mounthost)
-               return 1;
+       if (mounthost == NULL) {
+               if (nfs_family == mnt_family)
+                       return 1;
+               mounthost = (char *)nfs_hostname;
+       }
 
-       if (!nfs_name_to_address(mounthost, sap, &salen)) {
+       if (!nfs_lookup(mounthost, mnt_family, sap, &salen)) {
                nfs_error(_("%s: unable to determine mount server's address"),
                                progname);
                return 0;
@@ -320,13 +338,16 @@ static int nfs_set_version(struct nfsmount_info *mi)
  */
 static int nfs_validate_options(struct nfsmount_info *mi)
 {
-       struct sockaddr *sap = (struct sockaddr *)&mi->address;
+       struct sockaddr *sap = &mi->address.sa;
+       sa_family_t family;
 
        if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
                return 0;
 
+       if (!nfs_nfs_proto_family(mi->options, &family))
+               return 0;
        mi->salen = sizeof(mi->address);
-       if (!nfs_name_to_address(mi->hostname, sap, &mi->salen))
+       if (!nfs_lookup(mi->hostname, family, sap, &mi->salen))
                return 0;
 
        if (!nfs_set_version(mi))
@@ -453,12 +474,12 @@ static int nfs_construct_new_options(struct mount_options *options,
 static int
 nfs_rewrite_pmap_mount_options(struct mount_options *options)
 {
-       struct sockaddr_storage nfs_address;
-       struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_address;
+       union nfs_sockaddr nfs_address;
+       struct sockaddr *nfs_saddr = &nfs_address.sa;
        socklen_t nfs_salen = sizeof(nfs_address);
        struct pmap nfs_pmap;
-       struct sockaddr_storage mnt_address;
-       struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
+       union nfs_sockaddr mnt_address;
+       struct sockaddr *mnt_saddr = &mnt_address.sa;
        socklen_t mnt_salen = sizeof(mnt_address);
        struct pmap mnt_pmap;
        char *option;
@@ -559,7 +580,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
                return result;
        }
 
-       if (!nfs_fix_mounthost_option(options)) {
+       if (!nfs_fix_mounthost_option(options, mi->hostname)) {
                errno = EINVAL;
                goto out_fail;
        }
@@ -594,7 +615,7 @@ out_fail:
  */
 static int nfs_try_mount_v4(struct nfsmount_info *mi)
 {
-       struct sockaddr *sap = (struct sockaddr *)&mi->address;
+       struct sockaddr *sap = &mi->address.sa;
        struct mount_options *options = po_dup(mi->options);
        int result = 0;