/* * 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, const char *nfs_hostname) { 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 == NULL) { if (nfs_family == mnt_family) return 1; mounthost = (char *)nfs_hostname; } if (!nfs_lookup(mounthost, mnt_family, sap, &salen)) { nfs_error(_("%s: unable to determine mount server's address"), progname); return 0; } return nfs_append_generic_address_option(sap, salen, "mountaddr", options); }
/* * Returns the transport protocol to use for the mount service * * Returns the IPPROTO_ value specified by the mountproto option, or * if that doesn't exist, the IPPROTO_ value specified for NFS * itself. */ static unsigned short nfs_mount_protocol(struct mount_options *options) { char *option; option = po_get(options, "mountproto"); if (option) { if (strcmp(option, "tcp") == 0) return IPPROTO_TCP; if (strcmp(option, "udp") == 0) return IPPROTO_UDP; } return nfs_nfs_version(options); }
/* * Returns the NFS transport protocol specified by the given mount options * * Returns the IPPROTO_ value specified by the given mount options, or * IPPROTO_UDP if all fails. */ static unsigned short nfs_nfs_protocol(struct mount_options *options) { char *option; switch (po_rightmost(options, nfs_transport_opttbl)) { case 1: /* tcp */ return IPPROTO_TCP; case 2: /* proto */ option = po_get(options, "proto"); if (option) { if (strcmp(option, "tcp") == 0) return IPPROTO_TCP; if (strcmp(option, "udp") == 0) return IPPROTO_UDP; } } return IPPROTO_UDP; }
/* * Set up mandatory non-version specific NFS mount options. * * Returns 1 if successful; otherwise zero. */ static int nfs_validate_options(struct nfsmount_info *mi) { struct addrinfo hint = { .ai_protocol = (int)IPPROTO_UDP, }; sa_family_t family; int error; char *option; if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL)) return 0; if (!nfs_nfs_proto_family(mi->options, &family)) return 0; hint.ai_family = (int)family; error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address); if (error != 0) { nfs_error(_("%s: Failed to resolve server %s: %s"), progname, mi->hostname, gai_strerror(error)); mi->address = NULL; return 0; } if (!nfs_set_version(mi)) return 0; if (!nfs_append_sloppy_option(mi->options)) return 0; if (!nfs_append_addr_option(mi->address->ai_addr, mi->address->ai_addrlen, mi->options)) return 0; option = po_get(mi->options, "srcaddr"); if (option) { struct local_bind_info *local_ip; local_ip = malloc(sizeof(*local_ip)); memset(local_ip, 0, sizeof(*local_ip)); if (nfs_parse_local_bind(local_ip, option, mi->address->ai_addr->sa_family) >= 0) { mi->local_ip = local_ip; } else { free(local_ip); return 0; } } return 1; } /* * Get NFS/mnt server addresses from mount options * * Returns 1 and fills in @nfs_saddr, @nfs_salen, @mnt_saddr, and @mnt_salen * if all goes well; otherwise zero. */ static int nfs_extract_server_addresses(struct mount_options *options, struct sockaddr *nfs_saddr, socklen_t *nfs_salen, struct sockaddr *mnt_saddr, socklen_t *mnt_salen) { char *option; option = po_get(options, "addr"); if (option == NULL) return 0; if (!nfs_string_to_sockaddr(option, nfs_saddr, nfs_salen)) return 0; option = po_get(options, "mountaddr"); if (option == NULL) { memcpy(mnt_saddr, nfs_saddr, *nfs_salen); *mnt_salen = *nfs_salen; } else if (!nfs_string_to_sockaddr(option, mnt_saddr, mnt_salen)) return 0; return 1; }