Merge pull request #4639 from opensourcerouting/c-ares-lib

make c-ares DNS resolver available as lib
This commit is contained in:
Quentin Young 2019-07-03 16:49:19 -04:00 committed by GitHub
commit c682502cd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 131 additions and 61 deletions

View File

@ -1560,7 +1560,7 @@ if test "${NHRPD}" != ""; then
AC_MSG_ERROR([trying to build nhrpd, but libcares not found. install c-ares and its -dev headers.])
])
fi
AM_CONDITIONAL([CARES], [test "${NHRPD}" != ""])
dnl ------------------
dnl check Net-SNMP library

1
debian/frr.install vendored
View File

@ -2,6 +2,7 @@ etc/
usr/bin/vtysh
usr/bin/mtracebis
usr/lib/*/frr/libfrr.*
usr/lib/*/frr/libfrrcares.*
usr/lib/*/frr/libfrrospfapiclient.*
usr/lib/frr/*.sh
usr/lib/frr/*d

View File

@ -85,6 +85,7 @@ const char *node_names[] = {
"northbound debug", // NORTHBOUND_DEBUG_NODE,
"vnc debug", // DEBUG_VNC_NODE,
"route-map debug", /* RMAP_DEBUG_NODE */
"resolver debug", /* RESOLVER_DEBUG_NODE */
"aaa", // AAA_NODE,
"keychain", // KEYCHAIN_NODE,
"keychain key", // KEYCHAIN_KEY_NODE,

View File

