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:
79
lib/socket.c
79
lib/socket.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user