]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/network.c
mount: silently fails when bad option values are given
[nfs-utils.git] / utils / mount / network.c
index e3ad5c26a71da5d915fe45f28ae5d32e8dbc9827..d9903ed44c492cc3fccedfa04ea2b38ab5a3b83f 100644 (file)
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <sys/stat.h>
 #include <netinet/in.h>
 #include <rpc/rpc.h>
 #include <rpc/pmap_prot.h>
 #include <rpc/pmap_clnt.h>
 
+#include "sockaddr.h"
 #include "xcommon.h"
 #include "mount.h"
 #include "nls.h"
 #define CONNECT_TIMEOUT        (20)
 #define MOUNT_TIMEOUT  (30)
 
-#if SIZEOF_SOCKLEN_T - 0 == 0
-#define socklen_t unsigned int
-#endif
-
 extern int nfs_mount_data_version;
 extern char *progname;
 extern int verbose;
@@ -540,8 +538,8 @@ static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
                          struct pmap *pmap, const unsigned long *versions,
                          const unsigned int *protos)
 {
-       struct sockaddr_storage address;
-       struct sockaddr *saddr = (struct sockaddr *)&address;
+       union nfs_sockaddr address;
+       struct sockaddr *saddr = &address.sa;
        const unsigned long prog = pmap->pm_prog, *p_vers;
        const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
        const u_short port = (u_short) pmap->pm_port;
@@ -831,8 +829,8 @@ int start_statd(void)
 int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
                      const struct pmap *pmap, const dirpath *argp)
 {
-       struct sockaddr_storage address;
-       struct sockaddr *saddr = (struct sockaddr *)&address;
+       union nfs_sockaddr address;
+       struct sockaddr *saddr = &address.sa;
        struct pmap mnt_pmap = *pmap;
        struct timeval timeout = {
                .tv_sec         = MOUNT_TIMEOUT >> 3,
@@ -859,7 +857,14 @@ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
                return 0;
        }
 
-       client->cl_auth = authunix_create_default();
+       client->cl_auth = nfs_authsys_create();
+       if (client->cl_auth == NULL) {
+               if (verbose)
+                       nfs_error(_("%s: Failed to create RPC auth handle"),
+                               progname);
+               CLNT_DESTROY(client);
+               return 0;
+       }
 
        res = CLNT_CALL(client, MOUNTPROC_UMNT,
                        (xdrproc_t)xdr_dirpath, (caddr_t)argp,
@@ -959,8 +964,10 @@ CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
        }
        if (clnt) {
                /* try to mount hostname:dirname */
-               clnt->cl_auth = authunix_create_default();
-               return clnt;
+               clnt->cl_auth = nfs_authsys_create();
+               if (clnt->cl_auth)
+                       return clnt;
+               CLNT_DESTROY(clnt);
        }
        return NULL;
 }
@@ -1205,6 +1212,8 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
                        return 1;
                }
        case PO_BAD_VALUE:
+               nfs_error(_("%s: invalid value for 'nfsprog=' option"),
+                               progname);
                return 0;
        }
 
@@ -1244,9 +1253,12 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
                        }
                        return 0;
                case PO_NOT_FOUND:
-                       nfs_error(_("%s: option parsing error\n"),
+                       nfs_error(_("%s: parsing error on 'vers=' option\n"),
                                        progname);
+                       return 0;
                case PO_BAD_VALUE:
+                       nfs_error(_("%s: invalid value for 'vers=' option"),
+                                       progname);
                        return 0;
                }
        case 4: /* nfsvers */
@@ -1258,9 +1270,12 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
                        }
                        return 0;
                case PO_NOT_FOUND:
-                       nfs_error(_("%s: option parsing error\n"),
+                       nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
                                        progname);
+                       return 0;
                case PO_BAD_VALUE:
+                       nfs_error(_("%s: invalid value for 'nfsvers=' option"),
+                                       progname);
                        return 0;
                }
        }
@@ -1275,7 +1290,8 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
 
 /*
  * Returns TRUE if @protocol contains a valid value for this option,
- * or FALSE if the option was specified with an invalid value.
+ * or FALSE if the option was specified with an invalid value. On
+ * error, errno is set.
  */
 int
 nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol)
@@ -1292,8 +1308,13 @@ nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol)
                return 1;
        case 2: /* proto */
                option = po_get(options, "proto");
