From a448886485ea89efed2996838be6ac42b4dd81a9 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Mon, 3 Apr 2017 14:50:14 -0400 Subject: [PATCH] [core] inet_pton(), inet_ntop() on (sock_addr *) shared code to provide inet_pton() and inet_ntop() behavior on lighttpd (sock_addr *) and (buffer *) data structures. --- src/http-header-glue.c | 13 +++--- src/inet_ntop_cache.c | 89 ++++++++++++++++++++++++++++++++++++++++-- src/inet_ntop_cache.h | 7 ++++ src/mod_proxy.c | 21 ++-------- src/request.c | 27 ++++--------- src/sys-socket.h | 14 +++++++ 6 files changed, 122 insertions(+), 49 deletions(-) diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 7a928a64..535ef9ba 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -7,6 +7,7 @@ #include "log.h" #include "etag.h" #include "http_chunk.h" +#include "inet_ntop_cache.h" #include "response.h" #include "stat_cache.h" @@ -1536,8 +1537,8 @@ int http_cgi_headers (server *srv, connection *con, http_cgi_opts *opts, http_cg break; } } - s = inet_ntop(AF_INET6, (const void *) &(addr->ipv6.sin6_addr), - b2, sizeof(b2)-1); + s = sock_addr_inet_ntop(addr, b2, sizeof(b2)-1); + if (NULL == s) s = ""; break; #endif case AF_INET: @@ -1550,12 +1551,8 @@ int http_cgi_headers (server *srv, connection *con, http_cgi_opts *opts, http_cg break; } } - #ifdef HAVE_IPV6 - s = inet_ntop(AF_INET, (const void *) &(addr->ipv4.sin_addr), - b2, sizeof(b2)-1); - #else - s = inet_ntoa(addr->ipv4.sin_addr); - #endif + s = sock_addr_inet_ntop(addr, b2, sizeof(b2)-1); + if (NULL == s) s = ""; break; default: s = ""; diff --git a/src/inet_ntop_cache.c b/src/inet_ntop_cache.c index 3d921404..3d0fa21e 100644 --- a/src/inet_ntop_cache.c +++ b/src/inet_ntop_cache.c @@ -1,13 +1,90 @@ #include "first.h" -#include "base.h" #include "inet_ntop_cache.h" -#include "sys-socket.h" +#include "base.h" +#include "sys-socket.h" #include - +#include #include + +int sock_addr_inet_pton(sock_addr *addr, const char *str, + int family, unsigned short port) +{ + if (AF_INET == family) { + memset(&addr->ipv4, 0, sizeof(struct sockaddr_in)); + addr->ipv4.sin_family = AF_INET; + addr->ipv4.sin_port = htons(port); + #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/ + return (0 != inet_aton(str, &addr->ipv4.sin_addr)); + #else + return ((addr->ipv4.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE); + #endif + } + #ifdef HAVE_IPV6 + else if (AF_INET6 == family) { + memset(&addr->ipv6, 0, sizeof(struct sockaddr_in6)); + addr->ipv6.sin6_family = AF_INET6; + addr->ipv6.sin6_port = htons(port); + return inet_pton(AF_INET6, str, &addr->ipv6.sin6_addr); + } + #endif + else { + errno = EAFNOSUPPORT; + return -1; + } +} + + +const char * sock_addr_inet_ntop(const sock_addr *addr, char *buf, socklen_t sz) +{ + if (addr->plain.sa_family == AF_INET) { + #if defined(HAVE_INET_PTON) /*(expect inet_ntop if inet_pton)*/ + return inet_ntop(AF_INET,(const void *)&addr->ipv4.sin_addr,buf,sz); + #else /*(inet_ntoa() not thread-safe)*/ + return inet_ntoa(addr->ipv4.sin_addr); + #endif + } + #ifdef HAVE_IPV6 + else if (addr->plain.sa_family == AF_INET6) { + return inet_ntop(AF_INET6,(const void *)&addr->ipv6.sin6_addr,buf,sz); + } + #endif + #ifdef HAVE_SYS_UN_H + else if (addr->plain.sa_family == AF_UNIX) { + return addr->un.sun_path; + } + #endif + else { + errno = EAFNOSUPPORT; + return NULL; + } +} + + +int sock_addr_inet_ntop_copy_buffer(buffer *b, const sock_addr *addr) +{ + /*(incur cost of extra copy to avoid potential extra memory allocation)*/ + char buf[UNIX_PATH_MAX]; + const char *s = sock_addr_inet_ntop(addr, buf, sizeof(buf)); + if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ + buffer_copy_string(b, s); + return 0; +} + + +int sock_addr_inet_ntop_append_buffer(buffer *b, const sock_addr *addr) +{ + /*(incur cost of extra copy to avoid potential extra memory allocation)*/ + char buf[UNIX_PATH_MAX]; + const char *s = sock_addr_inet_ntop(addr, buf, sizeof(buf)); + if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ + buffer_append_string(b, s); + return 0; +} + + const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { #ifdef HAVE_IPV6 size_t ndx = 0, i; @@ -28,13 +105,19 @@ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { if (i == INET_NTOP_CACHE_MAX) { /* not found in cache */ + const char *s; + + /* TODO: ndx is never modified above; + * inet_ntop_cache is effectively a 1-element cache */ i = ndx; + s = inet_ntop(addr->plain.sa_family, addr->plain.sa_family == AF_INET6 ? (const void *) &(addr->ipv6.sin6_addr) : (const void *) &(addr->ipv4.sin_addr), srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN); + if (NULL == s) return ""; srv->inet_ntop_cache[i].ts = srv->cur_ts; srv->inet_ntop_cache[i].family = addr->plain.sa_family; diff --git a/src/inet_ntop_cache.h b/src/inet_ntop_cache.h index da2d3973..2babc874 100644 --- a/src/inet_ntop_cache.h +++ b/src/inet_ntop_cache.h @@ -3,6 +3,13 @@ #include "first.h" #include "base.h" + +int sock_addr_inet_pton(sock_addr *addr, const char *str, int family, unsigned short port); + +const char * sock_addr_inet_ntop(const sock_addr *addr, char *buf, socklen_t sz); +int sock_addr_inet_ntop_copy_buffer(buffer *b, const sock_addr *addr); +int sock_addr_inet_ntop_append_buffer(buffer *b, const sock_addr *addr); + const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr); #endif diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 6a9d8349..94e2b0b1 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -7,6 +7,7 @@ #include "http_chunk.h" #include "fdevent.h" +#include "inet_ntop_cache.h" #include "connections.h" #include "response.h" #include "joblist.h" @@ -809,31 +810,15 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) { buffer_append_string_len(ds->value, CONST_STR_LEN("\"")); if (addr->plain.sa_family == AF_INET) { if (0==getsockname(con->fd,(struct sockaddr *)&addrbuf,&addrlen)) { - #if defined(HAVE_INET_PTON)/*(expect inet_ntop if inet_pton)*/ - #ifndef INET_ADDRSTRLEN - #define INET_ADDRSTRLEN 16 - #endif - char buf[INET_ADDRSTRLEN]; - buf[0] = '\0'; - inet_ntop(AF_INET, (const void *)&addrbuf.ipv4.sin_addr, - buf, sizeof(buf)); - buffer_append_string(ds->value, buf); - #else - buffer_append_string(ds->value,/*(inet_ntoa() not thread-safe)*/ - inet_ntoa(addrbuf.ipv4.sin_addr)); - #endif + sock_addr_inet_ntop_append_buffer(ds->value, &addrbuf); } buffer_append_string_len(ds->value, CONST_STR_LEN(":")); buffer_append_int(ds->value, ntohs(addr->ipv4.sin_port)); #ifdef HAVE_IPV6 } else if (addr->plain.sa_family == AF_INET6) { if (0 == getsockname(con->fd,(struct sockaddr *)&addrbuf,&addrlen)){ - char buf[INET6_ADDRSTRLEN]; - buf[0] = '\0'; - inet_ntop(AF_INET6, (const void *)&addrbuf.ipv6.sin6_addr, - buf, sizeof(buf)); buffer_append_string_len(ds->value, CONST_STR_LEN("[")); - buffer_append_string(ds->value, buf); + sock_addr_inet_ntop_append_buffer(ds->value, &addrbuf); buffer_append_string_len(ds->value, CONST_STR_LEN("]")); buffer_append_string_len(ds->value, CONST_STR_LEN(":")); buffer_append_int(ds->value, ntohs(addr->ipv6.sin6_port)); diff --git a/src/request.c b/src/request.c index f69a4c85..65dc9580 100644 --- a/src/request.c +++ b/src/request.c @@ -3,6 +3,7 @@ #include "request.h" #include "keyvalue.h" #include "log.h" +#include "inet_ntop_cache.h" #include @@ -250,29 +251,15 @@ int http_request_host_normalize(buffer *b) { if (light_isdigit(*p)) { /* (IPv4 address literal or domain starting w/ digit (e.g. 3com))*/ - struct in_addr addr; - #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/ - if (0 != inet_aton(p, &addr)) - #else - if ((addr.s_addr = inet_addr(p)) != INADDR_NONE) - #endif - { - #if defined(HAVE_INET_PTON)/*(expect inet_ntop() if inet_pton())*/ - #ifndef INET_ADDRSTRLEN - #define INET_ADDRSTRLEN 16 - #endif - char buf[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, (const void *)&addr, buf, sizeof(buf)); - buffer_copy_string(b, buf); - #else - buffer_copy_string(b, inet_ntoa(addr)); /*(not thread-safe)*/ - #endif + sock_addr addr; + if (1 == sock_addr_inet_pton(&addr, p, AF_INET, 0)) { + sock_addr_inet_ntop_copy_buffer(b, &addr); } } } else { /* IPv6 addr */ #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - struct in6_addr addr; + sock_addr addr; char *bracket = b->ptr+blen-1; char *percent = strchr(b->ptr+1, '%'); size_t len; @@ -297,12 +284,12 @@ int http_request_host_normalize(buffer *b) { *bracket = '\0';/*(terminate IPv6 string)*/ if (percent) *percent = '\0'; /*(remove %interface from address)*/ - rc = inet_pton(AF_INET6, b->ptr+1, &addr); + rc = sock_addr_inet_pton(&addr, b->ptr+1, AF_INET6, 0); if (percent) *percent = '%'; /*(restore %interface)*/ *bracket = ']'; /*(restore bracket)*/ if (1 != rc) return -1; - inet_ntop(AF_INET6,(const void *)&addr, buf, sizeof(buf)); + sock_addr_inet_ntop(&addr, buf, sizeof(buf)); len = strlen(buf); if (percent) { if (percent > bracket) return -1; diff --git a/src/sys-socket.h b/src/sys-socket.h index 446f7bcb..93a47404 100644 --- a/src/sys-socket.h +++ b/src/sys-socket.h @@ -10,12 +10,26 @@ #define EINPROGRESS WSAEINPROGRESS #define EALREADY WSAEALREADY #define ECONNABORTED WSAECONNABORTED + #else + #include #include #include #include #include + +#endif + + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 #endif #endif