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: 14a4371bf4a4ef91a23980d43956188a8af52813 $
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: 14a4371bf4a4ef91a23980d43956188a8af52813 $")
26 
27 #define LOG_PREFIX mctx->mi->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 {
40 
41  char const *filename; //!< Unbound configuration file
42  char const *resolvconf; //!< resolv.conf file to use
43  char const *hosts; //!< hosts file to load
45 
46 typedef struct {
47  unbound_io_event_base_t *ev_b; //!< Unbound event base
48  rlm_unbound_t *inst; //!< Instance data
49  unbound_log_t *u_log; //!< Unbound log structure
51 
52 typedef struct {
53  int async_id; //!< Id of async query
54  request_t *request; //!< Current request being processed
55  rlm_unbound_thread_t *t; //!< Thread running this request
56  int done; //!< Indicator that the callback has been called
57  ///< Negative values indicate errors.
58  bool timedout; //!< Request timedout.
59  fr_type_t return_type; //!< Data type to parse results into
60  bool has_priority; //!< Does the returned data start with a priority field
61  uint16_t count; //!< Number of results to return
62  fr_value_box_list_t list; //!< Where to put the parsed results
63  TALLOC_CTX *out_ctx; //!< CTX to allocate parsed results in
64  fr_event_timer_t const *ev; //!< Event for timeout
66 
67 /*
68  * A mapping of configuration file names to internal variables.
69  */
70 static const conf_parser_t module_config[] = {
71  { FR_CONF_OFFSET_FLAGS("filename", CONF_FLAG_FILE_INPUT, rlm_unbound_t, filename), .dflt = "${modconfdir}/unbound/default.conf" },
72  { FR_CONF_OFFSET("timeout", rlm_unbound_t, timeout), .dflt = "3000" },
73  { FR_CONF_OFFSET_FLAGS("resolvconf", CONF_FLAG_FILE_INPUT, rlm_unbound_t, resolvconf) },
76 };
77 
79 {
80  /*
81  * Cancel an outstanding async unbound call if the request is being freed
82  */
83  if ((ur->async_id != 0) && (ur->done == 0)) ub_cancel(ur->t->ev_b->ub, ur->async_id);
84 
85  return 0;
86 }
87 
88 /** Callback called by unbound when resolution started with ub_resolve_event() completes
89  *
90  * @param mydata the request tracking structure set up before ub_resolve_event() was called
91  * @param rcode should be the rcode from the reply packet, but appears not to be
92  * @param packet wire format reply packet
93  * @param packet_len length of wire format packet
94  * @param sec DNSSEC status code
95  * @param why_bogus String describing DNSSEC issue if sec = 1
96  * @param rate_limited Was the request rate limited due to unbound workload
97  */
98 static void xlat_unbound_callback(void *mydata, int rcode, void *packet, int packet_len, int sec,
99  char *why_bogus
100 #if UNBOUND_VERSION_MAJOR > 1 || (UNBOUND_VERSION_MAJOR == 1 && UNBOUND_VERSION_MINOR > 7)
101  , UNUSED int rate_limited
102 #endif
103  )
104 
105 {
106  unbound_request_t *ur = talloc_get_type_abort(mydata, unbound_request_t);
107  request_t *request = ur->request;
108  fr_dbuff_t dbuff;
109  uint16_t qdcount = 0, ancount = 0, i, rdlength = 0;
110  uint8_t pktrcode = 0, skip = 0;
111  ssize_t used;
112  fr_value_box_t *vb;
113 
114  /*
115  * Request has completed remove timeout event and set
116  * async_id to 0 so ub_cancel() is not called when ur is freed
117  */
118  if (ur->ev) (void)fr_event_timer_delete(&ur->ev);
119  ur->async_id = 0;
120 
121  /*
122  * Bogus responses have the "sec" flag set to 1
123  */
124  if (sec == 1) {
125  RERROR("%s", why_bogus);
126  ur->done = -16;
127  goto resume;
128  }
129 
130  RHEXDUMP4((uint8_t const *)packet, packet_len, "Unbound callback called with packet [length %d]", packet_len);
131 
132  fr_dbuff_init(&dbuff, (uint8_t const *)packet, (size_t)packet_len);
133 
134  /* Skip initial header entries */
135  fr_dbuff_advance(&dbuff, 3);
136 
137  /*
138  * Extract rcode - it doesn't appear to be passed in as a
139  * parameter, contrary to the documentation...
140  */
141  fr_dbuff_out(&pktrcode, &dbuff);
142  rcode = pktrcode & 0x0f;
143  if (rcode != 0) {
144  ur->done = 0 - rcode;
145  REDEBUG("DNS rcode is %d", rcode);
146  goto resume;
147  }
148 
149  fr_dbuff_out(&qdcount, &dbuff);
150  if (qdcount > 1) {
151  RERROR("DNS results packet with multiple questions");
152  ur->done = -32;
153  goto resume;
154  }
155 
156  /* How many answer records do we have? */
157  fr_dbuff_out(&ancount, &dbuff);
158  RDEBUG4("Unbound returned %d answers", ancount);
159 
160  /* Skip remaining header entries */
161  fr_dbuff_advance(&dbuff, 4);
162 
163  /* Skip the QNAME */
164  fr_dbuff_out(&skip, &dbuff);
165  while (skip > 0) {
166  if (skip > 63) {
167  /*
168  * This is a pointer to somewhere else in the the packet
169  * Pointers use two octets
170  * Just move past the pointer to the next label in the question
171  */
172  fr_dbuff_advance(&dbuff, 1);
173  } else {
174  if (fr_dbuff_remaining(&dbuff) < skip) break;
175  fr_dbuff_advance(&dbuff, skip);
176  }
177  fr_dbuff_out(&skip, &dbuff);
178  }
179 
180  /* Skip QTYPE and QCLASS */
181  fr_dbuff_advance(&dbuff, 4);
182 
183  /* We only want a limited number of replies */
184  if (ancount > ur->count) ancount = ur->count;
185 
186  fr_value_box_list_init(&ur->list);
187 
188  /* Read the answer RRs */
189  for (i = 0; i < ancount; i++) {
190  fr_dbuff_out(&skip, &dbuff);
191  if (skip > 63) fr_dbuff_advance(&dbuff, 1);
192 
193  /* Skip TYPE, CLASS and TTL */
194  fr_dbuff_advance(&dbuff, 8);
195 
196  fr_dbuff_out(&rdlength, &dbuff);
197  RDEBUG4("RDLENGTH is %d", rdlength);
198 
200  switch (ur->return_type) {
201  case FR_TYPE_IPV4_ADDR:
202  case FR_TYPE_IPV6_ADDR:
203  case FR_TYPE_OCTETS:
204  if (fr_value_box_from_network(ur->out_ctx, vb, ur->return_type, NULL,
205  &dbuff, rdlength, true) < 0) {
206  error:
207  talloc_free(vb);
208  fr_value_box_list_talloc_free(&ur->list);
209  ur->done = -32;
210  goto resume;
211  }
212  break;
213 
214  case FR_TYPE_STRING:
215  if (ur->has_priority) {
216  /*
217  * This record type has a priority before the label
218  * add the priority first as a separate box
219  */
220  fr_value_box_t *priority_vb;
221  if (rdlength < 3) {
222  REDEBUG("Invalid data returned");
223  goto error;
224  }
225  MEM(priority_vb = fr_value_box_alloc_null(ur->out_ctx));
226  if (fr_value_box_from_network(ur->out_ctx, priority_vb, FR_TYPE_UINT16, NULL,
227  &dbuff, 2, true) < 0) {
228  talloc_free(priority_vb);
229  goto error;
230  }
231  fr_value_box_list_insert_tail(&ur->list, priority_vb);
232  }
233 
234  /* String types require decoding of dns format labels */
235  used = fr_dns_label_to_value_box(ur->out_ctx, vb, (uint8_t const *)packet, packet_len,
236  (uint8_t const *)fr_dbuff_current(&dbuff), true, NULL);
237  if (used < 0) goto error;
238  fr_dbuff_advance(&dbuff, (size_t)used);
239  break;
240 
241  default:
242  RERROR("No meaningful output type set");
243  goto error;
244  }
245 
246  fr_value_box_list_insert_tail(&ur->list, vb);
247 
248  }
249 
250  ur->done = 1;
251 
252 resume:
254 }
255 
256 /** Callback from our timeout event to cancel a request
257  *
258  */
260 {
261  unbound_request_t *ur = talloc_get_type_abort(uctx, unbound_request_t);
262  request_t *request = ur->request;
263 
264  REDEBUG("Timeout waiting for DNS resolution");
266 
267  ur->timedout = true;
268 }
269 
270 /*
271  * Xlat signal callback if an unbound request needs cancelling
272  */
273 static void xlat_unbound_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
274 {
275  unbound_request_t *ur = talloc_get_type_abort(xctx->rctx, unbound_request_t);
276 
277  if (ur->ev) (void)fr_event_timer_delete(&ur->ev);
278 
279  RDEBUG2("Forcefully cancelling pending unbound request");
280 }
281 
282 /*
283  * Xlat resume callback after unbound has either returned or timed out
284  * Move the parsed results to the xlat output cursor
285  */
287  xlat_ctx_t const *xctx,
288  request_t *request, UNUSED fr_value_box_list_t *in)
289 {
290  fr_value_box_t *vb;
291  unbound_request_t *ur = talloc_get_type_abort(xctx->rctx, unbound_request_t);
292 
293  /*
294  * Request timed out
295  */
296  if (ur->timedout) return XLAT_ACTION_FAIL;
297 
298 #define RCODEERROR(_code, _message) case _code: \
299  REDEBUG(_message, xctx->mctx->mi->name); \
300  goto error
301 
302  /* Check for unbound errors */
303  switch (ur->done) {
304  case 1:
305  break;
306 
307  default:
308  REDEBUG("Unknown DNS error");
309  error:
310  talloc_free(ur);
311  return XLAT_ACTION_FAIL;
312 
313  RCODEERROR(0, "%s - No result");
314  RCODEERROR(-1, "%s - Query format error");
315  RCODEERROR(-2, "%s - DNS server failure");
316  RCODEERROR(-3, "%s - Nonexistent domain name");
317  RCODEERROR(-4, "%s - DNS server does not support query type");
318  RCODEERROR(-5, "%s - DNS server refused query");
319  RCODEERROR(-16, "%s - Bogus DNS response");
320  RCODEERROR(-32, "%s - Error parsing DNS response");
321  }
322 
323  /*
324  * Move parsed results into xlat cursor
325  */
326  while ((vb = fr_value_box_list_pop_head(&ur->list))) {
327  fr_dcursor_append(out, vb);
328  }
329 
330  talloc_free(ur);
331  return XLAT_ACTION_DONE;
332 }
333 
334 
336  { .required = true, .concat = true, .type = FR_TYPE_STRING },
337  { .required = true, .concat = true, .type = FR_TYPE_STRING },
338  { .single = true, .type = FR_TYPE_UINT16 },
340 };
341 
342 /** Perform a DNS lookup using libunbound
343  *
344  * @ingroup xlat_functions
345  */
346 static xlat_action_t xlat_unbound(TALLOC_CTX *ctx, fr_dcursor_t *out,
347  xlat_ctx_t const *xctx,
348  request_t *request, fr_value_box_list_t *in)
349 {
351  rlm_unbound_thread_t *t = talloc_get_type_abort(xctx->mctx->thread, rlm_unbound_thread_t);
352  fr_value_box_t *host_vb = fr_value_box_list_head(in);
353  fr_value_box_t *query_vb = fr_value_box_list_next(in, host_vb);
354  fr_value_box_t *count_vb = fr_value_box_list_next(in, query_vb);
355  unbound_request_t *ur;
356 
357  if (host_vb->vb_length == 0) {
358  REDEBUG("Can't resolve zero length host");
359  return XLAT_ACTION_FAIL;
360  }
361 
362  MEM(ur = talloc_zero(unlang_interpret_frame_talloc_ctx(request), unbound_request_t));
363  talloc_set_destructor(ur, _unbound_request_free);
364 
365  /*
366  * Set the maximum number of records we want to return
367  */
368  if ((count_vb) && (count_vb->type == FR_TYPE_UINT16) && (count_vb->vb_uint16 > 0)) {
369  ur->count = count_vb->vb_uint16;
370  } else {
371  ur->count = UINT16_MAX;
372  }
373 
374  ur->request = request;
375  ur->t = t;
376  ur->out_ctx = ctx;
377 
378 #define UB_QUERY(_record, _rrvalue, _return, _hasprio) \
379  if (strcmp(query_vb->vb_strvalue, _record) == 0) { \
380  ur->return_type = _return; \
381  ur->has_priority = _hasprio; \
382  ub_resolve_event(t->ev_b->ub, host_vb->vb_strvalue, _rrvalue, 1, ur, \
383  xlat_unbound_callback, &ur->async_id); \
384  }
385 
386  /* coverity[dereference] */
387  UB_QUERY("A", 1, FR_TYPE_IPV4_ADDR, false)
388  else UB_QUERY("AAAA", 28, FR_TYPE_IPV6_ADDR, false)
389  else UB_QUERY("PTR", 12, FR_TYPE_STRING, false)
390  else UB_QUERY("MX", 15, FR_TYPE_STRING, true)
391  else UB_QUERY("SRV", 33, FR_TYPE_STRING, true)
392  else UB_QUERY("TXT", 16, FR_TYPE_STRING, false)
393  else UB_QUERY("CERT", 37, FR_TYPE_OCTETS, false)
394  else {
395  REDEBUG("Invalid / unsupported DNS query type");
396  return XLAT_ACTION_FAIL;
397  }
398 
399  /*
400  * unbound returned before we yielded - run the callback
401  * This is when serving results from local data
402  */
403  if (ur->async_id == 0) {
404  xlat_ctx_t our_xctx = *xctx;
405 
406  our_xctx.rctx = ur; /* Make the rctx available to the resume function */
407 
408  return xlat_unbound_resume(ctx, out, &our_xctx, request, in);
409  }
410 
411  if (fr_event_timer_in(ur, ur->t->ev_b->el, &ur->ev, fr_time_delta_from_msec(inst->timeout),
412  xlat_unbound_timeout, ur) < 0) {
413  REDEBUG("Unable to attach unbound timeout_envent");
414  ub_cancel(t->ev_b->ub, ur->async_id);
415  return XLAT_ACTION_FAIL;
416  }
417 
418  return unlang_xlat_yield(request, xlat_unbound_resume, xlat_unbound_signal, ~FR_SIGNAL_CANCEL, ur);
419 }
420 
422 {
423  rlm_unbound_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_unbound_t);
424  rlm_unbound_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_unbound_thread_t);
425  int res;
426 
427  t->inst = inst;
428  if (unbound_io_init(t, &t->ev_b, mctx->el) < 0) {
429  PERROR("Unable to create unbound event base");
430  return -1;
431  }
432 
433  /*
434  * Ensure unbound uses threads
435  */
436  res = ub_ctx_async(t->ev_b->ub, 1);
437  if (res) {
438  error:
439  PERROR("%s", ub_strerror(res));
440  free_error:
441  talloc_free(t->ev_b);
442  return -1;
443  }
444 
445  /*
446  * Load settings from the unbound config file
447  */
448  res = ub_ctx_config(t->ev_b->ub, UNCONST(char *, inst->filename));
449  if (res) goto error;
450 
451  if (unbound_log_init(t, &t->u_log, t->ev_b->ub) < 0) {
452  PERROR("Failed to initialise unbound log");
453  goto free_error;
454  }
455 
456  /*
457  * Load resolv.conf if specified
458  */
459  if (inst->resolvconf) ub_ctx_resolvconf(t->ev_b->ub, inst->resolvconf);
460 
461  /*
462  * Load hosts file if specified
463  */
464  if (inst->hosts) ub_ctx_hosts(t->ev_b->ub, inst->hosts);
465 
466  /*
467  * The unbound context needs to be "finalised" to fix its settings.
468  * The API does not expose a method to do this, rather it happens on first
469  * use. A quick workaround is to delete data which won't be present
470  */
471  ub_ctx_data_remove(t->ev_b->ub, "notar33lsite.foo123.nottld A 127.0.0.1");
472 
473  return 0;
474 }
475 
477 {
478  rlm_unbound_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_unbound_thread_t);
479 
480  talloc_free(t->u_log);
481  talloc_free(t->ev_b);
482 
483  return 0;
484 }
485 
486 static int mod_bootstrap(module_inst_ctx_t const *mctx)
487 {
488  rlm_unbound_t const *inst = talloc_get_type_abort(mctx->mi->data, rlm_unbound_t);
489  xlat_t *xlat;
490 
491  if (inst->timeout > 10000) {
492  cf_log_err(mctx->mi->conf, "timeout must be 0 to 10000");
493  return -1;
494  }
495 
496  if(!(xlat = module_rlm_xlat_register(mctx->mi->boot, mctx, NULL, xlat_unbound, FR_TYPE_VOID))) return -1;
498 
499  return 0;
500 }
501 
504  .common = {
505  .magic = MODULE_MAGIC_INIT,
506  .name = "unbound",
507  .inst_size = sizeof(rlm_unbound_t),
509  .bootstrap = mod_bootstrap,
510 
511  .thread_inst_size = sizeof(rlm_unbound_thread_t),
512  .thread_inst_type = "rlm_unbound_thread_t",
513  .thread_instantiate = mod_thread_instantiate,
514  .thread_detach = mod_thread_detach
515  }
516 };
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define RCSID(id)
Definition: build.h:446
#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:289
#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
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
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:346
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
Definition: interpret.c:1359
TALLOC_CTX * unlang_interpret_frame_talloc_ctx(request_t *request)
Get a talloc_ctx which is valid only for this frame.
Definition: interpret.c:1403
#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
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:42
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:68
void * thread
Thread instance data.
Definition: module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition: module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition: module_ctx.h:51
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition: module_ctx.h:63
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Definition: module_rlm.c:257
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
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:53
uint16_t count
Number of results to return.
Definition: rlm_unbound.c:61
static xlat_arg_parser_t const xlat_unbound_args[]
Definition: rlm_unbound.c:335
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:98
#define RCODEERROR(_code, _message)
fr_value_box_list_t list
Where to put the parsed results.
Definition: rlm_unbound.c:62
TALLOC_CTX * out_ctx
CTX to allocate parsed results in.
Definition: rlm_unbound.c:63
int done
Indicator that the callback has been called Negative values indicate errors.
Definition: rlm_unbound.c:56
bool timedout
Request timedout.
Definition: rlm_unbound.c:58
static int _unbound_request_free(unbound_request_t *ur)
Definition: rlm_unbound.c:78
char const * filename
Unbound configuration file.
Definition: rlm_unbound.c:41
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:486
#define UB_QUERY(_record, _rrvalue, _return, _hasprio)
fr_event_timer_t const * ev
Event for timeout.
Definition: rlm_unbound.c:64
bool has_priority
Does the returned data start with a priority field.
Definition: rlm_unbound.c:60
rlm_unbound_t * inst
Instance data.
Definition: rlm_unbound.c:48
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:259
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:421
fr_type_t return_type
Data type to parse results into.
Definition: rlm_unbound.c:59
unbound_io_event_base_t * ev_b
Unbound event base.
Definition: rlm_unbound.c:47
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:286
static void xlat_unbound_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
Definition: rlm_unbound.c:273
char const * hosts
hosts file to load
Definition: rlm_unbound.c:43
request_t * request
Current request being processed.
Definition: rlm_unbound.c:54
static const conf_parser_t module_config[]
Definition: rlm_unbound.c:70
rlm_unbound_thread_t * t
Thread running this request.
Definition: rlm_unbound.c:55
char const * resolvconf
resolv.conf file to use
Definition: rlm_unbound.c:42
module_rlm_t rlm_unbound
Definition: rlm_unbound.c:503
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Definition: rlm_unbound.c:476
unbound_log_t * u_log
Unbound log structure.
Definition: rlm_unbound.c:49
uint32_t timeout
Definition: rlm_unbound.c:39
CONF_SECTION * conf
Module's instance configuration.
Definition: module.h:329
void * data
Module's instance data.
Definition: module.h:271
void * boot
Data allocated during the boostrap phase.
Definition: module.h:274
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:271
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition: time.h:575
"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:145
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:165
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:144
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:54
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition: xlat_ctx.h:52
An xlat calling ctx.
Definition: xlat_ctx.h:49
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition: xlat_func.c:365