diff options
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/SConscript | 7 | ||||
-rw-r--r-- | src/base.h | 13 | ||||
-rw-r--r-- | src/configfile-glue.c | 75 | ||||
-rw-r--r-- | src/connections-glue.c | 2 | ||||
-rw-r--r-- | src/connections.c | 2 | ||||
-rw-r--r-- | src/gw_backend.c | 4 | ||||
-rw-r--r-- | src/http-header-glue.c | 26 | ||||
-rw-r--r-- | src/inet_ntop_cache.c | 457 | ||||
-rw-r--r-- | src/inet_ntop_cache.h | 16 | ||||
-rw-r--r-- | src/meson.build | 3 | ||||
-rw-r--r-- | src/mod_evasive.c | 25 | ||||
-rw-r--r-- | src/mod_extforward.c | 18 | ||||
-rw-r--r-- | src/mod_proxy.c | 40 | ||||
-rw-r--r-- | src/network.c | 36 | ||||
-rw-r--r-- | src/request.c | 2 | ||||
-rw-r--r-- | src/server.c | 39 | ||||
-rw-r--r-- | src/sock_addr.c | 685 | ||||
-rw-r--r-- | src/sock_addr.h | 51 | ||||
-rw-r--r-- | src/sys-socket.h | 3 | ||||
-rw-r--r-- | src/test_configfile.c | 17 |
22 files changed, 817 insertions, 719 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e7a4bf87..2e7c5948 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -555,12 +555,13 @@ set(COMMON_SRC fdevent_solaris_devpoll.c fdevent_solaris_port.c fdevent_freebsd_kqueue.c data_config.c - inet_ntop_cache.c crc32.c + crc32.c connections-glue.c configfile-glue.c http-header-glue.c http_auth.c http_vhostdb.c + sock_addr.c splaytree.c rand.c status_counter.c safe_memclear.c @@ -587,6 +588,7 @@ add_executable(lighttpd server.c response.c connections.c + inet_ntop_cache.c network.c network_darwin_sendfile.c network_freebsd_sendfile.c diff --git a/src/Makefile.am b/src/Makefile.am index 4a78d7a0..c16fc449 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,7 @@ common_src=base64.c buffer.c log.c \ fdevent_solaris_devpoll.c fdevent_solaris_port.c \ fdevent_freebsd_kqueue.c \ data_config.c \ - inet_ntop_cache.c crc32.c \ + crc32.c \ connections-glue.c \ configfile-glue.c \ http-header-glue.c \ @@ -75,10 +75,13 @@ common_src=base64.c buffer.c log.c \ http_vhostdb.c \ rand.c \ request.c \ + sock_addr.c \ splaytree.c status_counter.c \ safe_memclear.c -src = server.c response.c connections.c network.c \ +src = server.c response.c connections.c \ + inet_ntop_cache.c \ + network.c \ network_write.c network_linux_sendfile.c \ network_write_mmap.c network_write_no_mmap.c \ network_freebsd_sendfile.c network_writev.c \ @@ -389,7 +392,7 @@ hdr = server.h base64.h buffer.h network.h log.h keyvalue.h \ rand.h \ sys-endian.h sys-mmap.h sys-socket.h sys-strings.h \ mod_cml.h mod_cml_funcs.h \ - safe_memclear.h splaytree.h proc_open.h status_counter.h \ + safe_memclear.h sock_addr.h splaytree.h proc_open.h status_counter.h \ mod_magnet_cache.h @@ -513,7 +516,7 @@ test_buffer_LDADD = $(LIBUNWIND_LIBS) test_base64_SOURCES = test_base64.c base64.c buffer.c test_base64_LDADD = $(LIBUNWIND_LIBS) -test_configfile_SOURCES = test_configfile.c buffer.c array.c data_string.c keyvalue.c vector.c log.c +test_configfile_SOURCES = test_configfile.c buffer.c array.c data_string.c keyvalue.c vector.c log.c sock_addr.c test_configfile_LDADD = $(PCRE_LIB) $(LIBUNWIND_LIBS) noinst_HEADERS = $(hdr) diff --git a/src/SConscript b/src/SConscript index 4c2ba11a..d2bfa7d7 100644 --- a/src/SConscript +++ b/src/SConscript @@ -62,18 +62,21 @@ common_src = Split("base64.c buffer.c log.c \ fdevent_solaris_devpoll.c fdevent_solaris_port.c \ fdevent_freebsd_kqueue.c \ data_config.c \ - inet_ntop_cache.c crc32.c \ + crc32.c \ connections-glue.c \ configfile-glue.c \ http-header-glue.c \ http_auth.c \ http_vhostdb.c \ + sock_addr.c \ splaytree.c \ rand.c \ status_counter.c safe_memclear.c \ ") -src = Split("server.c response.c connections.c network.c \ +src = Split("server.c response.c connections.c \ + inet_ntop_cache.c \ + network.c \ network_writev.c \ network_write_mmap.c network_write_no_mmap.c \ network_write.c network_linux_sendfile.c \ @@ -23,7 +23,7 @@ #include "array.h" #include "chunk.h" #include "keyvalue.h" -#include "sys-socket.h" +#include "sock_addr.h" #include "etag.h" struct fdevents; /* declaration */ @@ -104,17 +104,6 @@ typedef struct { } request_handler; -union sock_addr { -#ifdef HAVE_IPV6 - struct sockaddr_in6 ipv6; -#endif - struct sockaddr_in ipv4; -#ifdef HAVE_SYS_UN_H - struct sockaddr_un un; -#endif - struct sockaddr plain; -}; - /* fcgi_response_header contains ... */ #define HTTP_STATUS BV(0) #define HTTP_CONNECTION BV(1) diff --git a/src/configfile-glue.c b/src/configfile-glue.c index cacf1f9a..6f0f576e 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -5,14 +5,12 @@ #include "array.h" #include "log.h" #include "plugin.h" +#include "sock_addr.h" #include "configfile.h" #include <string.h> #include <stdlib.h> -#ifndef _WIN32 -#include <arpa/inet.h> -#endif /** * like all glue code this file contains functions which @@ -225,72 +223,22 @@ static const char* cond_result_to_string(cond_result_t cond_result) { static int config_addrstr_eq_remote_ip_mask(server *srv, const char *addrstr, int nm_bits, sock_addr *rmt) { /* special-case 0 == nm_bits to mean "all bits of the address" in addrstr */ - sock_addr val; -#ifdef HAVE_INET_PTON - if (1 == inet_pton(AF_INET, addrstr, &val.ipv4.sin_addr)) -#else - if (INADDR_NONE != (val.ipv4.sin_addr = inet_addr(addrstr))) -#endif - { - /* build netmask */ - uint32_t nm; + sock_addr addr; + if (1 == sock_addr_inet_pton(&addr, addrstr, AF_INET, 0)) { if (nm_bits > 32) { log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv4 netmask too large:", nm_bits); return -1; } - nm = htonl(~((1u << (32 - (0 != nm_bits ? nm_bits : 32))) - 1)); - - if (rmt->plain.sa_family == AF_INET) { - return ((val.ipv4.sin_addr.s_addr & nm) == (rmt->ipv4.sin_addr.s_addr & nm)); -#ifdef HAVE_IPV6 - } else if (rmt->plain.sa_family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED(&rmt->ipv6.sin6_addr)) { - #ifdef s6_addr32 - in_addr_t x = rmt->ipv6.sin6_addr.s6_addr32[3]; - #else - in_addr_t x; - memcpy(&x, rmt->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); - #endif - return ((val.ipv4.sin_addr.s_addr & nm) == (x & nm)); -#endif - } else { - return 0; - } -#if defined(HAVE_INET_PTON) && defined(HAVE_IPV6) - } else if (1 == inet_pton(AF_INET6, addrstr, &val.ipv6.sin6_addr)) { + } else if (1 == sock_addr_inet_pton(&addr, addrstr, AF_INET6, 0)) { if (nm_bits > 128) { log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv6 netmask too large:", nm_bits); return -1; } - if (rmt->plain.sa_family == AF_INET6) { - uint8_t *a = (uint8_t *)&val.ipv6.sin6_addr.s6_addr[0]; - uint8_t *b = (uint8_t *)&rmt->ipv6.sin6_addr.s6_addr[0]; - int match; - do { - match = (nm_bits >= 8) - ? *a++ == *b++ - : (*a >> (8 - nm_bits)) == (*b >> (8 - nm_bits)); - } while (match && (nm_bits -= 8) > 0); - return match; - } else if (rmt->plain.sa_family == AF_INET - && IN6_IS_ADDR_V4MAPPED(&val.ipv6.sin6_addr)) { - uint32_t nm = - nm_bits < 128 ? htonl(~(~0u >> (nm_bits > 96 ? nm_bits - 96 : 0))) : ~0u; - #ifdef s6_addr32 - in_addr_t x = val.ipv6.sin6_addr.s6_addr32[3]; - #else - in_addr_t x; - memcpy(&x, val.ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); - #endif - return ((x & nm) == (rmt->ipv4.sin_addr.s_addr & nm)); - } else { - return 0; - } -#endif } else { log_error_write(srv, __FILE__, __LINE__, "ss", "ERROR: ip addr is invalid:", addrstr); return -1; } + return sock_addr_is_addr_eq_bits(&addr, rmt, nm_bits); } static int config_addrbuf_eq_remote_ip_mask(server *srv, buffer *string, char *nm_slash, sock_addr *rmt) { @@ -420,18 +368,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat switch(dc->cond) { case CONFIG_COND_NE: case CONFIG_COND_EQ: - switch (srv_sock->addr.plain.sa_family) { - case AF_INET: - port = ntohs(srv_sock->addr.ipv4.sin_port); - break; - #ifdef HAVE_IPV6 - case AF_INET6: - port = ntohs(srv_sock->addr.ipv6.sin6_port); - break; - #endif - default: - port = 0; - } + port = sock_addr_get_port(&srv_sock->addr); if (0 == port) break; ck_colon = strchr(dc->string->ptr, ':'); val_colon = strchr(l->ptr, ':'); diff --git a/src/connections-glue.c b/src/connections-glue.c index 8ba37c34..7c6309b7 100644 --- a/src/connections-glue.c +++ b/src/connections-glue.c @@ -325,7 +325,7 @@ int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, of * and only if TCP socket */ if (cq->first && cq->first->next) { - const int sa_family = con->srv_socket->addr.plain.sa_family; + const int sa_family = sock_addr_get_family(&con->srv_socket->addr); if (sa_family == AF_INET || sa_family == AF_INET6) { chunk *c = cq->first; while (c->type == MEM_CHUNK && NULL != (c = c->next)) ; diff --git a/src/connections.c b/src/connections.c index 33eca67e..bf271bb4 100644 --- a/src/connections.c +++ b/src/connections.c @@ -960,7 +960,7 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { } return NULL; } else { - if (cnt_addr.plain.sa_family != AF_UNIX) { + if (sock_addr_get_family(&cnt_addr) != AF_UNIX) { network_accept_tcp_nagle_disable(cnt); } return connection_accepted(srv, srv_socket, &cnt_addr, cnt); diff --git a/src/gw_backend.c b/src/gw_backend.c index 8eb92608..c24332b6 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -23,8 +23,8 @@ #include "buffer.h" #include "crc32.h" #include "fdevent.h" -#include "inet_ntop_cache.h" #include "log.h" +#include "sock_addr.h" @@ -397,7 +397,7 @@ static int gw_proc_sockaddr_init(server *srv, gw_host *host, gw_proc *proc) { /* overwrite host->host buffer with IP addr string so that * any further use of gw_host does not block on DNS lookup */ sock_addr_inet_ntop_copy_buffer(host->host, &addr); - host->family = addr.plain.sa_family; + host->family = sock_addr_get_family(&addr); } buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:")); buffer_append_string_buffer(proc->connection_name, host->host); diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 717a73e5..1916ca66 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -7,8 +7,8 @@ #include "log.h" #include "etag.h" #include "http_chunk.h" -#include "inet_ntop_cache.h" #include "response.h" +#include "sock_addr.h" #include "stat_cache.h" #include <string.h> @@ -1321,13 +1321,9 @@ int http_cgi_headers (server *srv, connection *con, http_cgi_opts *opts, http_cg const char *s; size_t n; char buf[LI_ITOSTRING_LENGTH]; - #ifdef HAVE_IPV6 - char b2[INET6_ADDRSTRLEN + 1]; - #else - char b2[INET_ADDRSTRLEN + 1]; - #endif sock_addr *addr; sock_addr addrbuf; + char b2[INET6_ADDRSTRLEN + 1]; /* (CONTENT_LENGTH must be first for SCGI) */ if (!opts->authorizer) { @@ -1466,23 +1462,9 @@ int http_cgi_headers (server *srv, connection *con, http_cgi_opts *opts, http_cg rc |= cb(vdata, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); switch (addr->plain.sa_family) { - #ifdef HAVE_IPV6 - case AF_INET6: - if (0 ==memcmp(&addr->ipv6.sin6_addr,&in6addr_any,sizeof(in6addr_any))){ - socklen_t addrlen = sizeof(addrbuf); - if (0 == getsockname(con->fd,(struct sockaddr *)&addrbuf,&addrlen)){ - addr = &addrbuf; - } else { - s = ""; - break; - } - } - s = sock_addr_inet_ntop(addr, b2, sizeof(b2)-1); - if (NULL == s) s = ""; - break; - #endif case AF_INET: - if (srv_sock->addr.ipv4.sin_addr.s_addr == INADDR_ANY) { + case AF_INET6: + if (sock_addr_is_addr_wildcard(addr)) { socklen_t addrlen = sizeof(addrbuf); if (0 == getsockname(con->fd,(struct sockaddr *)&addrbuf,&addrlen)){ addr = &addrbuf; diff --git a/src/inet_ntop_cache.c b/src/inet_ntop_cache.c index 8a1625b9..868b8df2 100644 --- a/src/inet_ntop_cache.c +++ b/src/inet_ntop_cache.c @@ -1,461 +1,15 @@ #include "first.h" #include "inet_ntop_cache.h" -#include "base.h" -#include "log.h" #include "sys-socket.h" #include <sys/types.h> -#include <errno.h> #include <string.h> #ifndef _WIN32 -#include <netdb.h> +#include <arpa/inet.h> #endif - -unsigned short sock_addr_get_port (const sock_addr *addr) -{ - switch (addr->plain.sa_family) { - case AF_INET: - return ntohs(addr->ipv4.sin_port); - #ifdef HAVE_IPV6 - case AF_INET6: - return ntohs(addr->ipv6.sin6_port); - #endif - default: /* case AF_UNIX: */ - return 0; - } -} - - -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; -} - - -int sock_addr_nameinfo_append_buffer(server *srv, buffer *b, const sock_addr *addr) -{ - /*(this routine originates from - * http-header-glue.c:http_response_redirect_to_directory())*/ - /*(note: name resolution here is *blocking*)*/ - if (AF_INET == addr->plain.sa_family) { - struct hostent *he = gethostbyaddr((char *)&addr->ipv4.sin_addr, - sizeof(struct in_addr), AF_INET); - if (NULL == he) { - log_error_write(srv, __FILE__, __LINE__, - "SdS", "NOTICE: gethostbyaddr failed: ", - h_errno, ", using ip-address instead"); - - sock_addr_inet_ntop_append_buffer(b, addr); - } else { - buffer_append_string(b, he->h_name); - } - } - #ifdef HAVE_IPV6 - else if (AF_INET6 == addr->plain.sa_family) { - char hbuf[256]; - if (0 != getnameinfo((const struct sockaddr *)(&addr->ipv6), - sizeof(addr->ipv6), - hbuf, sizeof(hbuf), NULL, 0, 0)) { - log_error_write(srv, __FILE__, __LINE__, - "SSS", "NOTICE: getnameinfo failed: ", - strerror(errno), ", using ip-address instead"); - - buffer_append_string_len(b, CONST_STR_LEN("[")); - sock_addr_inet_ntop_append_buffer(b, addr); - buffer_append_string_len(b, CONST_STR_LEN("]")); - } else { - buffer_append_string(b, hbuf); - } - } - #endif - else { - log_error_write(srv, __FILE__, __LINE__, - "S", "ERROR: unsupported address-type"); - return -1; - } - - return 0; -} - - -int sock_addr_from_str_hints(server *srv, sock_addr *addr, socklen_t *len, const char *str, int family, unsigned short port) -{ - /*(note: name resolution here is *blocking*)*/ - switch(family) { - case AF_UNSPEC: - if (0 == strcmp(str, "localhost")) { - /*(special-case "localhost" to IPv4 127.0.0.1)*/ - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->ipv4.sin_family = AF_INET; - addr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - return 1; - } - #ifdef HAVE_IPV6 - else { - struct addrinfo hints, *res; - int r; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { - log_error_write(srv, __FILE__, __LINE__, - "sssss", "getaddrinfo failed: ", - gai_strerror(r), "'", str, "'"); - return 0; - } - - memcpy(addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); - if (AF_INET6 == addr->plain.sa_family) { - addr->ipv6.sin6_port = htons(port); - *len = sizeof(struct sockaddr_in6); - } - else { /* AF_INET */ - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - } - return 1; - } - #else - /* fall through */ - #endif - #ifdef HAVE_IPV6 - case AF_INET6: - memset(addr, 0, sizeof(struct sockaddr_in6)); - addr->ipv6.sin6_family = AF_INET6; - if (0 == strcmp(str, "::")) { - addr->ipv6.sin6_addr = in6addr_any; - } - else if (0 == strcmp(str, "::1")) { - addr->ipv6.sin6_addr = in6addr_loopback; - } - else { - struct addrinfo hints, *res; - int r; - - memset(&hints, 0, sizeof(hints)); - - hints.ai_family = AF_INET6; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { - hints.ai_family = AF_INET; - if ( - #ifdef EAI_ADDRFAMILY - EAI_ADDRFAMILY == r && - #endif - 0 == getaddrinfo(str, NULL, &hints, &res)) { - memcpy(addr, res->ai_addr, res->ai_addrlen); - addr->ipv4.sin_family = AF_INET; - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - /*assert(*len == res->ai_addrlen);*/ - freeaddrinfo(res); - return 1; - } - - log_error_write(srv, __FILE__, __LINE__, - "sssss", "getaddrinfo failed: ", - gai_strerror(r), "'", str, "'"); - - return 0; - } - - memcpy(addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); - } - addr->ipv6.sin6_port = htons(port); - *len = sizeof(struct sockaddr_in6); - return 1; - #endif - case AF_INET: - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->ipv4.sin_family = AF_INET; - if (0 == strcmp(str, "0.0.0.0")) { - addr->ipv4.sin_addr.s_addr = htonl(INADDR_ANY); - } - else if (0 == strcmp(str, "127.0.0.1")) { - addr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - else { - #ifdef HAVE_INET_PTON - /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/ - struct addrinfo hints, *res; - int r; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { - log_error_write(srv, __FILE__, __LINE__, - "sssss", "getaddrinfo failed: ", - gai_strerror(r), "'", str, "'"); - return 0; - } - - memcpy(addr, res->ai_addr, res->ai_addrlen); - freeaddrinfo(res); - #else - struct hostent *he = gethostbyname(str); - if (NULL == he) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "gethostbyname failed:", h_errno, str); - return 0; - } - - if (he->h_addrtype != AF_INET) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "addr-type != AF_INET:", he->h_addrtype); - return 0; - } - - if (he->h_length != sizeof(struct in_addr)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "addr-length != sizeof(in_addr):",he->h_length); - return 0; - } - - memcpy(&addr->ipv4.sin_addr.s_addr,he->h_addr_list[0],he->h_length); - #endif - } - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - return 1; - #ifdef HAVE_SYS_UN_H - case AF_UNIX: - memset(addr, 0, sizeof(struct sockaddr_un)); - addr->un.sun_family = AF_UNIX; - { - size_t hostlen = strlen(str) + 1; - if (hostlen > sizeof(addr->un.sun_path)) { - log_error_write(srv, __FILE__, __LINE__, "sS", - "unix socket filename too long:", str); - /*errno = ENAMETOOLONG;*/ - return 0; - } - memcpy(addr->un.sun_path, str, hostlen); - #if defined(SUN_LEN) - *len = SUN_LEN(&addr->un); - #else - /* stevens says: */ - *len = hostlen + sizeof(addr->un.sun_family); - #endif - } - return 1; - #else - case AF_UNIX: - log_error_write(srv, __FILE__, __LINE__, "s", - "unix domain sockets are not supported."); - return 0; - #endif - default: - log_error_write(srv, __FILE__, __LINE__, "sd", - "address family unsupported:", family); - /*errno = EAFNOSUPPORT;*/ - return 0; - } -} - - -int sock_addr_from_str_numeric(server *srv, sock_addr *addr, const char *str) -{ - /*(note: does not handle port if getaddrinfo() is not available)*/ - /*(note: getaddrinfo() is stricter than inet_aton() in what is accepted)*/ - /*(this routine originates from mod_extforward.c:ipstr_to_sockaddr()*/ - #ifdef HAVE_IPV6 - struct addrinfo hints, *addrlist = NULL; - int result; - - /** - * quoting $ man getaddrinfo - * - * NOTES - * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3. - * AI_NUMERICSERV is available since glibc 2.3.4. - */ - #ifndef AI_NUMERICSERV - #define AI_NUMERICSERV 0 - #endif - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; - - errno = 0; - result = getaddrinfo(str, NULL, &hints, &addrlist); - - if (result != 0) { - log_error_write(srv, __FILE__, __LINE__, "SSSs(S)", - "could not parse ip address ", str, " because ", - gai_strerror(result), strerror(errno)); - } else if (addrlist == NULL) { - log_error_write(srv, __FILE__, __LINE__, "SSS", - "Problem in parsing ip address ", str, - ": succeeded, but no information returned"); - result = -1; - } else switch (addrlist->ai_family) { - case AF_INET: - memcpy(&addr->ipv4, addrlist->ai_addr, sizeof(addr->ipv4)); - force_assert(AF_INET == addr->plain.sa_family); - break; - case AF_INET6: - memcpy(&addr->ipv6, addrlist->ai_addr, sizeof(addr->ipv6)); - force_assert(AF_INET6 == addr->plain.sa_family); - break; - default: - log_error_write(srv, __FILE__, __LINE__, "SSS", - "Problem in parsing ip address ", str, - ": succeeded, but unknown family"); - result = -1; - break; - } - - freeaddrinfo(addrlist); - return (0 == result); - #else - UNUSED(srv); - addr->ipv4.sin_addr.s_addr = inet_addr(str); - addr->plain.sa_family = AF_INET; - return (addr->ipv4.sin_addr.s_addr != 0xFFFFFFFF); - #endif -} - - -int sock_addr_from_buffer_hints_numeric(server *srv, sock_addr *addr, socklen_t *len, const buffer *b, int family, unsigned short port) -{ - /*(this routine originates from mod_fastcgi.c and mod_scgi.c)*/ - if (buffer_string_is_empty(b)) { - /*(preserve existing behavior (for now))*/ - /*(would be better if initialized default when reading config)*/ - memset(&addr->ipv4, 0, sizeof(struct sockaddr_in)); - addr->ipv4.sin_family = AF_INET; - addr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - return 1; - } - else if (1 == sock_addr_inet_pton(addr, b->ptr, family, port)) { - *len = (family == AF_INET) - ? sizeof(struct sockaddr_in) /* family == AF_INET */ - : sizeof(struct sockaddr_in6); /* family == AF_INET6 */ - return 1; - } - #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) - else if (family == AF_INET6) { - log_error_write(srv, __FILE__, __LINE__, "sb", - "invalid IPv6 address literal:", b); - return 0; - } - #endif - #ifndef HAVE_INET_PTON /*(preserve existing behavior (for now))*/ - else { - struct hostent *he = gethostbyname(b->ptr); - if (NULL == he) { - log_error_write(srv, __FILE__, __LINE__, "sdb", - "gethostbyname failed:", h_errno, b); - return 0; - } - - if (he->h_addrtype != AF_INET) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "addr-type != AF_INET:", he->h_addrtype); - return 0; - } - - if (he->h_length != sizeof(struct in_addr)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "addr-length != sizeof(in_addr):",he->h_length); - return 0; - } - - memset(&addr->ipv4, 0, sizeof(struct sockaddr_in)); - memcpy(&addr->ipv4.sin_addr.s_addr, he->h_addr_list[0], he->h_length); - addr->ipv4.sin_family = AF_INET; - addr->ipv4.sin_port = htons(port); - *len = sizeof(struct sockaddr_in); - } - #else - UNUSED(srv); - #endif - - return 0; -} +#include "sock_addr.h" const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { @@ -498,12 +52,7 @@ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { i = ndx; if (++ndx >= INET_NTOP_CACHE_MAX) ndx = 0; - 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), - inet_ntop_cache[i].b2, INET6_ADDRSTRLEN); + s = sock_addr_inet_ntop(addr, inet_ntop_cache[i].b2, INET6_ADDRSTRLEN); if (NULL == s) return ""; inet_ntop_cache[i].family = addr->plain.sa_family; diff --git a/src/inet_ntop_cache.h b/src/inet_ntop_cache.h index c38bbf56..027f4097 100644 --- a/src/inet_ntop_cache.h +++ b/src/inet_ntop_cache.h @@ -2,23 +2,7 @@ #define _INET_NTOP_CACHE_H_ #include "first.h" -#include <sys/types.h> -#include "sys-socket.h" #include "base_decls.h" -#include "buffer.h" - -unsigned short sock_addr_get_port (const sock_addr *addr); - -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); -int sock_addr_nameinfo_append_buffer(server *srv, buffer *b, const sock_addr *addr); - -int sock_addr_from_buffer_hints_numeric(server *srv, sock_addr *addr, socklen_t *len, const buffer *b, int family, unsigned short port); -int sock_addr_from_str_hints(server *srv, sock_addr *addr, socklen_t *len, const char *str, int family, unsigned short port); -int sock_addr_from_str_numeric(server *srv, sock_addr *addr, const char *str); const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr); diff --git a/src/meson.build b/src/meson.build index e3c91d2f..08a4c8b0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -550,7 +550,6 @@ common_src = [ 'http_chunk.c', 'http_vhostdb.c', 'http-header-glue.c', - 'inet_ntop_cache.c', 'joblist.c', 'keyvalue.c', 'log.c', @@ -558,6 +557,7 @@ common_src = [ 'plugin.c', 'rand.c', 'safe_memclear.c', + 'sock_addr.c', 'splaytree.c', 'stat_cache.c', 'status_counter.c', @@ -570,6 +570,7 @@ endif main_src = [ 'configfile.c', 'connections.c', + 'inet_ntop_cache.c', 'network_darwin_sendfile.c', 'network_freebsd_sendfile.c', 'network_linux_sendfile.c', diff --git a/src/mod_evasive.c b/src/mod_evasive.c index 26362c09..1e0fad44 100644 --- a/src/mod_evasive.c +++ b/src/mod_evasive.c @@ -4,6 +4,7 @@ #include "log.h" #include "buffer.h" #include "response.h" +#include "sock_addr.h" #include "plugin.h" @@ -157,37 +158,15 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { /* no limit set, nothing to block */ if (p->conf.max_conns == 0) return HANDLER_GO_ON; - switch (con->dst_addr.plain.sa_family) { - case AF_INET: -#ifdef HAVE_IPV6 - case AF_INET6: -#endif - break; - default: /* Address family not supported */ - return HANDLER_GO_ON; - }; - for (j = 0; j < srv->conns->used; j++) { connection *c = srv->conns->ptr[j]; /* check if other connections are already actively serving data for the same IP * we can only ban connections which are already behind the 'read request' state * */ - if (c->dst_addr.plain.sa_family != con->dst_addr.plain.sa_family) continue; if (c->state <= CON_STATE_REQUEST_END) continue; - switch (con->dst_addr.plain.sa_family) { - case AF_INET: - if (c->dst_addr.ipv4.sin_addr.s_addr != con->dst_addr.ipv4.sin_addr.s_addr) continue; - break; -#ifdef HAVE_IPV6 - case AF_INET6: - if (0 != memcmp(c->dst_addr.ipv6.sin6_addr.s6_addr, con->dst_addr.ipv6.sin6_addr.s6_addr, 16)) continue; - break; -#endif - default: /* Address family not supported, should never be reached */ - continue; - }; + if (!sock_addr_is_addr_eq(&c->dst_addr, &con->dst_addr)) continue; conns_by_ip++; if (conns_by_ip > p->conf.max_conns) { diff --git a/src/mod_extforward.c b/src/mod_extforward.c index 0364f31f..0d1d7d7b 100644 --- a/src/mod_extforward.c +++ b/src/mod_extforward.c @@ -4,7 +4,7 @@ #include "log.h" #include "buffer.h" #include "request.h" -#include "inet_ntop_cache.h" +#include "sock_addr.h" #include "plugin.h" @@ -1403,10 +1403,8 @@ static int mod_extforward_hap_PROXY_v2 (connection * const con, switch (hdr->v2.fam) { case 0x11: /* TCPv4 */ - memset(&con->dst_addr.ipv4, 0, sizeof(struct sockaddr_in)); - con->dst_addr.ipv4.sin_family = AF_INET; - con->dst_addr.ipv4.sin_port = hdr->v2.addr.ip4.src_port; - con->dst_addr.ipv4.sin_addr.s_addr = hdr->v2.addr.ip4.src_addr; + sock_addr_assign(&con->dst_addr, AF_INET, hdr->v2.addr.ip4.src_port, + &hdr->v2.addr.ip4.src_addr); sock_addr_inet_ntop_copy_buffer(con->dst_addr_buf, &con->dst_addr); #if 0 ((struct sockaddr_in *)&by)->sin_family = AF_INET; @@ -1419,10 +1417,8 @@ static int mod_extforward_hap_PROXY_v2 (connection * const con, break; #ifdef HAVE_IPV6 case 0x21: /* TCPv6 */ - memset(&con->dst_addr.ipv6, 0, sizeof(struct sockaddr_in6)); - con->dst_addr.ipv6.sin6_family = AF_INET6; - con->dst_addr.ipv6.sin6_port = hdr->v2.addr.ip6.src_port; - memcpy(&con->dst_addr.ipv6.sin6_addr, hdr->v2.addr.ip6.src_addr, 16); + sock_addr_assign(&con->dst_addr, AF_INET6, hdr->v2.addr.ip6.src_port, + &hdr->v2.addr.ip6.src_addr); sock_addr_inet_ntop_copy_buffer(con->dst_addr_buf, &con->dst_addr); #if 0 ((struct sockaddr_in6 *)&by)->sin6_family = AF_INET6; @@ -1441,9 +1437,7 @@ static int mod_extforward_hap_PROXY_v2 (connection * const con, char *z = memchr(src_addr, '\0', UNIX_PATH_MAX); if (NULL == z) return -1; /* invalid addr; too long */ len = (uint32_t)(z - src_addr + 1); /*(+1 for '\0')*/ - memset(&con->dst_addr.un, 0, sizeof(struct sockaddr_un)); - con->dst_addr.un.sun_family = AF_UNIX; - memcpy(&con->dst_addr.un.sun_path, src_addr, len); + sock_addr_assign(&con->dst_addr, AF_UNIX, 0, src_addr); buffer_copy_string_len(con->dst_addr_buf, src_addr, len); } #if 0 /*(dst_addr should be identical to src_addr for AF_UNIX)*/ diff --git a/src/mod_proxy.c b/src/mod_proxy.c index a0a8dbc1..8ea72a05 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -7,10 +7,10 @@ #include "base.h" #include "array.h" #include "buffer.h" -#include "inet_ntop_cache.h" #include "keyvalue.h" #include "log.h" #include "plugin.h" +#include "sock_addr.h" #include "status_counter.h" /** @@ -572,6 +572,7 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) { } if (flags & PROXY_FORWARDED_FOR) { + int family = sock_addr_get_family(&con->dst_addr); buffer_append_string_len(ds->value, CONST_STR_LEN("for=")); if (NULL != dsfor) { /* over-simplified test expecting only IPv4 or IPv6 addresses, @@ -587,16 +588,14 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) { ds->value, CONST_BUF_LEN(dsfor->value)); if (ipv6) buffer_append_string_len(ds->value, CONST_STR_LEN("]")); buffer_append_string_len(ds->value, CONST_STR_LEN("\"")); - } else if (con->dst_addr.plain.sa_family == AF_INET) { + } else if (family == AF_INET) { /*(Note: if :port is added, then must be quoted-string: * e.g. for="...:port")*/ buffer_append_string_buffer(ds->value, con->dst_addr_buf); - #ifdef HAVE_IPV6 - } else if (con->dst_addr.plain.sa_family == AF_INET6) { + } else if (family == AF_INET6) { buffer_append_string_len(ds->value, CONST_STR_LEN("\"[")); buffer_append_string_buffer(ds->value, con->dst_addr_buf); buffer_append_string_len(ds->value, CONST_STR_LEN("]\"")); - #endif } else { buffer_append_string_len(ds->value, CONST_STR_LEN("\"")); buffer_append_string_backslash_escaped( @@ -607,39 +606,30 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) { } if (flags & PROXY_FORWARDED_BY) { + int family = sock_addr_get_family(&con->srv_socket->addr); /* Note: getsockname() and inet_ntop() are expensive operations. * (recommendation: do not to enable by=... unless required) * future: might use con->srv_socket->srv_token if addr is not * INADDR_ANY or in6addr_any, but must omit optional :port * from con->srv_socket->srv_token for consistency */ - sock_addr *addr = &con->srv_socket->addr; - sock_addr addrbuf; - socklen_t addrlen = sizeof(addrbuf); if (semicolon) buffer_append_string_len(ds->value, CONST_STR_LEN(";")); buffer_append_string_len(ds->value, CONST_STR_LEN("by=")); 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)) { - 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)){ - buffer_append_string_len(ds->value, CONST_STR_LEN("[")); - 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)); - } - #endif #ifdef HAVE_SYS_UN_H - } else if (addr->plain.sa_family == AF_UNIX) { + /* special-case: might need to encode unix domain socket path */ + if (family == AF_UNIX) { buffer_append_string_backslash_escaped( ds->value, CONST_BUF_LEN(con->srv_socket->srv_token)); + } + else #endif + { + sock_addr addr; + socklen_t addrlen = sizeof(addr); + if (0 == getsockname(con->fd,(struct sockaddr *)&addr, &addrlen)) { + sock_addr_stringify_append_buffer(ds->value, &addr); + } } buffer_append_string_len(ds->value, CONST_STR_LEN("\"")); semicolon = 1; diff --git a/src/network.c b/src/network.c index 6b92ae07..51dce3cc 100644 --- a/src/network.c +++ b/src/network.c @@ -5,12 +5,10 @@ #include "log.h" #include "connections.h" #include "plugin.h" -#include "joblist.h" #include "configfile.h" -#include "inet_ntop_cache.h" +#include "sock_addr.h" #include "network_backends.h" -#include "sys-mmap.h" #include "sys-socket.h" #include <sys/types.h> @@ -71,22 +69,7 @@ static handler_t network_server_handle_fdevent(server *srv, void *context, int r static void network_host_normalize_addr_str(buffer *host, sock_addr *addr) { buffer_reset(host); - if (addr->plain.sa_family == AF_INET6) - buffer_append_string_len(host, CONST_STR_LEN("[")); - sock_addr_inet_ntop_append_buffer(host, addr); - if (addr->plain.sa_family == AF_INET6) - buffer_append_string_len(host, CONST_STR_LEN("]")); - if (addr->plain.sa_family != AF_UNIX) { - #ifdef HAVE_IPV6 - unsigned short port = (addr->plain.sa_family == AF_INET) - ? ntohs(addr->ipv4.sin_port) - : ntohs(addr->ipv6.sin6_port); - #else - unsigned short port = ntohs(addr->ipv4.sin_port); - #endif - buffer_append_string_len(host, CONST_STR_LEN(":")); - buffer_append_int(host, (int)port); - } + sock_addr_stringify_append_buffer(host, addr); } static int network_host_parse_addr(server *srv, sock_addr *addr, socklen_t *addr_len, buffer *host, int use_ipv6) { @@ -146,6 +129,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int specific_config *s = srv->config_storage[sidx]; socklen_t addr_len = sizeof(sock_addr); sock_addr addr; + int family = 0; int set_v6only = 0; #ifdef __WIN32 @@ -199,8 +183,10 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int return -1; } + family = sock_addr_get_family(&addr); + #ifdef HAVE_IPV6 - if (*host != '\0' && AF_INET6 == addr.plain.sa_family) { + if (*host != '\0' && AF_INET6 == family) { if (s->set_v6only) { set_v6only = 1; } else { @@ -256,10 +242,10 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int } } else #ifdef HAVE_SYS_UN_H - if (AF_UNIX == srv_socket->addr.plain.sa_family) { + if (AF_UNIX == family) { /* check if the socket exists and try to connect to it. */ force_assert(host); /*(static analysis hint)*/ - if (-1 == (srv_socket->fd = fdevent_socket_cloexec(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { + if (-1 == (srv_socket->fd = fdevent_socket_cloexec(AF_UNIX, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; } @@ -291,7 +277,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int } else #endif { - if (-1 == (srv_socket->fd = fdevent_socket_nb_cloexec(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { + if (-1 == (srv_socket->fd = fdevent_socket_nb_cloexec(family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; } @@ -315,7 +301,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int return -1; } - if (srv_socket->addr.plain.sa_family != AF_UNIX) { + if (family != AF_UNIX) { if (fdevent_set_tcp_nodelay(srv_socket->fd, 1) < 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "setsockopt(TCP_NODELAY) failed:", strerror(errno)); return -1; @@ -330,7 +316,7 @@ static int network_server_init(server *srv, buffer *host_token, size_t sidx, int } if (-1 != stdin_fd) { } else - if (srv_socket->addr.plain.sa_family == AF_UNIX && !buffer_string_is_empty(s->socket_perms)) { + if (AF_UNIX == family && !buffer_string_is_empty(s->socket_perms)) { mode_t m = 0; for (char *str = s->socket_perms->ptr; *str; ++str) { m <<= 3; diff --git a/src/request.c b/src/request.c index fbfed15a..50156081 100644 --- a/src/request.c +++ b/src/request.c @@ -3,7 +3,7 @@ #include "request.h" #include "keyvalue.h" #include "log.h" -#include "inet_ntop_cache.h" +#include "sock_addr.h" #include <sys/stat.h> diff --git a/src/server.c b/src/server.c index de4b0a3a..4cd8699c 100644 --- a/src/server.c +++ b/src/server.c @@ -14,6 +14,7 @@ #include "http_vhostdb.h" #include "fdevent.h" #include "connections.h" +#include "sock_addr.h" #include "stat_cache.h" #include "plugin.h" #include "joblist.h" @@ -428,36 +429,12 @@ static server_socket * server_oneshot_getsock(server *srv, sock_addr *cnt_addr) size_t i; for (i = 0; i < srv->srv_sockets.used; ++i) { srv_socket = srv->srv_sockets.ptr[i]; - if (cnt_addr->plain.sa_family != srv_socket->addr.plain.sa_family) continue; - switch (cnt_addr->plain.sa_family) { - case AF_INET: - if (srv_socket->addr.ipv4.sin_port != cnt_addr->ipv4.sin_port) continue; - if (srv_socket->addr.ipv4.sin_addr.s_addr == cnt_addr->ipv4.sin_addr.s_addr) { - return srv_socket; - } - if (srv_socket->addr.ipv4.sin_addr.s_addr == htonl(INADDR_ANY)) { - srv_socket_wild = srv_socket; - } - continue; - #ifdef HAVE_IPV6 - case AF_INET6: - if (srv_socket->addr.ipv6.sin6_port != cnt_addr->ipv6.sin6_port) continue; - if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &cnt_addr->ipv6.sin6_addr, sizeof(struct in6_addr))) { - return srv_socket; - } - if (0 == memcmp(&srv_socket->addr.ipv6.sin6_addr, &in6addr_any, sizeof(struct in6_addr))) { - srv_socket_wild = srv_socket; - } - continue; - #endif - #ifdef HAVE_SYS_UN_H - case AF_UNIX: - if (0 == strcmp(srv_socket->addr.un.sun_path, cnt_addr->un.sun_path)) { - return srv_socket; - } - continue; - #endif - default: continue; + if (!sock_addr_is_port_eq(&srv_socket->addr,cnt_addr)) continue; + if (sock_addr_is_addr_eq(&srv_socket->addr,cnt_addr)) return srv_socket; + + if (NULL != srv_socket_wild) continue; + if (sock_addr_is_addr_wildcard(&srv_socket->addr)) { + srv_socket_wild = srv_socket; } } @@ -524,7 +501,7 @@ static int server_oneshot_init(server *srv, int fd) { return 0; } - if (cnt_addr.plain.sa_family != AF_UNIX) { + if (sock_addr_get_family(&cnt_addr) != AF_UNIX) { network_accept_tcp_nagle_disable(fd); } diff --git a/src/sock_addr.c b/src/sock_addr.c new file mode 100644 index 00000000..41fb92a0 --- /dev/null +++ b/src/sock_addr.c @@ -0,0 +1,685 @@ +#include "first.h" + +#include "sock_addr.h" + +#include "sys-socket.h" +#include <sys/types.h> +#include <errno.h> +#include <string.h> +#ifndef _WIN32 +#include <netdb.h> +#include <arpa/inet.h> +#endif + +#include "base.h" +#include "log.h" + + +unsigned short sock_addr_get_port (const sock_addr *saddr) +{ + switch (saddr->plain.sa_family) { + case AF_INET: + return ntohs(saddr->ipv4.sin_port); + #ifdef HAVE_IPV6 + case AF_INET6: + return ntohs(saddr->ipv6.sin6_port); + #endif + #ifdef HAVE_SYS_UN_H + /*case AF_UNIX:*/ + #endif + default: + return 0; + } +} + + +int sock_addr_is_addr_wildcard (const sock_addr *saddr) +{ + switch (saddr->plain.sa_family) { + case AF_INET: + return (saddr->ipv4.sin_addr.s_addr == INADDR_ANY); /*(htonl(0x0))*/ + #ifdef HAVE_IPV6 + case AF_INET6: + return !memcmp(&saddr->ipv6.sin6_addr,&in6addr_any,sizeof(in6addr_any)); + #endif + #ifdef HAVE_SYS_UN_H + /*case AF_UNIX:*/ + #endif + default: + return 0; + } +} + + +int sock_addr_is_family_eq (const sock_addr *saddr1, const sock_addr *saddr2) +{ + return saddr1->plain.sa_family == saddr2->plain.sa_family; +} + + +int sock_addr_is_port_eq (const sock_addr *saddr1, const sock_addr *saddr2) +{ + if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; + switch (saddr1->plain.sa_family) { + case AF_INET: + return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port; + #ifdef HAVE_IPV6 + case AF_INET6: + return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port; + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + return 1; + #endif + default: + return 0; + } +} + + +int sock_addr_is_addr_eq (const sock_addr *saddr1, const sock_addr *saddr2) +{ + if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; + switch (saddr1->plain.sa_family) { + case AF_INET: + return saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr; + #ifdef HAVE_IPV6 + case AF_INET6: + return 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr, + sizeof(struct in6_addr)); + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path); + #endif + default: + return 0; + } +} + + +#if 0 +int sock_addr_is_addr_port_eq (const sock_addr *saddr1, const sock_addr *saddr2) +{ + if (!sock_addr_is_family_eq(saddr1, saddr2)) return 0; + switch (saddr1->plain.sa_family) { + case AF_INET: + return saddr1->ipv4.sin_port == saddr2->ipv4.sin_port + && saddr1->ipv4.sin_addr.s_addr == saddr2->ipv4.sin_addr.s_addr; + #ifdef HAVE_IPV6 + case AF_INET6: + return saddr1->ipv6.sin6_port == saddr2->ipv6.sin6_port + && 0 == memcmp(&saddr1->ipv6.sin6_addr, &saddr2->ipv6.sin6_addr, + sizeof(struct in6_addr)); + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + return 0 == strcmp(saddr1->un.sun_path, saddr2->un.sun_path); + #endif + default: + return 0; + } +} +#endif + + +int sock_addr_is_addr_eq_bits(const sock_addr *a, const sock_addr *b, int bits) { + switch (a->plain.sa_family) { + case AF_INET: + { + uint32_t nm; /* build netmask */ + if (bits > 32) bits = 32; + nm = htonl(~((1u << (32 - (0 != bits ? bits : 32))) - 1)); + if (b->plain.sa_family == AF_INET) { + return + (a->ipv4.sin_addr.s_addr & nm) == (b->ipv4.sin_addr.s_addr & nm); + } + #ifdef HAVE_IPV6 + else if (b->plain.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&b->ipv6.sin6_addr)) { + #ifdef s6_addr32 + in_addr_t x = b->ipv6.sin6_addr.s6_addr32[3]; + #else + in_addr_t x; + memcpy(&x, b->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); + #endif + return ((a->ipv4.sin_addr.s_addr & nm) == (x & nm)); + } + #endif + return 0; + } + #ifdef HAVE_IPV6 + case AF_INET6: + if (bits > 128) bits = 128; + if (b->plain.sa_family == AF_INET6) { + uint8_t *c = (uint8_t *)&a->ipv6.sin6_addr.s6_addr[0]; + uint8_t *d = (uint8_t *)&b->ipv6.sin6_addr.s6_addr[0]; + int match; + do { + match = (bits >= 8) + ? *c++ == *d++ + : (*c >> (8 - bits)) == (*d >> (8 - bits)); + } while (match && (bits -= 8) > 0); + return match; + } + else if (b->plain.sa_family == AF_INET + && IN6_IS_ADDR_V4MAPPED(&a->ipv6.sin6_addr)) { + uint32_t nm = bits < 128 + ? htonl(~(~0u >> (bits > 96 ? bits - 96 : 0))) + : ~0u; + #ifdef s6_addr32 + in_addr_t x = a->ipv6.sin6_addr.s6_addr32[3]; + #else + in_addr_t x; + memcpy(&x, a->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t)); + #endif + return ((x & nm) == (b->ipv4.sin_addr.s_addr & nm)); + } + return 0; + #endif + #ifdef HAVE_SYS_UN_H + /*case AF_UNIX:*/ + #endif + default: + return 0; + } +} + + +int sock_addr_assign (sock_addr *saddr, int family, unsigned short nport, const void *naddr) +{ + switch (family) { + case AF_INET: + memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_port = nport; + memcpy(&saddr->ipv4.sin_addr, naddr, 4); + return 0; + #ifdef HAVE_IPV6 + case AF_INET6: + memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6)); + saddr->ipv6.sin6_family = AF_INET6; + saddr->ipv6.sin6_port = nport; + memcpy(&saddr->ipv6.sin6_addr, naddr, 16); + return 0; + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + { + size_t len = strlen((char *)naddr) + 1; + if (len > sizeof(saddr->un.sun_path)) { + errno = ENAMETOOLONG; + return -1; + } + memset(&saddr->un, 0, sizeof(struct sockaddr_un)); + saddr->un.sun_family = AF_UNIX; + memcpy(saddr->un.sun_path, naddr, len); + return 0; + } + #endif + default: + errno = EAFNOSUPPORT; + return -1; + } +} + + +int sock_addr_inet_pton(sock_addr *saddr, const char *str, + int family, unsigned short port) +{ + switch (family) { + case AF_INET: + memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_port = htons(port); + #if defined(HAVE_INET_ATON) /*(Windows does not provide inet_aton())*/ + return (0 != inet_aton(str, &saddr->ipv4.sin_addr)); + #else + return ((saddr->ipv4.sin_addr.s_addr = inet_addr(str)) != INADDR_NONE); + #endif + #ifdef HAVE_IPV6 + case AF_INET6: + memset(&saddr->ipv6, 0, sizeof(struct sockaddr_in6)); + saddr->ipv6.sin6_family = AF_INET6; + saddr->ipv6.sin6_port = htons(port); + return inet_pton(AF_INET6, str, &saddr->ipv6.sin6_addr); + #endif + default: + errno = EAFNOSUPPORT; + return -1; + } +} + + +const char * sock_addr_inet_ntop(const sock_addr *saddr, char *buf, socklen_t sz) +{ + switch (saddr->plain.sa_family) { + case AF_INET: + #if defined(HAVE_INET_PTON) /*(expect inet_ntop if inet_pton)*/ + return inet_ntop(AF_INET,(const void *)&saddr->ipv4.sin_addr,buf,sz); + #else /*(inet_ntoa() not thread-safe)*/ + return inet_ntoa(saddr->ipv4.sin_addr); + #endif + #ifdef HAVE_IPV6 + case AF_INET6: + return inet_ntop(AF_INET6,(const void *)&saddr->ipv6.sin6_addr,buf,sz); + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + return saddr->un.sun_path; + #endif + default: + errno = EAFNOSUPPORT; + return NULL; + } +} + + +int sock_addr_inet_ntop_copy_buffer(buffer *b, const sock_addr *saddr) +{ + /*(incur cost of extra copy to avoid potential extra memory allocation)*/ + char buf[UNIX_PATH_MAX]; + const char *s = sock_addr_inet_ntop(saddr, 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 *saddr) +{ + /*(incur cost of extra copy to avoid potential extra memory allocation)*/ + char buf[UNIX_PATH_MAX]; + const char *s = sock_addr_inet_ntop(saddr, buf, sizeof(buf)); + if (NULL == s) return -1; /*(buffer not modified if any error occurs)*/ + buffer_append_string(b, s); + return 0; +} + +int sock_addr_stringify_append_buffer(buffer *b, const sock_addr *saddr) +{ + switch (saddr->plain.sa_family) { + case AF_INET: + if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) return -1; + buffer_append_string_len(b, CONST_STR_LEN(":")); + buffer_append_int(b, ntohs(saddr->ipv4.sin_port)); + return 0; + #ifdef HAVE_IPV6 + case AF_INET6: + buffer_append_string_len(b, CONST_STR_LEN("[")); + if (0 != sock_addr_inet_ntop_append_buffer(b, saddr)) { + buffer_string_set_length(b, buffer_string_length(b)-1); + return -1; + } + buffer_append_string_len(b, CONST_STR_LEN("]")); + buffer_append_string_len(b, CONST_STR_LEN(":")); + buffer_append_int(b, ntohs(saddr->ipv6.sin6_port)); + return 0; + #endif + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + buffer_append_string(b, saddr->un.sun_path); + return 0; + #endif + default: + return 0; + } +} + + +int sock_addr_nameinfo_append_buffer(server *srv, buffer *b, const sock_addr *saddr) +{ + /*(this routine originates from + * http-header-glue.c:http_response_redirect_to_directory())*/ + /*(note: name resolution here is *blocking*)*/ + switch (saddr->plain.sa_family) { + case AF_INET: + { + struct hostent *he = gethostbyaddr((char *)&saddr->ipv4.sin_addr, + sizeof(struct in_addr), AF_INET); + if (NULL == he) { + log_error_write(srv, __FILE__, __LINE__, + "SdS", "NOTICE: gethostbyaddr failed: ", + h_errno, ", using ip-address instead"); + + sock_addr_inet_ntop_append_buffer(b, saddr); + } else { + buffer_append_string(b, he->h_name); + } + return 0; + } + #ifdef HAVE_IPV6 + case AF_INET6: + { + char hbuf[256]; + if (0 != getnameinfo((const struct sockaddr *)(&saddr->ipv6), + sizeof(saddr->ipv6), + hbuf, sizeof(hbuf), NULL, 0, 0)) { + log_error_write(srv, __FILE__, __LINE__, + "SSS", "NOTICE: getnameinfo failed: ", + strerror(errno), ", using ip-address instead"); + + buffer_append_string_len(b, CONST_STR_LEN("[")); + sock_addr_inet_ntop_append_buffer(b, saddr); + buffer_append_string_len(b, CONST_STR_LEN("]")); + } else { + buffer_append_string(b, hbuf); + } + return 0; + } + #endif + default: + log_error_write(srv, __FILE__, __LINE__, + "S", "ERROR: unsupported address-type"); + return -1; + } +} + + +int sock_addr_from_str_hints(server *srv, sock_addr *saddr, socklen_t *len, const char *str, int family, unsigned short port) +{ + /*(note: name resolution here is *blocking*)*/ + switch(family) { + case AF_UNSPEC: + if (0 == strcmp(str, "localhost")) { + /*(special-case "localhost" to IPv4 127.0.0.1)*/ + memset(saddr, 0, sizeof(struct sockaddr_in)); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + return 1; + } + #ifdef HAVE_IPV6 + else { + struct addrinfo hints, *res; + int r; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", + gai_strerror(r), "'", str, "'"); + return 0; + } + + memcpy(saddr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + if (AF_INET6 == saddr->plain.sa_family) { + saddr->ipv6.sin6_port = htons(port); + *len = sizeof(struct sockaddr_in6); + } + else { /* AF_INET */ + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + } + return 1; + } + #else + /* fall through */ + #endif + #ifdef HAVE_IPV6 + case AF_INET6: + memset(saddr, 0, sizeof(struct sockaddr_in6)); + saddr->ipv6.sin6_family = AF_INET6; + if (0 == strcmp(str, "::")) { + saddr->ipv6.sin6_addr = in6addr_any; + } + else if (0 == strcmp(str, "::1")) { + saddr->ipv6.sin6_addr = in6addr_loopback; + } + else { + struct addrinfo hints, *res; + int r; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { + hints.ai_family = AF_INET; + if ( + #ifdef EAI_ADDRFAMILY + EAI_ADDRFAMILY == r && + #endif + 0 == getaddrinfo(str, NULL, &hints, &res)) { + memcpy(saddr, res->ai_addr, res->ai_addrlen); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + /*assert(*len == res->ai_addrlen);*/ + freeaddrinfo(res); + return 1; + } + + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", + gai_strerror(r), "'", str, "'"); + + return 0; + } + + memcpy(saddr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + } + saddr->ipv6.sin6_port = htons(port); + *len = sizeof(struct sockaddr_in6); + return 1; + #endif + case AF_INET: + memset(saddr, 0, sizeof(struct sockaddr_in)); + saddr->ipv4.sin_family = AF_INET; + if (0 == strcmp(str, "0.0.0.0")) { + saddr->ipv4.sin_addr.s_addr = htonl(INADDR_ANY); + } + else if (0 == strcmp(str, "127.0.0.1")) { + saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + } + else { + #ifdef HAVE_INET_PTON + /*(reuse HAVE_INET_PTON for presence of getaddrinfo())*/ + struct addrinfo hints, *res; + int r; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", + gai_strerror(r), "'", str, "'"); + return 0; + } + + memcpy(saddr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + #else + struct hostent *he = gethostbyname(str); + if (NULL == he) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "gethostbyname failed:", h_errno, str); + return 0; + } + + if (he->h_addrtype != AF_INET) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "addr-type != AF_INET:", he->h_addrtype); + return 0; + } + + if (he->h_length != sizeof(struct in_addr)) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "addr-length != sizeof(in_addr):",he->h_length); + return 0; + } + + memcpy(&saddr->ipv4.sin_addr.s_addr, + he->h_addr_list[0], he->h_length); + #endif + } + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + return 1; + #ifdef HAVE_SYS_UN_H + case AF_UNIX: + memset(saddr, 0, sizeof(struct sockaddr_un)); + saddr->un.sun_family = AF_UNIX; + { + size_t hostlen = strlen(str) + 1; + if (hostlen > sizeof(saddr->un.sun_path)) { + log_error_write(srv, __FILE__, __LINE__, "sS", + "unix socket filename too long:", str); + /*errno = ENAMETOOLONG;*/ + return 0; + } + memcpy(saddr->un.sun_path, str, hostlen); + #if defined(SUN_LEN) + *len = SUN_LEN(&saddr->un); + #else + /* stevens says: */ + *len = hostlen + sizeof(saddr->un.sun_family); + #endif + } + return 1; + #else + case AF_UNIX: + log_error_write(srv, __FILE__, __LINE__, "s", + "unix domain sockets are not supported."); + return 0; + #endif + default: + log_error_write(srv, __FILE__, __LINE__, "sd", + "address family unsupported:", family); + /*errno = EAFNOSUPPORT;*/ + return 0; + } +} + + +int sock_addr_from_str_numeric(server *srv, sock_addr *saddr, const char *str) +{ + /*(note: does not handle port if getaddrinfo() is not available)*/ + /*(note: getaddrinfo() is stricter than inet_aton() in what is accepted)*/ + /*(this routine originates from mod_extforward.c:ipstr_to_sockaddr()*/ + #ifdef HAVE_IPV6 + struct addrinfo hints, *addrlist = NULL; + int result; + + /** + * quoting $ man getaddrinfo + * + * NOTES + * AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3. + * AI_NUMERICSERV is available since glibc 2.3.4. + */ + #ifndef AI_NUMERICSERV + #define AI_NUMERICSERV 0 + #endif + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; + + errno = 0; + result = getaddrinfo(str, NULL, &hints, &addrlist); + + if (result != 0) { + log_error_write(srv, __FILE__, __LINE__, "SSSs(S)", + "could not parse ip address ", str, " because ", + gai_strerror(result), strerror(errno)); + } else if (addrlist == NULL) { + log_error_write(srv, __FILE__, __LINE__, "SSS", + "Problem in parsing ip address ", str, + ": succeeded, but no information returned"); + result = -1; + } else switch (addrlist->ai_family) { + case AF_INET: + memcpy(&saddr->ipv4, addrlist->ai_addr, sizeof(saddr->ipv4)); + force_assert(AF_INET == saddr->plain.sa_family); + break; + case AF_INET6: + memcpy(&saddr->ipv6, addrlist->ai_addr, sizeof(saddr->ipv6)); + force_assert(AF_INET6 == saddr->plain.sa_family); + break; + default: + log_error_write(srv, __FILE__, __LINE__, "SSS", + "Problem in parsing ip address ", str, + ": succeeded, but unknown family"); + result = -1; + break; + } + + freeaddrinfo(addrlist); + return (0 == result); + #else + UNUSED(srv); + saddr->ipv4.sin_addr.s_addr = inet_addr(str); + saddr->plain.sa_family = AF_INET; + return (saddr->ipv4.sin_addr.s_addr != 0xFFFFFFFF); + #endif +} + + +int sock_addr_from_buffer_hints_numeric(server *srv, sock_addr *saddr, socklen_t *len, const buffer *b, int family, unsigned short port) +{ + /*(this routine originates from mod_fastcgi.c and mod_scgi.c)*/ + if (buffer_string_is_empty(b)) { + /*(preserve existing behavior (for now))*/ + /*(would be better if initialized default when reading config)*/ + memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + return 1; + } + else if (1 == sock_addr_inet_pton(saddr, b->ptr, family, port)) { + *len = (family == AF_INET) + ? sizeof(struct sockaddr_in) /* family == AF_INET */ + : sizeof(struct sockaddr_in6); /* family == AF_INET6 */ + return 1; + } + #if defined(HAVE_IPV6) && defined(HAVE_INET_PTON) + else if (family == AF_INET6) { + log_error_write(srv, __FILE__, __LINE__, "sb", + "invalid IPv6 address literal:", b); + return 0; + } + #endif + #ifndef HAVE_INET_PTON /*(preserve existing behavior (for now))*/ + else { + struct hostent *he = gethostbyname(b->ptr); + if (NULL == he) { + log_error_write(srv, __FILE__, __LINE__, "sdb", + "gethostbyname failed:", h_errno, b); + return 0; + } + + if (he->h_addrtype != AF_INET) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "addr-type != AF_INET:", he->h_addrtype); + return 0; + } + + if (he->h_length != sizeof(struct in_addr)) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "addr-length != sizeof(in_addr):",he->h_length); + return 0; + } + + memset(&saddr->ipv4, 0, sizeof(struct sockaddr_in)); + memcpy(&saddr->ipv4.sin_addr.s_addr, he->h_addr_list[0], he->h_length); + saddr->ipv4.sin_family = AF_INET; + saddr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + } + #else + UNUSED(srv); + #endif + + return 0; +} diff --git a/src/sock_addr.h b/src/sock_addr.h new file mode 100644 index 00000000..e949e7ef --- /dev/null +++ b/src/sock_addr.h @@ -0,0 +1,51 @@ +#ifndef INCLUDED_SOCK_ADDR_H +#define INCLUDED_SOCK_ADDR_H +#include "first.h" + +#include <sys/types.h> +#include "sys-socket.h" + +#include "base_decls.h" +#include "buffer.h" + + +union sock_addr { +#ifdef HAVE_IPV6 + struct sockaddr_in6 ipv6; +#endif + struct sockaddr_in ipv4; +#ifdef HAVE_SYS_UN_H + struct sockaddr_un un; +#endif + struct sockaddr plain; +}; + + +static inline int sock_addr_get_family (const sock_addr *saddr); +static inline int sock_addr_get_family (const sock_addr *saddr) { + return saddr->plain.sa_family; +} + +unsigned short sock_addr_get_port (const sock_addr *saddr); +int sock_addr_is_addr_wildcard (const sock_addr *saddr); +int sock_addr_is_family_eq (const sock_addr *saddr1, const sock_addr *saddr2); +int sock_addr_is_port_eq (const sock_addr *saddr1, const sock_addr *saddr2); +int sock_addr_is_addr_eq (const sock_addr *saddr1, const sock_addr *saddr2); +/*int sock_addr_is_addr_port_eq (const sock_addr *saddr1, const sock_addr *saddr2);*/ +int sock_addr_is_addr_eq_bits(const sock_addr *a, const sock_addr *b, int bits); +int sock_addr_assign (sock_addr *saddr, int family, unsigned short nport, const void *naddr); + +int sock_addr_inet_pton(sock_addr *saddr, const char *str, int family, unsigned short port); + +const char * sock_addr_inet_ntop(const sock_addr *saddr, char *buf, socklen_t sz); +int sock_addr_inet_ntop_copy_buffer(buffer *b, const sock_addr *saddr); +int sock_addr_inet_ntop_append_buffer(buffer *b, const sock_addr *saddr); +int sock_addr_stringify_append_buffer(buffer *b, const sock_addr *saddr); +int sock_addr_nameinfo_append_buffer(server *srv, buffer *b, const sock_addr *saddr); + +int sock_addr_from_buffer_hints_numeric(server *srv, sock_addr *saddr, socklen_t *len, const buffer *b, int family, unsigned short port); +int sock_addr_from_str_hints(server *srv, sock_addr *saddr, socklen_t *len, const char *str, int family, unsigned short port); +int sock_addr_from_str_numeric(server *srv, sock_addr *saddr, const char *str); + + +#endif diff --git a/src/sys-socket.h b/src/sys-socket.h index 93a47404..25b7eb0f 100644 --- a/src/sys-socket.h +++ b/src/sys-socket.h @@ -16,8 +16,9 @@ #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> +#ifdef HAVE_SYS_UN_H #include <sys/un.h> -#include <arpa/inet.h> +#endif #endif diff --git a/src/test_configfile.c b/src/test_configfile.c index 75cd66e4..3618be40 100644 --- a/src/test_configfile.c +++ b/src/test_configfile.c @@ -47,22 +47,7 @@ static void test_configfile_addrbuf_eq_remote_ip_mask (void) { sock_addr rmt; for (i = 0; i < (int)(sizeof(rmtmask)/sizeof(rmtmask[0])); ++i) { - #ifndef HAVE_INET_PTON - rmt.ipv4.sin_family = AF_INET; - rmt.ipv4.sin_addr.s_addr = inet_addr(rmtmask[i].rmtstr); - #else - if (rmtmask[i].rmtfamily == AF_INET) { - rmt.ipv4.sin_family = AF_INET; - inet_pton(AF_INET, rmtmask[i].rmtstr, &rmt.ipv4.sin_addr); - #ifdef HAVE_IPV6 - } else if (rmtmask[i].rmtfamily == AF_INET6) { - rmt.ipv6.sin6_family = AF_INET6; - inet_pton(AF_INET6, rmtmask[i].rmtstr, &rmt.ipv6.sin6_addr); - #endif - } else { - continue; - } - #endif + sock_addr_inet_pton(&rmt, rmtmask[i].rmtstr, rmtmask[i].rmtfamily, 0); buffer_copy_string(s, rmtmask[i].string); slash = strchr(s->ptr,'/'); assert(slash); m = config_addrbuf_eq_remote_ip_mask(NULL, s, slash, &rmt); |