Browse Source

[core] isolate sock_addr manipulation

personal/stbuehler/1.4.48-mod-proxy-fix
Glenn Strauss 4 years ago
parent
commit
1367f60626
  1. 4
      src/CMakeLists.txt
  2. 11
      src/Makefile.am
  3. 7
      src/SConscript
  4. 13
      src/base.h
  5. 75
      src/configfile-glue.c
  6. 2
      src/connections-glue.c
  7. 2
      src/connections.c
  8. 4
      src/gw_backend.c
  9. 26
      src/http-header-glue.c
  10. 457
      src/inet_ntop_cache.c
  11. 16
      src/inet_ntop_cache.h
  12. 3
      src/meson.build
  13. 25
      src/mod_evasive.c
  14. 18
      src/mod_extforward.c
  15. 40
      src/mod_proxy.c
  16. 36
      src/network.c
  17. 2
      src/request.c
  18. 39
      src/server.c
  19. 685
      src/sock_addr.c
  20. 51
      src/sock_addr.h
  21. 3
      src/sys-socket.h
  22. 17
      src/test_configfile.c

4
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

11
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)

7
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 \

13
src/base.h

@ -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)

75
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, ':');

2
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)) ;

2
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);

4
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);

26
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;

457
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;

16
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);

3
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',

25
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) {

18
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)*/

40
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;

36
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;

2
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>

39
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);
}

685
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