X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fnetwork.c;h=d61242798f6a7153472cb132fb54927a602cb4d1;hp=e3ad5c26a71da5d915fe45f28ae5d32e8dbc9827;hb=f99d1b8e8768ab96b51bed52f21a626ac9a4797f;hpb=e9ab22a79e385babb16623a9260bda358291c80d diff --git a/utils/mount/network.c b/utils/mount/network.c index e3ad5c2..d612427 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -37,11 +37,13 @@ #include #include #include +#include #include #include #include #include +#include "sockaddr.h" #include "xcommon.h" #include "mount.h" #include "nls.h" @@ -51,15 +53,12 @@ #include "parse_opt.h" #include "network.h" #include "conffile.h" +#include "nfslib.h" #define PMAP_TIMEOUT (10) #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; @@ -84,6 +83,7 @@ static const char *nfs_nfs_pgmtbl[] = { static const char *nfs_transport_opttbl[] = { "udp", "tcp", + "rdma", "proto", NULL, }; @@ -540,8 +540,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 +831,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 +859,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 +966,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 +1214,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 +1255,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 +1272,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 +1292,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) @@ -1290,10 +1308,20 @@ nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol) case 1: /* tcp */ *protocol = IPPROTO_TCP; return 1; - case 2: /* proto */ + case 2: /* rdma */ + *protocol = NFSPROTO_RDMA; + return 1; + case 3: /* 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; + nfs_error(_("%s: Failed to find '%s' protocol"), + progname, option); + return 0; + } + return 1; + } } /* @@ -1323,6 +1351,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 +1364,65 @@ 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 UNUSED(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 */ + case 2: /* rdma */ + /* for compatibility; these are always AF_INET */ + *family = AF_INET; return 1; - case 2: /* proto */ + case 3: /* 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)) { + + nfs_error(_("%s: Failed to find '%s' protocol"), + progname, option); + errno = EPROTONOSUPPORT; + return 0; + } } - /* - * 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 +1446,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 +1477,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 +1492,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 +1502,15 @@ 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; + nfs_error(_("%s: Failed to find '%s' protocol"), + progname, option); + return 0; + } + return 1; + } /* * MNT transport protocol wasn't specified. If the NFS @@ -1470,6 +1539,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 +1554,29 @@ 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)) { + nfs_error(_("%s: Failed to find '%s' protocol"), + progname, option); + errno = EPROTONOSUPPORT; + 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 +1585,9 @@ int nfs_mount_proto_family(struct mount_options *options, * NFS. */ return nfs_nfs_proto_family(options, family); +out_err: + errno = EAFNOSUPPORT; + return 0; } /**