]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/stropts.c
Change the append_addr_option() function to support sending either IPv4
[nfs-utils.git] / utils / mount / stropts.c
index 3564f15c098dbe434727f8dc9f6a76ede8ab2674..f856998f569b9201d11f0f0398d3592b7ad95fd4 100644 (file)
 #include <errno.h>
 #include <netdb.h>
 #include <time.h>
+
 #include <sys/socket.h>
 #include <sys/mount.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #include "xcommon.h"
 #include "mount.h"
@@ -45,6 +48,7 @@
 #include "error.h"
 #include "network.h"
 #include "parse_opt.h"
+#include "version.h"
 
 #ifdef HAVE_RPCSVC_NFS_PROT_H
 #include <rpcsvc/nfs_prot.h>
@@ -76,6 +80,7 @@
 extern int nfs_mount_data_version;
 extern char *progname;
 extern int verbose;
+extern int sloppy;
 
 struct nfsmount_info {
        const char              *spec,          /* server:/path */
@@ -189,6 +194,37 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
        return time(NULL) + (time_t)(timeout_minutes * 60);
 }
 
+/*
+ * Convert the passed-in sockaddr-style address to presentation
+ * format, then append an option of the form "keyword=address".
+ *
+ * Returns 1 if the option was appended successfully; otherwise zero.
+ */
+static int nfs_append_generic_address_option(const struct sockaddr *sap,
+                                            const socklen_t salen,
+                                            const char *keyword,
+                                            struct mount_options *options)
+{
+       char address[NI_MAXHOST];
+       char new_option[512];
+
+       if (!nfs_present_sockaddr(sap, salen, address, sizeof(address)))
+               goto out_err;
+
+       if (snprintf(new_option, sizeof(new_option), "%s=%s",
+                                       keyword, address) >= sizeof(new_option))
+               goto out_err;
+
+       if (po_append(options, new_option) != PO_SUCCEEDED)
+               goto out_err;
+
+       return 1;
+
+out_err:
+       nfs_error(_("%s: failed to construct %s option"), progname, keyword);
+       return 0;
+}
+
 /*
  * Append the 'addr=' option to the options string to pass a resolved
  * server address to the kernel.  After a successful mount, this address
@@ -201,19 +237,12 @@ static time_t nfs_parse_retry_option(struct mount_options *options,
  * Returns 1 if 'addr=' option appended successfully;
  * otherwise zero.
  */
-static int append_addr_option(struct sockaddr_in *saddr,
-                          struct mount_options *options)
+static int nfs_append_addr_option(const struct sockaddr *sap,
+                                 socklen_t salen,
+                                 struct mount_options *options)
 {
-       char new_option[24];
-
        po_remove_all(options, "addr");
-
-       snprintf(new_option, sizeof(new_option) - 1,
-                       "addr=%s", inet_ntoa(saddr->sin_addr));
-
-       if (po_append(options, new_option) == PO_SUCCEEDED)
-               return 1;
-       return 0;
+       return nfs_append_generic_address_option(sap, salen, "addr", options);
 }
 
 /*
@@ -287,6 +316,16 @@ static int verify_lock_option(struct mount_options *options)
        return 1;
 }
 
+static int nfs_append_sloppy_option(struct mount_options *options)
+{
+       if (!sloppy || linux_version_code() < MAKE_VERSION(2, 6, 27))
+               return 1;
+
+       if (po_append(options, "sloppy") == PO_FAILED)
+               return 0;
+       return 1;
+}
+
 /*
  * Set up mandatory NFS mount options.
  *
@@ -309,10 +348,11 @@ static int nfs_validate_options(struct nfsmount_info *mi)
                        return 0;
        }
 
-       if (!append_addr_option(&saddr, mi->options))
+       if (!nfs_append_sloppy_option(mi->options))
                return 0;
 
-       return 1;
+       return nfs_append_addr_option((struct sockaddr *)&saddr,
+                                       sizeof(saddr), mi->options);
 }
 
 /*
@@ -357,9 +397,12 @@ static struct mount_options *rewrite_mount_options(char *str)
        int p;
 
        options = po_split(str);
-       if (!options)
+       if (!options) {
+               errno = EFAULT;
                return NULL;
+       }
 
+       errno = EINVAL;
        option = po_get(options, "addr");
        if (option) {
                nfs_server.saddr.sin_family = AF_INET;
@@ -426,7 +469,7 @@ static struct mount_options *rewrite_mount_options(char *str)
        po_remove_all(options, "udp");
 
        if (!probe_bothports(&mnt_server, &nfs_server)) {
-               rpc_mount_errors("rpcbind", 0, 0);
+               errno = ESPIPE;
                goto err;
        }
 
@@ -452,6 +495,7 @@ static struct mount_options *rewrite_mount_options(char *str)
 
        }
 
+       errno = 0;
        return options;
 
 err:
@@ -498,10 +542,8 @@ static int nfs_retry_nfs23mount(struct nfsmount_info *mi)
        char **extra_opts = mi->extra_opts;
 
        retry_options = rewrite_mount_options(*extra_opts);
-       if (!retry_options) {
-               errno = EIO;
+       if (!retry_options)
                return 0;
-       }
 
        if (po_join(retry_options, &retry_str) == PO_FAILED) {
                po_destroy(retry_options);