diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/sock.c | 74 | ||||
-rw-r--r-- | src/sock.h | 3 |
3 files changed, 79 insertions, 3 deletions
@@ -356,6 +356,9 @@ main (int argc, char **argv) setup_sig(SIGPIPE, SIG_IGN, "SIGPIPE", argv[0]); + if (init_sock()) + exit (EX_SOFTWARE); + #ifdef FILTER_ENABLE if (config->filter) filter_init (); @@ -425,6 +428,8 @@ main (int argc, char **argv) filter_destroy (); #endif /* FILTER_ENABLE */ + cleanup_sock(); + free_config (config); shutdown_logging (); @@ -36,6 +36,50 @@ #include "loop.h" #include "sblist.h" +static struct htab *resolvers; + +static ares_channel setup_resolver (const char *bind_to, const char *bind_to_alt) +{ + htab_value *val = htab_find(resolvers, bind_to); + htab_value *val_alt = NULL; + htab_value tmp_val; + + if (!bind_to) + return NULL; + + if (bind_to_alt) + val_alt = htab_find(resolvers, bind_to_alt); + + if (!val && !val_alt) { + /* struct ares_options options; */ + ares_channel resolver = NULL; + /* memset(&options, 0, sizeof(options)); */ + /* int res = ares_init_options(&resolver, options */ + /* struct ares_options *options, */ + /* int optmask) */ + int res = ares_init(&resolver); + tmp_val = HTV_P(resolver); + } else if (val) { + tmp_val = *val; + } else { + tmp_val = *val_alt; + } + + if (!val) { + htab_insert(resolvers, bind_to, tmp_val); + } + + if (!val_alt && bind_to_alt) { + htab_insert(resolvers, bind_to_alt, tmp_val); + } + + if (val && val_alt && val->p != val_alt->p) { + log_message(LOG_WARNING, "Different resolvers for %s and $s", bind_to, bind_to_alt); + } + + return tmp_val.p; +} + /* * Return a human readable error for getaddrinfo() and getnameinfo(). */ @@ -116,8 +160,9 @@ bind_socket_list (int sockfd, sblist *addresses, int family) int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt) { int sockfd, n; - struct addrinfo hints, *res, *ressave; + struct ares_addrinfo hints, *res, *ressave; char portstr[6]; + ares_channel *resolver = NULL; assert (host != NULL); assert (port > 0); @@ -129,13 +174,21 @@ int opensock (const char *host, int port, const char *bind_to, const char *bind_ "opensock: bind to %s or %s", bind_to, bind_to_alt); } + if (bind_to) { + resolver = setup_resolver(bind_to, bind_to_alt); + } + + if (!resolver) { + log_message (LOG_ERR, "opensock: no resolver for %s", bind_to); + } + memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf (portstr, sizeof (portstr), "%d", port); - n = getaddrinfo (host, portstr, &hints, &res); + n = ares_getaddrinfo (host, portstr, &hints, &res); if (n != 0) { log_message (LOG_ERR, "opensock: Could not retrieve address info for %s:%d: %s", host, port, get_gai_error (n)); @@ -185,7 +238,7 @@ int opensock (const char *host, int port, const char *bind_to, const char *bind_ close (sockfd); } while ((res = res->ai_next) != NULL); - freeaddrinfo (ressave); + ares_freeaddrinfo (ressave); if (res == NULL) { log_message (LOG_ERR, "opensock: Could not establish a connection to %s:%d", @@ -420,3 +473,18 @@ void getpeer_information (union sockaddr_union* addr, char *ipaddr, size_t ipadd void *ipdata = af == AF_INET ? (void*)&addr->v4.sin_addr : (void*)&addr->v6.sin6_addr; inet_ntop(af, ipdata, ipaddr, ipaddr_len); } + + +int init_sock (void) +{ + if (ares_library_init(ARES_LIB_INIT_ALL)) + return -1; + + resolvers = htab_create(10); +} + +void cleanup_sock (void) +{ + htab_destroy(resolvers); + ares_library_cleanup(); +} @@ -50,6 +50,9 @@ union sockaddr_union { struct sockaddr_in6 v6; }; +extern int init_sock(void); +extern void destroy_dock(void); + extern int opensock (const char *host, int port, const char *bind_to, const char *bind_to_alt); extern int listen_sock (const char *addr, uint16_t port, sblist* listen_fds); |