-               if (option != NULL)
-                       return nfs_get_proto(option, &family, protocol);
+               if (option != NULL) {
+                       if (!nfs_get_proto(option, &family, protocol)) {
+                               errno = EPROTONOSUPPORT;
+                               return 0;
+                       }
+                       return 1;
+               }
        }
 
        /*
@@ -1323,6 +1344,8 @@ nfs_nfs_port(struct mount_options *options, unsigned long *port)
                        return 1;
                }
        case PO_BAD_VALUE:
+               nfs_error(_("%s: invalid value for 'port=' option"),
+                               progname);
                return 0;
        }
 
@@ -1334,38 +1357,59 @@ nfs_nfs_port(struct mount_options *options, unsigned long *port)
        return 1;
 }
 
+#ifdef IPV6_SUPPORTED
+sa_family_t    config_default_family = AF_UNSPEC;
+
+static int
+nfs_verify_family(sa_family_t family)
+{
+       return 1;
+}
+#else /* IPV6_SUPPORTED */
+sa_family_t    config_default_family = AF_INET;
+
+static int
+nfs_verify_family(sa_family_t family)
+{
+       if (family != AF_INET)
+               return 0;
+
+       return 1;
+}
+#endif /* IPV6_SUPPORTED */
+
 /*
  * Returns TRUE and fills in @family if a valid NFS protocol option
- * is found, or FALSE if the option was specified with an invalid value.
+ * is found, or FALSE if the option was specified with an invalid value
+ * or if the protocol family isn't supported. On error, errno is set.
  */
 int nfs_nfs_proto_family(struct mount_options *options,
                                sa_family_t *family)
 {
        unsigned long protocol;
        char *option;
-
-#ifdef HAVE_LIBTIRPC
-       *family = AF_UNSPEC;
-#else
-       *family = AF_INET;
-#endif
+       sa_family_t tmp_family = config_default_family;
 
        switch (po_rightmost(options, nfs_transport_opttbl)) {
        case 0: /* udp */
-               return 1;
        case 1: /* tcp */
+               /* for compatibility; these are always AF_INET */
+               *family = AF_INET;
                return 1;
        case 2: /* proto */
                option = po_get(options, "proto");
-               if (option != NULL)
-                       return nfs_get_proto(option, family, &protocol);
+               if (option != NULL &&
+                   !nfs_get_proto(option, &tmp_family, &protocol))
+                       goto out_err;
        }
 
-       /*
-        * NFS transport protocol wasn't specified.  Return the
-        * default address family.
-        */
+       if (!nfs_verify_family(tmp_family))
+               goto out_err;
+       *family = tmp_family;
        return 1;
+out_err:
+       errno = EAFNOSUPPORT;
+       return 0;
 }
 
 /*
@@ -1389,6 +1433,8 @@ nfs_mount_program(struct mount_options *options, unsigned long *program)
                        return 1;
                }
        case PO_BAD_VALUE:
+               nfs_error(_("%s: invalid value for 'mountprog=' option"),
+                               progname);
                return 0;
        }
 
@@ -1418,6 +1464,8 @@ nfs_mount_version(struct mount_options *options, unsigned long *version)
                        return 1;
                }
        case PO_BAD_VALUE:
+               nfs_error(_("%s: invalid value for 'mountvers=' option"),
+                               progname);
                return 0;
        }
 
@@ -1431,7 +1479,8 @@ nfs_mount_version(struct mount_options *options, unsigned long *version)
 
 /*
  * Returns TRUE if @protocol contains a valid value for this option,
- * or FALSE if the option was specified with an invalid value.
+ * or FALSE if the option was specified with an invalid value. On
+ * error, errno is set.
  */
 static int
 nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
@@ -1440,8 +1489,13 @@ nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
        char *option;
 
        option = po_get(options, "mountproto");
-       if (option != NULL)
-               return nfs_get_proto(option, &family, protocol);
+       if (option != NULL) {
+               if (!nfs_get_proto(option, &family, protocol)) {
+                       errno = EPROTONOSUPPORT;
+                       return 0;
+               }
+               return 1;
+       }
 
        /*
         * MNT transport protocol wasn't specified.  If the NFS
@@ -1470,6 +1524,8 @@ nfs_mount_port(struct mount_options *options, unsigned long *port)
                        return 1;
                }
        case PO_BAD_VALUE:
+               nfs_error(_("%s: invalid value for 'mountport=' option"),
+                               progname);
                return 0;
        }
 
@@ -1483,23 +1539,25 @@ nfs_mount_port(struct mount_options *options, unsigned long *port)
 
 /*
  * Returns TRUE and fills in @family if a valid MNT protocol option
- * is found, or FALSE if the option was specified with an invalid value.
+ * is found, or FALSE if the option was specified with an invalid value
+ * or if the protocol family isn't supported. On error, errno is set.
  */
 int nfs_mount_proto_family(struct mount_options *options,
                                sa_family_t *family)
 {
        unsigned long protocol;
        char *option;
-
-#ifdef HAVE_LIBTIRPC
-       *family = AF_UNSPEC;
-#else
-       *family = AF_INET;
-#endif
+       sa_family_t tmp_family = config_default_family;
 
        option = po_get(options, "mountproto");
-       if (option != NULL)
-               return nfs_get_proto(option, family, &protocol);
+       if (option != NULL) {
+               if (!nfs_get_proto(option, &tmp_family, &protocol))
+                       goto out_err;
+               if (!nfs_verify_family(tmp_family))
+                       goto out_err;
+               *family = tmp_family;
+               return 1;
+       }
 
        /*
         * MNT transport protocol wasn't specified.  If the NFS
@@ -1508,6 +1566,9 @@ int nfs_mount_proto_family(struct mount_options *options,
         * NFS.
         */
        return nfs_nfs_proto_family(options, family);
+out_err:
+       errno = EAFNOSUPPORT;
+       return 0;
 }
 
 /**