Skip to content

Commit

Permalink
Merge pull request #310 from getdnsapi/features/getdns_context_set_lo…
Browse files Browse the repository at this point in the history
…gfunc

A configurable log function
  • Loading branch information
wtoorop authored Jun 28, 2017
2 parents 280e72a + 91ccbcd commit 45884a2
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 160 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
* 2017-07-??: Version 1.1.2
* Bugfix for parallel make install
* Bugfix to trigger event callbacks on socket errors
* A getdns_context_set_logfunc() function with which one may
register a callback log function for certain library subsystems
at certain levels. Currently this can only be used for
upstream stastistics subsystem.

* 2017-06-15: Version 1.1.1
* Bugfix #306 hanging/segfaulting on certain (IPv6) upstream failures
* Spelling fix s/receive/receive. Thanks Andreas Schulze.
Expand Down
11 changes: 6 additions & 5 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ sinclude(./m4/acx_getaddrinfo.m4)
sinclude(./m4/ax_check_compile_flag.m4)
sinclude(./m4/pkg.m4)

AC_INIT([getdns], [1.1.1], [[email protected]], [], [https://getdnsapi.net])
AC_INIT([getdns], [1.1.2], [[email protected]], [], [https://getdnsapi.net])

# Dont forget to put a dash in front of the release candidate!!!
# That is how it is done with semantic versioning!
#
AC_SUBST(RELEASE_CANDIDATE, [])
AC_SUBST(RELEASE_CANDIDATE, [-rc1])

# Set current date from system if not set
AC_ARG_WITH([current-date],
Expand All @@ -51,7 +51,7 @@ AC_ARG_WITH([current-date],
[CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`"])

AC_SUBST(GETDNS_VERSION, ["AC_PACKAGE_VERSION$RELEASE_CANDIDATE"])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x01010100])
AC_SUBST(GETDNS_NUMERIC_VERSION, [0x010101c1])
AC_SUBST(API_VERSION, ["December 2015"])
AC_SUBST(API_NUMERIC_VERSION, [0x07df0c00])
GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRENT_DATE for the $API_VERSION version of the API"
Expand Down Expand Up @@ -83,9 +83,10 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_NAME $GETDNS_VERSION configured on $CURRE
# getdns-0.9.0 had libversion 5:0:4
# getdns-1.0.0 had libversion 5:1:4
# getdns-1.1.0 had libversion 6:0:0
# getdns-1.1.1 has libversion 6:1:0
# getdns-1.1.1 had libversion 6:1:0
# getdns-1.1.2 will have libversion 7:0:1
#
GETDNS_LIBVERSION=6:1:0
GETDNS_LIBVERSION=7:0:1

AC_SUBST(GETDNS_COMPILATION_COMMENT)
AC_SUBST(GETDNS_LIBVERSION)
Expand Down
192 changes: 104 additions & 88 deletions src/const-info.c

Large diffs are not rendered by default.

84 changes: 67 additions & 17 deletions src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ typedef unsigned short in_port_t;

#include <assert.h>
#include <ctype.h>
#include <stdarg.h>

#ifdef HAVE_PTHREAD
#include <pthread.h>
Expand Down Expand Up @@ -241,16 +242,13 @@ add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
}
#endif

#if !defined(STUB_NATIVE_DNSSEC) || (defined(DAEMON_DEBUG) && DAEMON_DEBUG)
static uint8_t*
upstream_addr(getdns_upstream *upstream)
{
return upstream->addr.ss_family == AF_INET
? (void *)&((struct sockaddr_in*)&upstream->addr)->sin_addr
: (void *)&((struct sockaddr_in6*)&upstream->addr)->sin6_addr;
}
#endif


static in_port_t
upstream_port(getdns_upstream *upstream)
Expand Down Expand Up @@ -655,6 +653,7 @@ upstreams_create(getdns_context *context, size_t size)
r->current_stateful = 0;
r->tls_backoff_time = context->tls_backoff_time;
r->tls_connection_retries = context->tls_connection_retries;
r->log = context->log;
return r;
}

Expand Down Expand Up @@ -719,6 +718,22 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
GETDNS_FREE(upstreams->mf, upstreams);
}

void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;

if (!upstream || !upstream->upstreams || !upstream->upstreams->log.func
|| !(upstream->upstreams->log.system & system)
|| level > upstream->upstreams->log.level)
return;

va_start(args, fmt);
upstream->upstreams->log.func(
upstream->upstreams->log.userarg, system, level, fmt, args);
va_end(args);
}

void
_getdns_upstream_shutdown(getdns_upstream *upstream)
{
Expand All @@ -732,23 +747,24 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
/* Keep track of the best auth state this upstream has had*/
if (upstream->tls_auth_state > upstream->best_tls_auth_state)
upstream->best_tls_auth_state = upstream->tls_auth_state;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Conn closed : Transport=%s - Resp=%d,Timeouts=%d,Auth=%s,Keepalive(ms)=%d\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->responses_received, (int)upstream->responses_timeouts,
_getdns_auth_str(upstream->tls_auth_state), (int)upstream->keepalive_timeout);
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Upstream stats: Transport=%s - Resp=%d,Timeouts=%d,Best_auth=%s\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->total_responses, (int)upstream->total_timeouts,
_getdns_auth_str(upstream->best_tls_auth_state));
DEBUG_DAEMON("%s %-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
STUB_DEBUG_DAEMON, upstream->addr_str,
_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : Upstream stats: Transport=%s - Conns=%d,Conn_fails=%d,Conn_shutdowns=%d,Backoffs=%d\n",
upstream->addr_str,
(upstream->transport == GETDNS_TRANSPORT_TLS ? "TLS" : "TCP"),
(int)upstream->conn_completed, (int)upstream->conn_setup_failed,
(int)upstream->conn_shutdowns, (int)upstream->conn_backoffs);
#endif

/* Back off connections that never got up service at all (probably no
TCP service or incompatible TLS version/cipher).
Expand All @@ -771,11 +787,11 @@ _getdns_upstream_shutdown(getdns_upstream *upstream)
upstream->conn_setup_failed = 0;
upstream->conn_shutdowns = 0;
upstream->conn_backoffs++;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
DEBUG_DAEMON("%s %-40s : !Backing off this upstream - Will retry as new upstream at %s",
STUB_DEBUG_DAEMON, upstream->addr_str,

_getdns_upstream_log(upstream, GETDNS_LOG_UPSTREAM_STATS, GETDNS_LOG_DEBUG,
"%-40s : !Backing off this upstream - Will retry as new upstream at %s",
upstream->addr_str,
asctime(gmtime(&upstream->conn_retry_time)));
#endif
}
// Reset per connection counters
upstream->queries_sent = 0;
Expand Down Expand Up @@ -920,10 +936,8 @@ upstream_init(getdns_upstream *upstream,

upstream->addr_len = ai->ai_addrlen;
(void) memcpy(&upstream->addr, ai->ai_addr, ai->ai_addrlen);
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
inet_ntop(upstream->addr.ss_family, upstream_addr(upstream),
upstream->addr_str, INET6_ADDRSTRLEN);
#endif

/* How is this upstream doing on connections? */
upstream->conn_completed = 0;
Expand Down Expand Up @@ -1366,6 +1380,11 @@ getdns_context_create_with_extended_memory_functions(
result->update_callback2 = NULL_update_callback;
result->update_userarg = NULL;

result->log.func = NULL;
result->log.userarg = NULL;
result->log.system = 0;
result->log.level = GETDNS_LOG_ERR;

result->mf.mf_arg = userarg;
result->mf.mf.ext.malloc = malloc;
result->mf.mf.ext.realloc = realloc;
Expand Down Expand Up @@ -1689,6 +1708,37 @@ getdns_context_get_update_callback(getdns_context *context, void **userarg,
return GETDNS_RETURN_GOOD;
}

getdns_return_t
getdns_context_set_logfunc(getdns_context *context, void *userarg,
uint64_t system, getdns_loglevel_type level, getdns_logfunc_type log)
{
if (!context)
return GETDNS_RETURN_INVALID_PARAMETER;

context->log.func = log;
context->log.userarg = userarg;
context->log.system = system;
context->log.level = level;
if (context->upstreams) {
context->upstreams->log = context->log;
}
return GETDNS_RETURN_GOOD;
}

void _getdns_context_log(getdns_context *context, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...)
{
va_list args;

if (!context || !context->log.func || !(context->log.system & system)
|| level > context->log.level)
return;

va_start(args, fmt);
context->log.func(context->log.userarg, system, level, fmt, args);
va_end(args);
}

#ifdef HAVE_LIBUNBOUND
/*
* Helpers to set options on the unbound ctx
Expand Down
19 changes: 17 additions & 2 deletions src/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ typedef struct getdns_upstream {

socklen_t addr_len;
struct sockaddr_storage addr;
#if defined(DAEMON_DEBUG) && DAEMON_DEBUG
char addr_str[INET6_ADDRSTRLEN];
#endif

/**
* How is this upstream doing over UDP?
Expand Down Expand Up @@ -238,6 +236,13 @@ typedef struct getdns_upstream {

} getdns_upstream;

typedef struct getdns_log_config {
getdns_logfunc_type func;
void *userarg;
uint64_t system;
getdns_loglevel_type level;
} getdns_log_config;

typedef struct getdns_upstreams {
struct mem_funcs mf;
size_t referenced;
Expand All @@ -246,6 +251,7 @@ typedef struct getdns_upstreams {
size_t current_stateful;
uint16_t tls_backoff_time;
uint16_t tls_connection_retries;
getdns_log_config log;
getdns_upstream upstreams[];
} getdns_upstreams;

Expand Down Expand Up @@ -296,6 +302,8 @@ struct getdns_context {
getdns_update_callback2 update_callback2;
void *update_userarg;

getdns_log_config log;

int processing;
int destroying;

Expand Down Expand Up @@ -395,6 +403,13 @@ struct getdns_context {
#endif /* HAVE_MDNS_SUPPORT */
}; /* getdns_context */

void _getdns_upstream_log(getdns_upstream *upstream, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...);

void _getdns_context_log(getdns_context *context, uint64_t system,
getdns_loglevel_type level, const char *fmt, ...);


/** internal functions **/
/**
* Sets up the unbound contexts with stub or recursive behavior
Expand Down
1 change: 0 additions & 1 deletion src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#define STUB_DEBUG_READ "------- READ: "
#define STUB_DEBUG_WRITE "------- WRITE: "
#define STUB_DEBUG_CLEANUP "--- CLEANUP: "
#define STUB_DEBUG_DAEMON "GETDNS_DAEMON: "

#ifdef GETDNS_ON_WINDOWS
#define DEBUG_ON(...) do { \
Expand Down
40 changes: 34 additions & 6 deletions src/getdns/getdns_extra.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <sys/time.h>
#include <stdio.h>
#include <time.h>
#include <stdarg.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -501,13 +502,40 @@ getdns_context_set_tls_query_padding_blocksize(getdns_context *context, uint16_t
*/
getdns_return_t
getdns_context_unset_edns_maximum_udp_payload_size(getdns_context *context);
/** @}
*/

/**
* \addtogroup getdns_context
* @{
*/

typedef enum getdns_loglevel_type {
GETDNS_LOG_EMERG = 0,
GETDNS_LOG_ALERT = 1,
GETDNS_LOG_CRIT = 2,
GETDNS_LOG_ERR = 3,
GETDNS_LOG_WARNING = 4,
GETDNS_LOG_NOTICE = 5,
GETDNS_LOG_INFO = 6,
GETDNS_LOG_DEBUG = 7
} getdns_loglevel_type;

#define GETDNS_LOG_EMERG_TEXT "System is unusable"
#define GETDNS_LOG_ALERT_TEXT "Action must be taken immediately"
#define GETDNS_LOG_CRIT_TEXT "Critical conditions"
#define GETDNS_LOG_ERR_TEXT "Error conditions"
#define GETDNS_LOG_WARNING_TEXT "Warning conditions"
#define GETDNS_LOG_NOTICE_TEXT "normal, but significant, condition"
#define GETDNS_LOG_INFO_TEXT "Informational message"
#define GETDNS_LOG_DEBUG_TEXT "Debug-level message"

#define GETDNS_LOG_UPSTREAM_STATS 4096
#define GETDNS_LOG_UPSTREAM_STATS_TEXT "Log messages about upstream statistics"

typedef void (*getdns_logfunc_type) (void *userarg, uint64_t log_systems,
getdns_loglevel_type, const char *, va_list ap);

/**
*
*/
getdns_return_t
getdns_context_set_logfunc(getdns_context *context, void *userarg,
uint64_t system, getdns_loglevel_type level, getdns_logfunc_type func);

/**
* Get the current resolution type setting from this context.
Expand Down
1 change: 1 addition & 0 deletions src/libgetdns.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ getdns_context_set_follow_redirects
getdns_context_set_idle_timeout
getdns_context_set_limit_outstanding_queries
getdns_context_set_listen_addresses
getdns_context_set_logfunc
getdns_context_set_memory_functions
getdns_context_set_namespaces
getdns_context_set_resolution_type
Expand Down
2 changes: 1 addition & 1 deletion src/mk-const-info.c.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cat > const-info.c << END_OF_HEAD
static struct const_info consts_info[] = {
{ -1, NULL, "/* <unknown getdns value> */" },
END_OF_HEAD
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%4d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%4d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%4d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns.h.in getdns/getdns_extra.h.in | sed 's/,,/,/g' >> const-info.c
gawk '/^[ ]+GETDNS_[A-Z_]+[ ]+=[ ]+[0-9]+/{ key = sprintf("%7d", $3); consts[key] = $1; }/^#define GETDNS_[A-Z_]+[ ]+[0-9]+/ && !/^#define GETDNS_RRTYPE/ && !/^#define GETDNS_RRCLASS/ && !/^#define GETDNS_OPCODE/ && !/^#define GETDNS_RCODE/ && !/_TEXT/{ key = sprintf("%7d", $3); consts[key] = $2; }/^#define GETDNS_[A-Z_]+[ ]+\(\(getdns_(return|append_name)_t) [0-9]+ \)/{ key = sprintf("%7d", $4); consts[key] = $2; }END{ n = asorti(consts, const_vals); for ( i = 1; i <= n; i++) { val = const_vals[i]; name = consts[val]; print "\t{ "val", \""name"\", "name"_TEXT },"}}' getdns/getdns_extra.h.in getdns/getdns.h.in | sed 's/,,/,/g' >> const-info.c
cat >> const-info.c << END_OF_TAIL
};
Expand Down
Loading

0 comments on commit 45884a2

Please sign in to comment.