]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add unbound logging glue code
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 1 Nov 2019 13:53:00 +0000 (07:53 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 1 Nov 2019 13:55:34 +0000 (07:55 -0600)
This _has_ been tested and appears to work fine.

src/modules/rlm_unbound/all.mk.in
src/modules/rlm_unbound/log.c [new file with mode: 0644]
src/modules/rlm_unbound/log.h [new file with mode: 0644]

index 710cef36614ae8075b35eb438af26c07030a1b22..b865f479650ac123661deea27cc92d9b4f5a7936 100644 (file)
@@ -6,7 +6,7 @@ TARGET          := $(TARGETNAME).a
 endif
 endif
 
-SOURCES                := $(TARGETNAME).c io.c
+SOURCES                := $(TARGETNAME).c io.c log.c
 
 SRC_CFLAGS     := @mod_cflags@
 TGT_LDLIBS     := @mod_ldflags@ $(OPENSSL_LIBS)
diff --git a/src/modules/rlm_unbound/log.c b/src/modules/rlm_unbound/log.c
new file mode 100644 (file)
index 0000000..1baa480
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *   This program is is free software; you can redistribute it 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.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file rlm_unbound/log.c
+ * @brief Provides interface between libunbound and the FreeRADIUS event loop
+ *
+ * @copyright 2019 The FreeRADIUS server project
+ * @copyright 2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSID("$Id$")
+
+#define LOG_PREFIX "rlm_unbound - "
+
+#include <freeradius-devel/util/syserror.h>
+#include "log.h"
+
+/** Write libunbound output to the server or request log
+ *
+ * @param[in] cookie   The current thread.
+ * @param[in] buf      Log message from unbound.
+ * @param[in] size     Length of log message.
+ */
+static ssize_t _unbound_log_write(void *cookie, char const *buf, size_t size)
+{
+       unbound_log_t   *u_log = talloc_get_type_abort(cookie, unbound_log_t);
+       REQUEST         *request = u_log->request;
+       size_t          len = size;
+
+       if (len == 0) return len;
+       if (buf[len - 1] == '\n') len--;        /* Trim trailing new line */
+
+       ROPTIONAL(RDEBUG, DEBUG, "%pV", fr_box_strvalue_len(buf, len));
+
+       return size;
+}
+
+/** Set the debug level for a ub_ctx from the request or global debug level
+ *
+ * @param[in] ub       Unbound context to set log level for.
+ * @param[in] lvl      To set.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+static int unbound_log_lvl_set(struct ub_ctx *ub, fr_log_lvl_t lvl)
+{
+       int ret;
+       int level;
+
+       switch (lvl) {
+       case L_DBG_LVL_DISABLE:
+       case L_DBG_LVL_OFF:
+       case L_DBG_LVL_1:
+               level = 0;
+               break;
+
+       case L_DBG_LVL_2:
+               level = 1;
+               break;
+
+       case L_DBG_LVL_3:
+               level = 2;      /* Mid-to-heavy levels of output */
+               break;
+
+       case L_DBG_LVL_4:
+               level = 3;      /* Pretty crazy amounts of output */
+               break;
+
+       case L_DBG_LVL_MAX:
+       default:
+               level = 4;      /* Insane amounts of output including crypts */
+               break;
+       }
+
+       ret = ub_ctx_debuglevel(ub, level);
+       if (ret != 0) {
+               ERROR("Failed setting unbound log level to %i", level);
+               return -1;
+       }
+
+       return 0;
+}
+
+/** Switch thread-specific libunbound output to the request log destination(s)
+ *
+ */
+int unbound_log_to_request(unbound_log_t *u_log, struct ub_ctx *ub, REQUEST *request)
+{
+       u_log->request = request;
+       return unbound_log_lvl_set(ub, request->log.lvl);
+}
+
+/** Switch thread-specific libunbound output to the global log
+ *
+ * Must be called before a function that previously called #unbound_log_to_request
+ * yields, or can no longer be certain that the REQUEST * set in t->request
+ * is still valid.
+ */
+int unbound_log_to_global(unbound_log_t *u_log, struct ub_ctx *ub)
+{
+       u_log->request = NULL;
+       return unbound_log_lvl_set(ub, fr_debug_lvl);
+}
+
+static int _unbound_log_free(unbound_log_t *u_log)
+{
+       if (u_log->stream) fclose(u_log->stream);
+       return 0;
+}
+
+/** Setup an unbound context for log, and initialise a u_log struct
+ *
+ */
+int unbound_log_init(TALLOC_CTX *ctx, unbound_log_t **u_log_out, struct ub_ctx *ub)
+{
+       char            opt[64]; /* To silence const warns until newer unbound in distros */
+       char            *val;
+       unbound_log_t   *u_log;
+       int             ret;
+
+       /*
+        *      Check if the user tried to configure
+        *      a log destination, and disable it
+        *      if they did.
+        */
+       strcpy(opt, "use-syslog");
+       ret = ub_ctx_get_option(ub, opt, &val);
+       if ((ret != 0) || !val) {
+               ERROR("Failed retrieving unbound syslog settings: %s", ub_strerror(ret));
+               return -1;
+       }
+
+       if (strcmp(val, "yes") == 0) {
+               char vbuff[3];
+
+               strcpy(opt, "use-syslog:");
+               strcpy(vbuff, "no");
+
+               WARN("Disabling unbound syslog output (%s %s) > (%s %s)", opt, val, opt, vbuff);
+
+               ret = ub_ctx_set_option(ub, opt, vbuff);
+               if (ret != 0) {
+                       ERROR("Failed disabling unbound syslog output: %s", ub_strerror(ret));
+                       free(val);
+                       return -1;
+               }
+       }
+       free(val);
+
+       strcpy(opt, "logfile");
+       ret = ub_ctx_get_option(ub, opt, &val);
+       if ((ret != 0) || !val) {
+               ERROR("Failed retrieving unbound logfile settings: %s", ub_strerror(ret));
+               return -1;
+       }
+
+       if (strcmp(val, "yes") == 0) {
+               char vbuff[3];
+
+               WARN("Disabling unbound logfile output (%s %s) > (%s %s)", opt, val, opt, vbuff);
+               strcpy(opt, "logfile:");
+               strcpy(vbuff, "no");
+
+               ret = ub_ctx_set_option(ub, opt, vbuff);
+               if (ret != 0) {
+                       ERROR("Failed disabling unbound logfile output: %s", ub_strerror(ret));
+                       free(val);
+                       return -1;
+               }
+       }
+       free(val);
+
+       MEM(u_log = talloc_zero(ctx, unbound_log_t));
+
+       /*
+        *      Open a FILE stream, and associate a write
+        *      function with it, which then call's
+        *      FreeRADIUS' log functions.
+        */
+       u_log->stream = fopencookie(u_log, "w", (cookie_io_functions_t){ .write = _unbound_log_write });
+       if (!u_log->stream) {
+               ERROR("Failed creating log stream for unbound: %s", fr_syserror(errno));
+               talloc_free(u_log);
+               return -1;
+       }
+       talloc_set_destructor(u_log, _unbound_log_free);        /* Close stream when log struct is freed */
+       setlinebuf(u_log->stream);
+
+       ret = ub_ctx_debugout(ub, u_log->stream);
+       if (ret != 0) {
+               ERROR("Failed setting log stream for unbound: %s", ub_strerror(ret));
+               talloc_free(u_log);
+               return -1;
+       }
+
+       /*
+        *      Set the initial log level and destination
+        */
+       ret = unbound_log_to_global(u_log, ub);
+       if (ret < 0) {
+               talloc_free(u_log);
+               return -1;
+       }
+
+       *u_log_out = u_log;
+
+       return 0;
+}
diff --git a/src/modules/rlm_unbound/log.h b/src/modules/rlm_unbound/log.h
new file mode 100644 (file)
index 0000000..32ccabb
--- /dev/null
@@ -0,0 +1,60 @@
+#pragma once
+/*
+ *   This program is free software; you can redistribute it 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.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @brief Function prototypes and datatypes for the REST (HTTP) transport.
+ * @file rlm_unbound/unbound.h
+ *
+ * @copyright 2019 The FreeRADIUS server project
+ * @copyright 2019 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSIDH(rlm_unbound_log_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <freeradius-devel/server/request.h>
+
+#ifdef HAVE_WDOCUMENTATION
+DIAG_OFF(documentation)
+#endif
+#include <unbound.h>
+#ifdef HAVE_WDOCUMENTATION
+DIAG_ON(documentation)
+#endif
+
+/** Logging state
+ *
+ */
+typedef struct {
+       REQUEST         *request;               //!< Request we're logging to.
+       FILE            *stream;                //!< Stream we use to interface with the
+                                               ///< FreeRADIUS logging functions.
+} unbound_log_t;
+
+int    unbound_log_to_request(unbound_log_t *u_log, struct ub_ctx *ub, REQUEST *request);
+
+int    unbound_log_to_global(unbound_log_t *u_log, struct ub_ctx *ub);
+
+int    unbound_log_init(TALLOC_CTX *ctx, unbound_log_t **u_log_out, struct ub_ctx *ub);
+
+#ifdef __cplusplus
+}
+#endif