+ switch (po_get_numeric(options, "port", &tmp)) {
+ case PO_NOT_FOUND:
+ break;
+ case PO_FOUND:
+ if (tmp >= 1 && tmp <= 65535) {
+ *port = tmp;
+ return 1;
+ }
+ case PO_BAD_VALUE:
+ nfs_error(_("%s: invalid value for 'port=' option"),
+ progname);
+ return 0;
+ }
+
+ /*
+ * NFS service port wasn't specified. The pmap port value
+ * will be filled in later by an rpcbind query in this case.
+ */
+ *port = 0;
+ 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
+ * 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;
+ sa_family_t tmp_family = config_default_family;
+
+ switch (po_rightmost(options, nfs_transport_opttbl)) {
+ case 0: /* udp */
+ case 1: /* tcp */
+ case 2: /* rdma */
+ /* for compatibility; these are always AF_INET */
+ *family = AF_INET;
+ return 1;
+ case 3: /* proto */
+ option = po_get(options, "proto");
+ if (option != NULL &&
+ !nfs_get_proto(option, &tmp_family, &protocol)) {
+
+ nfs_error(_("%s: Failed to find '%s' protocol"),
+ progname, option);
+ errno = EPROTONOSUPPORT;
+ return 0;
+ }
+ }
+
+ if (!nfs_verify_family(tmp_family))
+ goto out_err;
+ *family = tmp_family;
+ return 1;
+out_err:
+ errno = EAFNOSUPPORT;