The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_unbound.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: f6c77c5aa89000222baa052187c1df2ae2bd620b $
19  * @file rlm_unbound.c
20  * @brief DNS services via libunbound.
21  *
22  * @copyright 2013 The FreeRADIUS server project
23  * @copyright 2013 Brian S. Julin (bjulin@clarku.edu)
24  */
25 RCSID("$Id: f6c77c5aa89000222baa052187c1df2ae2bd620b $")
26 
27 #define LOG_PREFIX mctx->inst->name
28 
29 #include <freeradius-devel/server/base.h>
30 #include <freeradius-devel/server/module_rlm.h>
31 #include <freeradius-devel/server/log.h>
32 #include <freeradius-devel/unlang/xlat_func.h>
33 #include <fcntl.h>
34 
35 #include "io.h"
36 #include "log.h"
37 
38 typedef struct {
39  char const *name;
41 
42  char const *filename; //!< Unbound configuration file
43  char const *resolvconf; //!< resolv.conf file to use
44  char const *hosts; //!< hosts file to load
46 
47 typedef struct {
48  unbound_io_event_base_t *ev_b; //!< Unbound event base
49  rlm_unbound_t *inst; //!< Instance data
50  unbound_log_t *u_log; //!< Unbound log structure
52 
53 typedef struct {
54  int async_id; //!< Id of async query
55  request_t *request; //!< Current request being processed
56  rlm_unbound_thread_t *t; //!< Thread running this request
57  int done; //!< Indicator that the callback has been called
58  ///< Negative values indicate errors.
59  bool timedout; //!< Request timedout.
60  fr_type_t return_type; //!< Data type to parse results into
61  bool has_priority; //!< Does the returned data start with a priority field
62  uint16_t count; //!< Number of results to return
63  fr_value_box_list_t list; //!< Where to put the parsed results
64  TALLOC_CTX *out_ctx; //!< CTX to allocate parsed results in
65  fr_event_timer_t const *ev; //!< Event for timeout
67 
68 /*
69  * A mapping of configuration file names to internal variables.
70  */
71 static const conf_parser_t module_config[] = {
72  { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_unbound_t, filename), .dflt = "${modconfdir}/unbound/default.conf" },
73  { FR_CONF_OFFSET("timeout", rlm_unbound_t, timeout), .dflt = "3000" },
74  { FR_CONF_OFFSET_FLAGS("resolvconf", CONF_FLAG_FILE_INPUT, rlm_unbound_t, resolvconf) },
77 };
78 
80 {
81  /*
82  * Cancel an outstanding async unbound call if the request is being freed
83  */
84  if ((ur->async_id != 0) && (ur->done == 0)) ub_cancel(ur->t->ev_b->ub, ur->async_id);
85 
86  return 0;
87 }
88 
89 /** Callback called by unbound when resolution started with ub_resolve_event() completes
90  *
91  * @param mydata the request tracking structure set up before ub_resolve_event() was called
92  * @param rcode should be the rcode from the reply packet, but appears not to be
93  * @param packet wire format reply packet
94  * @param packet_len length of wire format packet
95  * @param sec DNSSEC status code
96  * @param why_bogus String describing DNSSEC issue if sec = 1
97  * @param rate_limited Was the request rate limited due to unbound workload
98  */
99 static void xlat_unbound_callback(void *mydata, int rcode, void *packet, int packet_len, int sec,
100  char *why_bogus
101 #if UNBOUND_VERSION_MAJOR > 1 || (UNBOUND_VERSION_MAJOR == 1 && UNBOUND_VERSION_MINOR > 7)
102  , UNUSED int rate_limited
103 #endif
104  )
105 
106 {
107  unbound_request_t *ur = talloc_get_type_abort(mydata, unbound_request_t);
108  request_t *request = ur->request;
109  fr_dbuff_t dbuff;
110  uint16_t qdcount = 0, ancount = 0, i, rdlength = 0;
111  uint8_t pktrcode = 0, skip = 0;
112  ssize_t used;
113  fr_value_box_t *vb;
114 
115  /*
116  * Request has completed remove timeout event and set
117  * async_id to 0 so ub_cancel() is not called when ur is freed
118  */
119  if (ur->ev) (void)fr_event_timer_delete(&ur->ev);
120  ur->async_id = 0;
121 
122  /*
123  * Bogus responses have the "sec" flag set to 1
124  */
125  if (sec == 1) {
126  RERROR("%s", why_bogus);
127  ur->done = -16;
128  goto resume;
129  }
130 
131  RHEXDUMP4((uint8_t const *)packet, packet_len, "Unbound callback called with packet [length %d]", packet_len);
132 
133  fr_dbuff_init(&dbuff, (uint8_t const *)packet, (size_t)packet_len);
134 
135  /* Skip initial header entries */
136  fr_dbuff_advance(&dbuff, 3);
137 
138  /*
139  * Extract rcode - it doesn't appear to be passed in as a
140  * parameter, contrary to the documentation...
141  */
142  fr_dbuff_out(&pktrcode, &dbuff);
143  rcode = pktrcode & 0x0f;
144  if (rcode != 0) {
145  ur->done = 0 - rcode;
146  REDEBUG("DNS rcode is %d", rcode);
147  goto resume;
148  }
149 
150  fr_dbuff_out(&qdcount, &dbuff);
151  if (qdcount > 1) {
152  RERROR("DNS results packet with multiple questions");
153  ur->done = -32;
154  goto resume;
155  }
156 
157  /* How many answer records do we have? */
158  fr_dbuff_out(&ancount, &dbuff);
159  RDEBUG4("Unbound returned %d answers", ancount);
160 
161  /* Skip remaining header entries */
162  fr_dbuff_advance(&dbuff, 4);
163 
164  /* Skip the QNAME */
165  fr_dbuff_out(&skip, &dbuff);
166  while (skip > 0) {
167  if (skip > 63) {
168  /*
169  * This is a pointer to somewhere else in the the packet
170  * Pointers use two octets
171  * Just move past the pointer to the next label in the question
172  */
173  fr_dbuff_advance(&dbuff, 1);
174  } else {
175  if (fr_dbuff_remaining(&dbuff) < skip) break;
176  fr_dbuff_advance(&dbuff, skip);
177  }
178  fr_dbuff_out(&skip, &dbuff);
179  }
180 
181  /* Skip QTYPE and QCLASS */
182  fr_dbuff_advance(&dbuff, 4);
183 
184  /* We only want a limited number of replies */
185  if (ancount > ur->count) ancount = ur->count;
186 
187  fr_value_box_list_init(&ur->list);
188 
189  /* Read the answer RRs */
190  for (i = 0; i < ancount; i++) {
191  fr_dbuff_out(&skip, &dbuff);
192  if (skip > 63) fr_dbuff_advance(&dbuff, 1);
193 
194  /* Skip TYPE, CLASS and TTL */
195  fr_dbuff_advance(&dbuff, 8);
196 
197  fr_dbuff_out(&rdlength, &dbuff);
198  RDEBUG4("RDLENGTH is %d", rdlength);
199 
201  switch (ur->return_type) {
202  case FR_TYPE_IPV4_ADDR:
203  case FR_TYPE_IPV6_ADDR:
204  case FR_TYPE_OCTETS:
205  if (fr_value_box_from_network(ur->out_ctx, vb, ur->return_type, NULL,
206  &dbuff, rdlength, true) < 0) {
207  error:
208  talloc_free(vb);
209  fr_value_box_list_talloc_free(&ur->list);
210  ur->done = -32;
211  goto resume;
212  }
213  break;
214 
215  case FR_TYPE_STRING:
216  if (ur->has_priority) {
217  /*
218  * This record type has a priority before the label
219  * add the priority first as a separate box
220  */
221  fr_value_box_t *priority_vb;
222  if (rdlength < 3) {
223  REDEBUG("%s - Invalid data returned", ur->t->inst->name);
224  goto error;
225  }
226  MEM(priority_vb = fr_value_box_alloc_null(ur->out_ctx));
227  if (fr_value_box_from_network(ur->out_ctx, priority_vb, FR_TYPE_UINT16, NULL,
228  &dbuff, 2, true) < 0) {
229  talloc_free(priority_vb);
230  goto error;
231  }
232  fr_value_box_list_insert_tail(&ur->list, priority_vb);
233  }
234 
235  /* String types require decoding of dns format labels */
236  used = fr_dns_label_to_value_box(ur->out_ctx, vb, (uint8_t const *)packet, packet_len,
237  (uint8_t const *)fr_dbuff_current(&dbuff), true, NULL);
238  if (used < 0) goto error;
239  fr_dbuff_advance(&dbuff, (size_t)used);
240  break;
241 
242  default:
243  RERROR("No meaningful output type set");
244  goto error;
245  }
246 
247  fr_value_box_list_insert_tail(&ur->list, vb);
248 
249  }
250 
251  ur->done = 1;
252 
253 resume:
255 }
256 
257 /** Callback from our timeout event to cancel a request
258  *
259  */
261 {
262  unbound_request_t *ur = talloc_get_type_abort(uctx, unbound_request_t);
263  request_t *request = ur->request;
264 
265  REDEBUG("Timeout waiting for DNS resolution");
267 
268  ur->timedout = true;
269 }
270 
271 /*
272  * Xlat signal callback if an unbound request needs cancelling
273  */
274 static void xlat_unbound_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
275 {
276  unbound_request_t *ur = talloc_get_type_abort(xctx->rctx, unbound_request_t);
277 
278  if (ur->ev) (void)fr_event_timer_delete(&ur->ev);
279 
280  RDEBUG2("Forcefully cancelling pending unbound request");
281 }
282 
283 /*
284  * Xlat resume callback after unbound has either returned or timed out
285  * Move the parsed results to the xlat output cursor
286  */
288  xlat_ctx_t const *xctx,
289  request_t *request, UNUSED fr_value_box_list_t *in)
290 {
291  fr_value_box_t *vb;
292  unbound_request_t *ur = talloc_get_type_abort(xctx->rctx, unbound_request_t);
293 
294  /*
295  * Request timed out
296  */
297  if (ur->timedout) return XLAT_ACTION_FAIL;
298 
299 #define RCODEERROR(_code, _message) case _code: \
300  REDEBUG(_message, ur->t->inst->name); \
301  goto error
302 
303  /* Check for unbound errors */
304  switch (ur->done) {
305  case 1:
306  break;
307 
308  default:
309  REDEBUG("%s - Unknown DNS error", ur->t->inst->name);
310  error:
311  talloc_free(ur);
312  return XLAT_ACTION_FAIL;
313 
314  RCODEERROR(0, "%s - No result");
315  RCODEERROR(-1, "%s - Query format error");
316  RCODEERROR(-2, "%s - DNS server failure");
317  RCODEERROR(-3, "%s - Nonexistent domain name");
318  RCODEERROR(-4, "%s - DNS server does not support query type");
319  RCODEERROR(-5, "%s - DNS server refused query");
320  RCODEERROR(-16, "%s - Bogus DNS response");
321  RCODEERROR(-32, "%s - Error parsing DNS response");
322  }
323 
324  /*
325  * Move parsed results into xlat cursor
326  */
327  while ((vb = fr_value_box_list_pop_head(&ur->list))) {
328  fr_dcursor_append(out, vb);
329  }
330 
331  talloc_free(ur);
332  return XLAT_ACTION_DONE;
333 }
334 
335 
337  { .required = true, .concat = true, .type = FR_TYPE_STRING },
338  { .required = true, .concat = true, .type = FR_TYPE_STRING },
339  { .single = true, .type = FR_TYPE_UINT16 },
341 };
342 
343 /** Perform a DNS lookup using libunbound
344  *
345  * @ingroup xlat_functions
346  */
347 static xlat_action_t xlat_unbound(TALLOC_CTX *ctx, fr_dcursor_t *out,
348  xlat_ctx_t const *xctx,
349  request_t *request, fr_value_box_list_t *in)
350 {
352  rlm_unbound_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_unbound_thread_t);
353  fr_value_box_t *host_vb = fr_value_box_list_head(in);
354  fr_value_box_t *query_vb = fr_value_box_list_next(in, host_vb);
355  fr_value_box_t *count_vb = fr_value_box_list_next(in, query_vb);
356  unbound_request_t *ur;
357 
358  if (host_vb->vb_length == 0) {
359  REDEBUG("Can't resolve zero length host");
360  return XLAT_ACTION_FAIL;
361  }
362 
363  MEM(ur = talloc_zero(unlang_interpret_frame_talloc_ctx(request), unbound_request_t));
364  talloc_set_destructor(ur, _unbound_request_free);
365 
366  /*
367  * Set the maximum number of records we want to return
368  */
369  if ((count_vb) && (count_vb->type == FR_TYPE_UINT16) && (count_vb->vb_uint16 > 0)) {
370  ur->count = count_vb->vb_uint16;
371  } else {
372  ur->count = UINT16_MAX;
373  }
374 
375  ur->request = request;
376  ur->t = t;
377  ur->out_ctx = ctx;
378 
379 #define UB_QUERY(_record, _rrvalue, _return, _hasprio) \
380  if (strcmp(query_vb->vb_strvalue, _record) == 0) { \
381  ur->return_type = _return; \
382  ur->has_priority = _hasprio; \
383  ub_resolve_event(t->ev_b->ub, host_vb->vb_strvalue, _rrvalue, 1, ur, \
384  xlat_unbound_callback, &ur->async_id); \
385  }
386 
387  /* coverity[dereference] */
388  UB_QUERY("A", 1, FR_TYPE_IPV4_ADDR, false)
389  else UB_QUERY("AAAA", 28, FR_TYPE_IPV6_ADDR, false)
390  else UB_QUERY("PTR", 12, FR_TYPE_STRING, false)
391  else UB_QUERY("MX", 15, FR_TYPE_STRING, true)
392  else UB_QUERY("SRV", 33, FR_TYPE_STRING, true)
393  else UB_QUERY("TXT", 16, FR_TYPE_STRING, false)
394  else UB_QUERY("CERT", 37, FR_TYPE_OCTETS, false)
395  else {
396  REDEBUG("Invalid / unsupported DNS query type");
397  return XLAT_ACTION_FAIL;
398  }
399 
400  /*
401  * unbound returned before we yielded - run the callback
402  * This is when serving results from local data
403  */
404  if (ur->async_id == 0) {
405  xlat_ctx_t our_xctx = *xctx;
406 
407  our_xctx.rctx = ur; /* Make the rctx available to the resume function */
408 
409  return xlat_unbound_resume(ctx, out, &our_xctx, request, in);
410  }
411 
412  if (fr_event_timer_in(ur, ur->t->ev_b->el, &ur->ev, fr_time_delta_from_msec(inst->timeout),
413  xlat_unbound_timeout, ur) < 0) {
414  REDEBUG("Unable to attach unbound timeout_envent");
415  ub_cancel(t->ev_b->ub, ur->async_id);
416  return XLAT_ACTION_FAIL;
417  }
418 
419  return unlang_xlat_yield(request, xlat_unbound_resume, xlat_unbound_signal, ~FR_SIGNAL_CANCEL, ur);
420 }
421 
423 {
424  rlm_unbound_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_unbound_t);
425  rlm_unbound_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_unbound_thread_t);
426  int res;
427 
428  t->inst = inst;
429  if (unbound_io_init(t, &t->ev_b, mctx->el) < 0) {
430  PERROR("Unable to create unbound event base");
431  return -1;
432  }
433 
434  /*
435  * Ensure unbound uses threads
436  */
437  res = ub_ctx_async(t->ev_b->ub, 1);
438  if (res) {
439  error:
440  PERROR("%s", ub_strerror(res));
441  free_error:
442  talloc_free(t->ev_b);
443  return -1;
444  }
445 
446  /*
447  * Load settings from the unbound config file
448  */
449  res = ub_ctx_config(t->ev_b->ub, UNCONST(char *, inst->filename));
450  if (res) goto error;
451 
452  if (unbound_log_init(t, &t->u_log, t->ev_b->ub) < 0) {
453  PERROR("Failed to initialise unbound log");
454  goto free_error;
455  }
456 
457  /*
458  * Load resolv.conf if specified
459  */
460  if (inst->resolvconf) ub_ctx_resolvconf(t->ev_b->ub, inst->resolvconf);
461 
462  /*
463  * Load hosts file if specified
464  */
465  if (inst->hosts) ub_ctx_hosts(t->ev_b->ub, inst->hosts);
466 
467  /*
468  * The unbound context needs to be "finalised" to fix its settings.
469  * The API does not expose a method to do this, rather it happens on first
470  * use. A quick workaround is to delete data which won't be present
471  */
472  ub_ctx_data_remove(t->ev_b->ub, "notar33lsite.foo123.nottld A 127.0.0.1");
473 
474  return 0;
475 }
476 
478 {
479  rlm_unbound_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_unbound_thread_t);
480 
481  talloc_free(t->u_log);
482  talloc_free(t->ev_b);
483 
484  return 0;
485 }
486 
487 static int mod_bootstrap(module_inst_ctx_t const *mctx)
488 {
489  rlm_unbound_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_unbound_t);
490  xlat_t *xlat;
491 
492  inst->name = mctx->inst->name;
493 
494  if (inst->timeout > 10000) {
495  cf_log_err(mctx->inst->conf, "timeout must be 0 to 10000");
496  return -1;
497  }
498 
499  if(!(xlat = xlat_func_register_module(NULL, mctx, NULL, xlat_unbound, FR_TYPE_VOID))) return -1;
501 
502  return 0;
503 }
504 
507  .common = {
508  .magic = MODULE_MAGIC_INIT,
509  .name = "unbound",
510  .flags = MODULE_TYPE_THREAD_SAFE,
511  .inst_size = sizeof(rlm_unbound_t),
513  .bootstrap = mod_bootstrap,
514 
515  .thread_inst_size = sizeof(rlm_unbound_thread_t),
516  .thread_inst_type = "rlm_unbound_thread_t",
517  .thread_instantiate = mod_thread_instantiate,
518  .thread_detach = mod_thread_detach
519  }
520 };
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:268
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition: cf_parse.h:256
@ CONF_FLAG_FILE_INPUT
File matching value must exist, and must be readable.
Definition: cf_parse.h:412
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define fr_dbuff_advance(_dbuff_or_marker, _len)
Advance 'current' position in dbuff or marker by _len bytes.
Definition: dbuff.h:1067
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition: dbuff.h:906
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition: dbuff.h:738
#define fr_dbuff_out(_out, _dbuff_or_marker)
Copy data from a dbuff or marker to a fixed sized C type.
Definition: dbuff.h:1779
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
static fr_slen_t in
Definition: dict.h:645
char const *_CONST name
Instance name.
Definition: dl_module.h:163
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
CONF_SECTION *_CONST conf
Module's instance configuration.
Definition: dl_module.h:166
ssize_t fr_dns_label_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, uint8_t const *label, bool tainted, fr_dns_labels_t *lb)
Decode a fr_value_box_t from one DNS label.
Definition: dns.c:1225
#define fr_event_timer_in(...)
Definition: event.h:255
static xlat_action_t xlat_unbound(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Perform a DNS lookup using libunbound.
Definition: rlm_unbound.c:347
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
Definition: interpret.c:1340
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition: interpret.c:1384
#define PERROR(_fmt,...)
Definition: log.h:228
#define RHEXDUMP4(_data, _len, _fmt,...)
Definition: log.h:706
#define RERROR(fmt,...)
Definition: log.h:298
#define RDEBUG4(fmt,...)
Definition: log.h:344
talloc_free(reap)
int fr_event_timer_delete(fr_event_timer_t const **ev_p)
Delete a timer event from the event list.
Definition: event.c:1604
Stores all information relating to an event list.
Definition: event.c:411
A timer event.
Definition: event.c:102
unsigned short uint16_t
Definition: merged_model.c:31
fr_type_t
Definition: merged_model.c:80
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
static size_t used
void * thread
Thread specific instance data.
Definition: module_ctx.h:43
fr_event_list_t * el
Event list to register any IO handlers and timers against.
Definition: module_ctx.h:63
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
void * thread
Thread instance data.
Definition: module_ctx.h:62
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:59
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:58
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
int unbound_io_init(TALLOC_CTX *ctx, unbound_io_event_base_t **ev_b_out, fr_event_list_t *el)
Alloc a new event base, and unbound ctx initialised from that event base.
Definition: io.c:482
Function prototypes and datatypes for the REST (HTTP) transport.
struct ub_ctx * ub
Unbound ctx instantiated from this event base.
Definition: io.h:51
fr_event_list_t * el
Event loop events should be inserted into.
Definition: io.h:53
Wrapper around our event loop specifying callbacks for creating new event handles.
Definition: io.h:48
int unbound_log_init(TALLOC_CTX *ctx, unbound_log_t **u_log_out, struct ub_ctx *ub)
Setup an unbound context for log, and initialise a u_log struct.
Definition: log.c:129
Function prototypes and datatypes for the REST (HTTP) transport.
Logging state.
Definition: log.h:44
static const conf_parser_t config[]
Definition: base.c:188
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
int async_id
Id of async query.
Definition: rlm_unbound.c:54
uint16_t count
Number of results to return.
Definition: rlm_unbound.c:62
static xlat_arg_parser_t const xlat_unbound_args[]
Definition: rlm_unbound.c:336
static void xlat_unbound_callback(void *mydata, int rcode, void *packet, int packet_len, int sec, char *why_bogus)
Callback called by unbound when resolution started with ub_resolve_event() completes.
Definition: rlm_unbound.c:99
#define RCODEERROR(_code, _message)
fr_value_box_list_t list
Where to put the parsed results.
Definition: rlm_unbound.c:63
TALLOC_CTX * out_ctx
CTX to allocate parsed results in.
Definition: rlm_unbound.c:64
int done
Indicator that the callback has been called Negative values indicate errors.
Definition: rlm_unbound.c:57
bool timedout
Request timedout.
Definition: rlm_unbound.c:59
char const * name
Definition: rlm_unbound.c:39
static int _unbound_request_free(unbound_request_t *ur)
Definition: rlm_unbound.c:79
char const * filename
Unbound configuration file.
Definition: rlm_unbound.c:42
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:487
#define UB_QUERY(_record, _rrvalue, _return, _hasprio)
fr_event_timer_t const * ev
Event for timeout.
Definition: rlm_unbound.c:65
bool has_priority
Does the returned data start with a priority field.
Definition: rlm_unbound.c:61
rlm_unbound_t * inst
Instance data.
Definition: rlm_unbound.c:49
static void xlat_unbound_timeout(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Callback from our timeout event to cancel a request.
Definition: rlm_unbound.c:260
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:422
fr_type_t return_type
Data type to parse results into.
Definition: rlm_unbound.c:60
unbound_io_event_base_t * ev_b
Unbound event base.
Definition: rlm_unbound.c:48
static xlat_action_t xlat_unbound_resume(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Definition: rlm_unbound.c:287
static void xlat_unbound_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
Definition: rlm_unbound.c:274
char const * hosts
hosts file to load
Definition: rlm_unbound.c:44
request_t * request
Current request being processed.
Definition: rlm_unbound.c:55
static const conf_parser_t module_config[]
Definition: rlm_unbound.c:71
rlm_unbound_thread_t * t
Thread running this request.
Definition: rlm_unbound.c:56
char const * resolvconf
resolv.conf file to use
Definition: rlm_unbound.c:43
module_rlm_t rlm_unbound
Definition: rlm_unbound.c:506
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:477
unbound_log_t * u_log
Unbound log structure.
Definition: rlm_unbound.c:50
uint32_t timeout
Definition: rlm_unbound.c:40
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
Definition: module.h:49
fr_signal_t
Definition: signal.h:48
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
#define talloc_get_type_abort_const
Definition: talloc.h:270
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition: time.h:573
"server local" time.
Definition: time.h:69
static fr_event_list_t * el
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition: xlat.c:561
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition: value.c:1709
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition: value.h:619
static size_t char ** out
Definition: value.h:984
void * rctx
Resume context.
Definition: xlat_ctx.h:47
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition: xlat_ctx.h:45
An xlat calling ctx.
Definition: xlat_ctx.h:42
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition: xlat_func.c:360
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.
Definition: xlat_func.c:274