IPv6 Support. Add ipv6 support to the socket management.

IPv6 addresses are specified in [...] format.

iscsi://10.1.1.27/...
iscsi://10.1.1.27:3260/...
iscsi://[fec0::1]/...
iscsi://[fec0::1]:3260/...
This commit is contained in:
Ronnie Sahlberg
2011-01-08 16:09:14 +11:00
parent 7d702357d1
commit aa916b7802

View File

@@ -46,9 +46,8 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
int tpgt = -1; int tpgt = -1;
int port = 3260; int port = 3260;
char *str; char *str;
char *addr; char *addr, *host;
struct sockaddr_storage s; struct addrinfo *ai = NULL;
struct sockaddr_in *sin = (struct sockaddr_in *)&s;
int socksize; int socksize;
if (iscsi->fd != -1) { if (iscsi->fd != -1) {
@@ -63,60 +62,74 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
"Failed to strdup portal address."); "Failed to strdup portal address.");
return -1; return -1;
} }
host = addr;
/* check if we have a target portal group tag */ /* check if we have a target portal group tag */
str = rindex(addr, ','); str = rindex(host, ',');
if (str != NULL) { if (str != NULL) {
tpgt = atoi(str+1); tpgt = atoi(str+1);
str[0] = 0; str[0] = 0;
} }
/* XXX need handling for {ipv6 addresses} */ str = rindex(host, ':');
/* for now, assume all is ipv4 */
str = rindex(addr, ':');
if (str != NULL) { if (str != NULL) {
port = atoi(str+1); if (index(str, ']') == NULL) {
str[0] = 0; if (str != NULL) {
port = atoi(str+1);
str[0] = 0;
}
}
} }
sin->sin_family = AF_INET; /* ipv6 in [...] form ? */
sin->sin_port = htons(port); if (host[0] == '[') {
if (inet_pton(AF_INET, addr, &sin->sin_addr) != 1) { host ++;
struct hostent *he; str = index(host, ']');
if (str == NULL) {
he = gethostbyname(addr);
if (he == NULL) {
iscsi_set_error(iscsi, "Invalid target:%s "
"Failed to resolve hostname.", addr);
free(addr); free(addr);
iscsi_set_error(iscsi, "Invalid target:%s "
"Missing ']' in IPv6 address", portal);
return -1; return -1;
} }
if (he->h_addrtype != AF_INET) { *str = 0;
iscsi_set_error(iscsi, "Invalid target:%s "
"Can not resolve into IPv4.", addr);
free(addr);
return -1;
}
sin->sin_addr.s_addr = *(uint32_t *)he->h_addr_list[0];
} }
/* is it a hostname ? */
if (getaddrinfo(host, NULL, NULL, &ai) != 0) {
free(addr);
iscsi_set_error(iscsi, "Invalid target:%s "
"Can not resolv into IPv4/v6.", portal);
return -1;
}
free(addr); free(addr);
switch (s.ss_family) { switch (ai->ai_family) {
case AF_INET: case AF_INET:
iscsi->fd = socket(AF_INET, SOCK_STREAM, 0);
socksize = sizeof(struct sockaddr_in); socksize = sizeof(struct sockaddr_in);
((struct sockaddr_in *)(ai->ai_addr))->sin_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
((struct sockaddr_in *)(ai->ai_addr))->sin_len = socksize;
#endif
break;
case AF_INET6:
socksize = sizeof(struct sockaddr_in6);
((struct sockaddr_in6 *)(ai->ai_addr))->sin6_port = htons(port);
#ifdef HAVE_SOCK_SIN_LEN
((struct sockaddr_in6 *)(ai->ai_addr))->sin6_len = socksize;
#endif
break; break;
default: default:
iscsi_set_error(iscsi, "Unknown address family :%d. " iscsi_set_error(iscsi, "Unknown address family :%d. "
"Only IPv4 supported so far.", s.ss_family); "Only IPv4/IPv6 supported so far.",
ai->ai_family);
freeaddrinfo(ai);
return -1; return -1;
} }
#ifdef HAVE_SOCK_SIN_LEN
s.ss_len = socksize;
#endif
iscsi->fd = socket(ai->ai_family, SOCK_STREAM, 0);
if (iscsi->fd == -1) { if (iscsi->fd == -1) {
freeaddrinfo(ai);
iscsi_set_error(iscsi, "Failed to open iscsi socket. " iscsi_set_error(iscsi, "Failed to open iscsi socket. "
"Errno:%s(%d).", strerror(errno), errno); "Errno:%s(%d).", strerror(errno), errno);
return -1; return -1;
@@ -128,15 +141,17 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
set_nonblocking(iscsi->fd); set_nonblocking(iscsi->fd);
if (connect(iscsi->fd, (struct sockaddr *)&s, socksize) != 0 if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
&& errno != EINPROGRESS) { && errno != EINPROGRESS) {
iscsi_set_error(iscsi, "Connect failed with errno : " iscsi_set_error(iscsi, "Connect failed with errno : "
"%s(%d)", strerror(errno), errno); "%s(%d)", strerror(errno), errno);
close(iscsi->fd); close(iscsi->fd);
iscsi->fd = -1; iscsi->fd = -1;
freeaddrinfo(ai);
return -1; return -1;
} }
freeaddrinfo(ai);
return 0; return 0;
} }