@ -94,6 +94,7 @@ enum node_type {
NORTHBOUND_DEBUG_NODE, /* Northbound Debug node. */
DEBUG_VNC_NODE, /* Debug VNC node. */
RMAP_DEBUG_NODE, /* Route-map debug node */
RESOLVER_DEBUG_NODE, /* Resolver debug node */
AAA_NODE, /* AAA node. */
KEYCHAIN_NODE, /* Key-chain node. */
KEYCHAIN_KEY_NODE, /* Key-chain key node. */

View File

@ -356,6 +356,12 @@ static struct log_ref ferr_lib_err[] = {
.description = "A callback used to process a configuration change has returned an error while applying the changes",
.suggestion = "Gather log data and open an Issue.",
},
{
.code = EC_LIB_RESOLVER,
.title = "DNS Resolution",
.description = "An error was detected while attempting to resolve a hostname",
.suggestion = "Ensure that DNS is working properly and the hostname is configured in dns. If you are still seeing this error, open an issue"
},
{
.code = END_FERR,
}

View File

@ -84,6 +84,7 @@ enum lib_log_refs {
EC_LIB_GRPC_INIT,
EC_LIB_ID_CONSISTENCY,
EC_LIB_ID_EXHAUST,
EC_LIB_RESOLVER,
};
extern void lib_error_init(void);

View File

@ -17,17 +17,18 @@
#include "vector.h"
#include "thread.h"
#include "lib_errors.h"
#include "nhrpd.h"
#include "nhrp_errors.h"
#include "resolver.h"
#include "command.h"
struct resolver_state {
ares_channel channel;
struct thread_master *master;
struct thread *timeout;
vector read_threads, write_threads;
};
static struct resolver_state state;
static bool resolver_debug;
#define THREAD_RUNNING ((struct thread *)-1)
@ -54,7 +55,8 @@ static int resolver_cb_socket_readable(struct thread *t)
ares_process_fd(r->channel, fd, ARES_SOCKET_BAD);
if (vector_lookup(r->read_threads, fd) == THREAD_RUNNING) {
t = NULL;
thread_add_read(master, resolver_cb_socket_readable, r, fd, &t);
thread_add_read(r->master, resolver_cb_socket_readable, r, fd,
&t);
vector_set_index(r->read_threads, fd, t);
}
resolver_update_timeouts(r);
@ -71,7 +73,7 @@ static int resolver_cb_socket_writable(struct thread *t)
ares_process_fd(r->channel, ARES_SOCKET_BAD, fd);
if (vector_lookup(r->write_threads, fd) == THREAD_RUNNING) {
t = NULL;
thread_add_write(master, resolver_cb_socket_writable, r, fd,
thread_add_write(r->master, resolver_cb_socket_writable, r, fd,
&t);
vector_set_index(r->write_threads, fd, t);
}
@ -91,8 +93,8 @@ static void resolver_update_timeouts(struct resolver_state *r)
tv = ares_timeout(r->channel, NULL, &tvbuf);
if (tv) {
unsigned int timeoutms = tv->tv_sec * 1000 + tv->tv_usec / 1000;
thread_add_timer_msec(master, resolver_cb_timeout, r, timeoutms,
&r->timeout);
thread_add_timer_msec(r->master, resolver_cb_timeout, r,
timeoutms, &r->timeout);
}
}
@ -105,8 +107,8 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable,
if (readable) {
t = vector_lookup_ensure(r->read_threads, fd);
if (!t) {
thread_add_read(master, resolver_cb_socket_readable, r,
fd, &t);
thread_add_read(r->master, resolver_cb_socket_readable,
r, fd, &t);
vector_set_index(r->read_threads, fd, t);
}
} else {
@ -122,8 +124,8 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable,
if (writable) {
t = vector_lookup_ensure(r->write_threads, fd);
if (!t) {
thread_add_read(master, resolver_cb_socket_writable, r,
fd, &t);
thread_add_read(r->master, resolver_cb_socket_writable,
r, fd, &t);
vector_set_index(r->write_threads, fd, t);
}
} else {
@ -137,37 +139,23 @@ static void ares_socket_cb(void *data, ares_socket_t fd, int readable,
}
}
void resolver_init(void)
{
struct ares_options ares_opts;
state.read_threads = vector_init(1);
state.write_threads = vector_init(1);
ares_opts = (struct ares_options){
.sock_state_cb = &ares_socket_cb,
.sock_state_cb_data = &state,
.timeout = 2,
.tries = 3,
};
ares_init_options(&state.channel, &ares_opts,
ARES_OPT_SOCK_STATE_CB | ARES_OPT_TIMEOUT
| ARES_OPT_TRIES);
}
static void ares_address_cb(void *arg, int status, int timeouts,
struct hostent *he)
{
struct resolver_query *query = (struct resolver_query *)arg;
union sockunion addr[16];
void (*callback)(struct resolver_query *, int, union sockunion *);
size_t i;
callback = query->callback;
query->callback = NULL;
if (status != ARES_SUCCESS) {
debugf(NHRP_DEBUG_COMMON, "[%p] Resolving failed", query);
query->callback(query, -1, NULL);
query->callback = NULL;
if (resolver_debug)
zlog_debug("[%p] Resolving failed", query);
callback(query, -1, NULL);
return;
}
@ -186,10 +174,10 @@ static void ares_address_cb(void *arg, int status, int timeouts,
}
}
debugf(NHRP_DEBUG_COMMON, "[%p] Resolved with %d results", query,
(int)i);
query->callback(query, i, &addr[0]);
query->callback = NULL;
if (resolver_debug)
zlog_debug("[%p] Resolved with %d results", query, (int)i);
callback(query, i, &addr[0]);
}
void resolver_resolve(struct resolver_query *query, int af,
@ -199,15 +187,61 @@ void resolver_resolve(struct resolver_query *query, int af,
{
if (query->callback != NULL) {
flog_err(
EC_NHRP_RESOLVER,
EC_LIB_RESOLVER,
"Trying to resolve '%s', but previous query was not finished yet",
hostname);
return;
}
debugf(NHRP_DEBUG_COMMON, "[%p] Resolving '%s'", query, hostname);
if (resolver_debug)
zlog_debug("[%p] Resolving '%s'", query, hostname);
query->callback = callback;
ares_gethostbyname(state.channel, hostname, af, ares_address_cb, query);
resolver_update_timeouts(&state);
}
DEFUN(debug_resolver,
debug_resolver_cmd,
"[no] debug resolver",
NO_STR
DEBUG_STR
"Debug DNS resolver actions\n")
{
resolver_debug = (argc == 2);
return CMD_SUCCESS;
}
static struct cmd_node resolver_debug_node = {RESOLVER_DEBUG_NODE, "", 1};
static int resolver_config_write_debug(struct vty *vty)
{
if (resolver_debug)
vty_out(vty, "debug resolver\n");
return 1;
}
void resolver_init(struct thread_master *tm)
{
struct ares_options ares_opts;
state.master = tm;
state.read_threads = vector_init(1);
state.write_threads = vector_init(1);
ares_opts = (struct ares_options){
.sock_state_cb = &ares_socket_cb,
.sock_state_cb_data = &state,
.timeout = 2,
.tries = 3,
};
ares_init_options(&state.channel, &ares_opts,
ARES_OPT_SOCK_STATE_CB | ARES_OPT_TIMEOUT
| ARES_OPT_TRIES);
install_node(&resolver_debug_node, resolver_config_write_debug);
install_element(CONFIG_NODE, &debug_resolver_cmd);
install_element(ENABLE_NODE, &debug_resolver_cmd);
}

25
lib/resolver.h Normal file
View File

@ -0,0 +1,25 @@
/* C-Ares integration to Quagga mainloop
* Copyright (c) 2014-2015 Timo Teräs
*
* This file is free software: you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _FRR_RESOLVER_H
#define _FRR_RESOLVER_H
#include "thread.h"
#include "sockunion.h"
struct resolver_query {
void (*callback)(struct resolver_query *, int n, union sockunion *);
};
void resolver_init(struct thread_master *tm);
void resolver_resolve(struct resolver_query *query, int af,
const char *hostname, void (*cb)(struct resolver_query *,
int, union sockunion *));
#endif /* _FRR_RESOLVER_H */

View File

@ -285,6 +285,21 @@ lib_libfrrsnmp_la_SOURCES = \
lib/snmp.c \
# end
#
# c-ares support
#
if CARES
lib_LTLIBRARIES += lib/libfrrcares.la
pkginclude_HEADERS += lib/resolver.h
endif
lib_libfrrcares_la_CFLAGS = $(WERROR) $(CARES_CFLAGS)
lib_libfrrcares_la_LDFLAGS = -version-info 0:0:0
lib_libfrrcares_la_LIBADD = $(CARES_LIBS)
lib_libfrrcares_la_SOURCES = \
lib/resolver.c \
#end
#
# ZeroMQ support
#

View File

@ -31,12 +31,6 @@ static struct log_ref ferr_nhrp_err[] = {
.description = "NHRP has detected a error with the Strongswan code",
.suggestion = "Ensure that StrongSwan is configured correctly. Restart StrongSwan and FRR"
},
{
.code = EC_NHRP_RESOLVER,
.title = "NHRP DNS Resolution",
.description = "NHRP has detected an error in an attempt to resolve a hostname",
.suggestion = "Ensure that DNS is working properly and the hostname is configured in dns. If you are still seeing this error, open an issue"
},
{
.code = END_FERR,
}

View File

@ -25,7 +25,6 @@
enum nhrp_log_refs {
EC_NHRP_SWAN = NHRP_FERR_START,
EC_NHRP_RESOLVER,
};
extern void nhrp_error_init(void);

View File

@ -141,7 +141,7 @@ int main(int argc, char **argv)
nhrp_error_init();
vrf_init(NULL, NULL, NULL, NULL, NULL);
nhrp_interface_init();
resolver_init();
resolver_init(master);
/* Run with elevated capabilities, as for all netlink activity
* we need privileges anyway. */

View File

@ -16,6 +16,7 @@
#include "zclient.h"
#include "debug.h"
#include "memory.h"
#include "resolver.h"
DECLARE_MGROUP(NHRPD)
@ -84,15 +85,6 @@ static inline int notifier_active(struct notifier_list *l)
return !list_empty(&l->notifier_head);
}
struct resolver_query {
void (*callback)(struct resolver_query *, int n, union sockunion *);
};
void resolver_init(void);
void resolver_resolve(struct resolver_query *query, int af,
const char *hostname, void (*cb)(struct resolver_query *,
int, union sockunion *));
void nhrp_zebra_init(void);
void nhrp_zebra_terminate(void);

View File

@ -8,8 +8,7 @@ vtysh_scan += $(top_srcdir)/nhrpd/nhrp_vty.c
man8 += $(MANBUILD)/nhrpd.8
endif
nhrpd_nhrpd_LDADD = lib/libfrr.la $(LIBCAP) $(CARES_LIBS)
nhrpd_nhrpd_CFLAGS = $(AM_CFLAGS) $(CARES_CFLAGS)
nhrpd_nhrpd_LDADD = lib/libfrr.la lib/libfrrcares.la $(LIBCAP)
nhrpd_nhrpd_SOURCES = \
nhrpd/linux.c \
nhrpd/netlink_arp.c \
@ -27,7 +26,6 @@ nhrpd_nhrpd_SOURCES = \
nhrpd/nhrp_vc.c \
nhrpd/nhrp_vty.c \
nhrpd/reqid.c \
nhrpd/resolver.c \
nhrpd/vici.c \
nhrpd/zbuf.c \
nhrpd/znl.c \

View File

@ -377,6 +377,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
strlen("debug route-map"))
== 0)
config = config_get(RMAP_DEBUG_NODE, line);
else if (strncmp(line, "debug resolver",
strlen("debug resolver")) == 0)
config = config_get(RESOLVER_DEBUG_NODE, line);
else if (strncmp(line, "debug", strlen("debug")) == 0)
config = config_get(DEBUG_NODE, line);
else if (strncmp(line, "password", strlen("password")) == 0
@ -423,7 +426,7 @@ void vtysh_config_parse_line(void *arg, const char *line)
|| (I) == PREFIX_IPV6_NODE || (I) == FORWARDING_NODE \
|| (I) == DEBUG_NODE || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE \
|| (I) == NORTHBOUND_DEBUG_NODE || (I) == RMAP_DEBUG_NODE \
|| (I) == MPLS_NODE)
|| (I) == RESOLVER_DEBUG_NODE || (I) == MPLS_NODE)
/* Display configuration to file pointer. */
void vtysh_config_dump(void)