CLEANUP: minor cleanup in str2sa_range() and str2ip()

Don't use a statically allocated address both for str2ip and str2sa_range,
use the same. The inet and unix code paths have been splitted a little
better to improve readability.
This commit is contained in:
Willy Tarreau 2013-03-10 19:27:44 +01:00
parent 2de5dae80e
commit c120c8d347
2 changed files with 62 additions and 66 deletions

View File

@ -212,7 +212,7 @@ extern const char *invalid_char(const char *name);
extern const char *invalid_domainchar(const char *name); extern const char *invalid_domainchar(const char *name);
/* /*
* converts <str> to a struct sockaddr_storage* which is locally allocated. The * converts <str> to a struct sockaddr_storage* provided by the caller. The
* string is assumed to contain only an address, no port. The address can be a * string is assumed to contain only an address, no port. The address can be a
* dotted IPv4 address, an IPv6 address, a host name, or empty or "*" to * dotted IPv4 address, an IPv6 address, a host name, or empty or "*" to
* indicate INADDR_ANY. NULL is returned if the host part cannot be resolved. * indicate INADDR_ANY. NULL is returned if the host part cannot be resolved.
@ -220,7 +220,7 @@ extern const char *invalid_domainchar(const char *name);
* all other fields remain zero. The string is not supposed to be modified. * all other fields remain zero. The string is not supposed to be modified.
* The IPv6 '::' address is IN6ADDR_ANY. * The IPv6 '::' address is IN6ADDR_ANY.
*/ */
struct sockaddr_storage *str2ip(const char *str); struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage *sa);
/* /*
* converts <str> to a locally allocated struct sockaddr_storage *, and a * converts <str> to a locally allocated struct sockaddr_storage *, and a

View File

@ -504,7 +504,7 @@ const char *invalid_domainchar(const char *name) {
} }
/* /*
* converts <str> to a struct sockaddr_storage* which is locally allocated. The * converts <str> to a struct sockaddr_storage* provided by the caller. The
* string is assumed to contain only an address, no port. The address can be a * string is assumed to contain only an address, no port. The address can be a
* dotted IPv4 address, an IPv6 address, a host name, or empty or "*" to * dotted IPv4 address, an IPv6 address, a host name, or empty or "*" to
* indicate INADDR_ANY. NULL is returned if the host part cannot be resolved. * indicate INADDR_ANY. NULL is returned if the host part cannot be resolved.
@ -512,48 +512,47 @@ const char *invalid_domainchar(const char *name) {
* all other fields remain zero. The string is not supposed to be modified. * all other fields remain zero. The string is not supposed to be modified.
* The IPv6 '::' address is IN6ADDR_ANY. * The IPv6 '::' address is IN6ADDR_ANY.
*/ */
struct sockaddr_storage *str2ip(const char *str) struct sockaddr_storage *str2ip(const char *str, struct sockaddr_storage *sa)
{ {
static struct sockaddr_storage sa;
struct hostent *he; struct hostent *he;
memset(&sa, 0, sizeof(sa)); memset(sa, 0, sizeof(sa));
/* Any IPv6 address */ /* Any IPv6 address */
if (str[0] == ':' && str[1] == ':' && !str[2]) { if (str[0] == ':' && str[1] == ':' && !str[2]) {
sa.ss_family = AF_INET6; sa->ss_family = AF_INET6;
return &sa; return sa;
} }
/* Any IPv4 address */ /* Any IPv4 address */
if (!str[0] || (str[0] == '*' && !str[1])) { if (!str[0] || (str[0] == '*' && !str[1])) {
sa.ss_family = AF_INET; sa->ss_family = AF_INET;
return &sa; return sa;
} }
/* check for IPv6 first */ /* check for IPv6 first */
if (inet_pton(AF_INET6, str, &((struct sockaddr_in6 *)&sa)->sin6_addr)) { if (inet_pton(AF_INET6, str, &((struct sockaddr_in6 *)sa)->sin6_addr)) {
sa.ss_family = AF_INET6; sa->ss_family = AF_INET6;
return &sa; return sa;
} }
/* then check for IPv4 */ /* then check for IPv4 */
if (inet_pton(AF_INET, str, &((struct sockaddr_in *)&sa)->sin_addr)) { if (inet_pton(AF_INET, str, &((struct sockaddr_in *)sa)->sin_addr)) {
sa.ss_family = AF_INET; sa->ss_family = AF_INET;
return &sa; return sa;
} }
/* try to resolve an IPv4/IPv6 hostname */ /* try to resolve an IPv4/IPv6 hostname */
he = gethostbyname(str); he = gethostbyname(str);
if (he) { if (he) {
sa.ss_family = he->h_addrtype; sa->ss_family = he->h_addrtype;
switch (sa.ss_family) { switch (sa->ss_family) {
case AF_INET: case AF_INET:
((struct sockaddr_in *)&sa)->sin_addr = *(struct in_addr *) *(he->h_addr_list); ((struct sockaddr_in *)sa)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
return &sa; return sa;
case AF_INET6: case AF_INET6:
((struct sockaddr_in6 *)&sa)->sin6_addr = *(struct in6_addr *) *(he->h_addr_list); ((struct sockaddr_in6 *)sa)->sin6_addr = *(struct in6_addr *) *(he->h_addr_list);
return &sa; return sa;
} }
} }
#ifdef USE_GETADDRINFO #ifdef USE_GETADDRINFO
@ -568,14 +567,14 @@ struct sockaddr_storage *str2ip(const char *str)
hints.ai_protocol = 0; hints.ai_protocol = 0;
if (getaddrinfo(str, NULL, &hints, &result) == 0) { if (getaddrinfo(str, NULL, &hints, &result) == 0) {
sa.ss_family = result->ai_family; sa->ss_family = result->ai_family;
switch (result->ai_family) { switch (result->ai_family) {
case AF_INET: case AF_INET:
memcpy((struct sockaddr_in *)&sa, result->ai_addr, result->ai_addrlen); memcpy((struct sockaddr_in *)sa, result->ai_addr, result->ai_addrlen);
return &sa; return sa;
case AF_INET6: case AF_INET6:
memcpy((struct sockaddr_in6 *)&sa, result->ai_addr, result->ai_addrlen); memcpy((struct sockaddr_in6 *)sa, result->ai_addr, result->ai_addrlen);
return &sa; return sa;
} }
} }
@ -622,6 +621,7 @@ struct sockaddr_storage *str2ip(const char *str)
*/ */
struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char **err, const char *pfx) struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char **err, const char *pfx)
{ {
static struct sockaddr_storage ss;
struct sockaddr_storage *ret = NULL; struct sockaddr_storage *ret = NULL;
char *str2; char *str2;
char *port1, *port2; char *port1, *port2;
@ -637,7 +637,6 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
if (*str2 == '/') { if (*str2 == '/') {
/* unix socket */ /* unix socket */
static struct sockaddr_storage ss;
int prefix_path_len; int prefix_path_len;
int max_path_len; int max_path_len;
@ -662,48 +661,45 @@ struct sockaddr_storage *str2sa_range(const char *str, int *low, int *high, char
else { else {
strcpy(((struct sockaddr_un *)&ss)->sun_path, str2); strcpy(((struct sockaddr_un *)&ss)->sun_path, str2);
} }
ret = &ss;
goto out;
} }
else {
port1 = strrchr(str2, ':'); port1 = strrchr(str2, ':');
if (port1) if (port1)
*port1++ = '\0'; *port1++ = '\0';
else
port1 = "";
ret = str2ip(str2);
if (!ret) {
memprintf(err, "invalid address: '%s' in '%s'\n", str2, str);
goto out;
}
if (isdigit(*port1)) { /* single port or range */
port2 = strchr(port1, '-');
if (port2)
*port2++ = '\0';
else else
port2 = port1; port1 = "";
portl = atoi(port1);
porth = atoi(port2); if (str2ip(str2, &ss) == NULL) {
porta = portl; memprintf(err, "invalid address: '%s' in '%s'\n", str2, str);
} goto out;
else if (*port1 == '-') { /* negative offset */ }
portl = atoi(port1 + 1);
porta = -portl; if (isdigit(*port1)) { /* single port or range */
} port2 = strchr(port1, '-');
else if (*port1 == '+') { /* positive offset */ if (port2)
porth = atoi(port1 + 1); *port2++ = '\0';
porta = porth; else
} port2 = port1;
else if (*port1) { /* other any unexpected char */ portl = atoi(port1);
memprintf(err, "invalid character '%c' in port number '%s'\n", *port1, port1); porth = atoi(port2);
ret = NULL; porta = portl;
goto out; }
else if (*port1 == '-') { /* negative offset */
portl = atoi(port1 + 1);
porta = -portl;
}
else if (*port1 == '+') { /* positive offset */
porth = atoi(port1 + 1);
porta = porth;
}
else if (*port1) { /* other any unexpected char */
memprintf(err, "invalid character '%c' in port number '%s'\n", *port1, port1);
goto out;
}
set_host_port(&ss, porta);
} }
set_host_port(ret, porta); ret = &ss;
out: out:
if (low) if (low)
*low = portl; *low = portl;