MEDIUM: tools: make str2ip2() preserve existing ports
Often we need to call str2ip2() on an address which already contains a
port without replacing it, so let's ensure we preserve it even if the
family changes.
diff --git a/src/standard.c b/src/standard.c
index 5937b48..e25d38e 100644
--- a/src/standard.c
+++ b/src/standard.c
@@ -625,13 +625,14 @@
* all other fields remain zero. The string is not supposed to be modified.
* The IPv6 '::' address is IN6ADDR_ANY. If <resolve> is non-zero, the hostname
* is resolved, otherwise only IP addresses are resolved, and anything else
- * returns NULL.
+ * returns NULL. If the address contains a port, this one is preserved.
*/
struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, int resolve)
{
struct hostent *he;
/* max IPv6 length, including brackets and terminating NULL */
char tmpip[48];
+ int port = get_host_port(sa);
/* check IPv6 with square brackets */
if (str[0] == '[') {
@@ -664,6 +665,7 @@
sa->ss_family = AF_INET6;
else if (sa->ss_family != AF_INET6)
goto fail;
+ set_host_port(sa, port);
return sa;
}
@@ -671,6 +673,7 @@
if (!str[0] || (str[0] == '*' && !str[1])) {
if (!sa->ss_family || sa->ss_family == AF_UNSPEC)
sa->ss_family = AF_INET;
+ set_host_port(sa, port);
return sa;
}
@@ -678,6 +681,7 @@
if ((!sa->ss_family || sa->ss_family == AF_UNSPEC || sa->ss_family == AF_INET6) &&
inet_pton(AF_INET6, str, &((struct sockaddr_in6 *)sa)->sin6_addr)) {
sa->ss_family = AF_INET6;
+ set_host_port(sa, port);
return sa;
}
@@ -685,6 +689,7 @@
if ((!sa->ss_family || sa->ss_family == AF_UNSPEC || sa->ss_family == AF_INET) &&
inet_pton(AF_INET, str, &((struct sockaddr_in *)sa)->sin_addr)) {
sa->ss_family = AF_INET;
+ set_host_port(sa, port);
return sa;
}
@@ -714,9 +719,11 @@
switch (result->ai_family) {
case AF_INET:
memcpy((struct sockaddr_in *)sa, result->ai_addr, result->ai_addrlen);
+ set_host_port(sa, port);
return sa;
case AF_INET6:
memcpy((struct sockaddr_in6 *)sa, result->ai_addr, result->ai_addrlen);
+ set_host_port(sa, port);
return sa;
}
}
@@ -736,9 +743,11 @@
switch (sa->ss_family) {
case AF_INET:
((struct sockaddr_in *)sa)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
+ set_host_port(sa, port);
return sa;
case AF_INET6:
((struct sockaddr_in6 *)sa)->sin6_addr = *(struct in6_addr *) *(he->h_addr_list);
+ set_host_port(sa, port);
return sa;
}
}