Add support for IPv6 addresses to the pNFS "-p" option.
This patch adds code to handle IPv6 addresses returned by getaddrinfo() for the host entries in the "-p" command line argument. If the IPv6 address is a link local address, only use it if it is the only address for the host. This is done since there is no way to know if the NFSv4.1 pNFS client is in the same scope zone as the MDS. inet_ntop() is used for the IPv6 address translation, since the client will have no use for the scope zone suffix and inet_ntop() does not put this in the address string. Discussed with: bu7cher@yandex.ru
This commit is contained in:
parent
29c3c889cb
commit
35f38de3c9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=336795
@ -1179,14 +1179,16 @@ backup_stable(__unused int signo)
|
|||||||
static void
|
static void
|
||||||
parse_dsserver(const char *optionarg, struct nfsd_nfsd_args *nfsdargp)
|
parse_dsserver(const char *optionarg, struct nfsd_nfsd_args *nfsdargp)
|
||||||
{
|
{
|
||||||
char *ad, *cp, *cp2, *dsaddr, *dshost, *dspath, *dsvol, nfsprt[9];
|
char *cp, *cp2, *dsaddr, *dshost, *dspath, *dsvol, nfsprt[9];
|
||||||
char *mdspath, *mdsp;
|
char *mdspath, *mdsp, ip6[INET6_ADDRSTRLEN];
|
||||||
|
const char *ad;
|
||||||
int ecode;
|
int ecode;
|
||||||
u_int adsiz, dsaddrcnt, dshostcnt, dspathcnt, hostsiz, pathsiz;
|
u_int adsiz, dsaddrcnt, dshostcnt, dspathcnt, hostsiz, pathsiz;
|
||||||
u_int mdspathcnt;
|
u_int mdspathcnt;
|
||||||
size_t dsaddrsiz, dshostsiz, dspathsiz, nfsprtsiz, mdspathsiz;
|
size_t dsaddrsiz, dshostsiz, dspathsiz, nfsprtsiz, mdspathsiz;
|
||||||
struct addrinfo hints, *ai_tcp;
|
struct addrinfo hints, *ai_tcp, *res;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
struct sockaddr_in6 sin6;
|
||||||
|
|
||||||
cp = strdup(optionarg);
|
cp = strdup(optionarg);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
@ -1275,22 +1277,55 @@ parse_dsserver(const char *optionarg, struct nfsd_nfsd_args *nfsdargp)
|
|||||||
|
|
||||||
/* Get the fully qualified domain name and IP address. */
|
/* Get the fully qualified domain name and IP address. */
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
|
||||||
hints.ai_family = AF_INET;
|
hints.ai_family = PF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_protocol = IPPROTO_TCP;
|
hints.ai_protocol = IPPROTO_TCP;
|
||||||
ecode = getaddrinfo(cp, NULL, &hints, &ai_tcp);
|
ecode = getaddrinfo(cp, NULL, &hints, &ai_tcp);
|
||||||
if (ecode != 0)
|
if (ecode != 0)
|
||||||
err(1, "getaddrinfo pnfs: %s %s", cp,
|
err(1, "getaddrinfo pnfs: %s %s", cp,
|
||||||
gai_strerror(ecode));
|
gai_strerror(ecode));
|
||||||
if (ai_tcp->ai_addr->sa_family != AF_INET ||
|
ad = NULL;
|
||||||
ai_tcp->ai_addrlen < sizeof(sin))
|
for (res = ai_tcp; res != NULL; res = res->ai_next) {
|
||||||
err(1, "getaddrinfo() returned non-INET address");
|
if (res->ai_addr->sa_family == AF_INET) {
|
||||||
/* Mips cares about sockaddr_in alignment, so copy the addr. */
|
if (res->ai_addrlen < sizeof(sin))
|
||||||
memcpy(&sin, ai_tcp->ai_addr, sizeof(sin));
|
err(1, "getaddrinfo() returned "
|
||||||
|
"undersized IPv4 address");
|
||||||
|
/*
|
||||||
|
* Mips cares about sockaddr_in alignment,
|
||||||
|
* so copy the address.
|
||||||
|
*/
|
||||||
|
memcpy(&sin, res->ai_addr, sizeof(sin));
|
||||||
|
ad = inet_ntoa(sin.sin_addr);
|
||||||
|
break;
|
||||||
|
} else if (res->ai_family == AF_INET6) {
|
||||||
|
if (res->ai_addrlen < sizeof(sin6))
|
||||||
|
err(1, "getaddrinfo() returned "
|
||||||
|
"undersized IPv6 address");
|
||||||
|
/*
|
||||||
|
* Mips cares about sockaddr_in6 alignment,
|
||||||
|
* so copy the address.
|
||||||
|
*/
|
||||||
|
memcpy(&sin6, res->ai_addr, sizeof(sin6));
|
||||||
|
ad = inet_ntop(AF_INET6, &sin6.sin6_addr, ip6,
|
||||||
|
sizeof(ip6));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX
|
||||||
|
* Since a link local address will only
|
||||||
|
* work if the client and DS are in the
|
||||||
|
* same scope zone, only use it if it is
|
||||||
|
* the only address.
|
||||||
|
*/
|
||||||
|
if (ad != NULL &&
|
||||||
|
!IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ad == NULL)
|
||||||
|
err(1, "No IP address for %s", cp);
|
||||||
|
|
||||||
/* Append this address to dsaddr. */
|
/* Append this address to dsaddr. */
|
||||||
ad = inet_ntoa(sin.sin_addr);
|
|
||||||
adsiz = strlen(ad);
|
adsiz = strlen(ad);
|
||||||
if (dsaddrcnt + adsiz + nfsprtsiz + 1 > dsaddrsiz) {
|
if (dsaddrcnt + adsiz + nfsprtsiz + 1 > dsaddrsiz) {
|
||||||
dsaddrsiz *= 2;
|
dsaddrsiz *= 2;
|
||||||
|
Loading…
Reference in New Issue
Block a user