The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
proto_detail.c
Go to the documentation of this file.
1 /*
2  * This program 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
5  * (at 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: 35600925791b9762b8468c22bf7c595ec1afebd0 $
19  * @file proto_detail.c
20  * @brief Detail master protocol handler.
21  *
22  * @copyright 2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  * @copyright 2016 Alan DeKok (aland@freeradius.org)
24  */
25 #include <freeradius-devel/io/application.h>
26 #include <freeradius-devel/io/listen.h>
27 #include <freeradius-devel/io/schedule.h>
28 #include <freeradius-devel/radius/radius.h>
29 #include <freeradius-devel/util/pair_legacy.h>
30 
31 #include "proto_detail.h"
32 
33 extern fr_app_t proto_detail;
34 static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
35 static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
36 
37 #if 0
38 /*
39  * When we want detailed debugging here, without detailed server
40  * debugging.
41  */
42 #define MPRINT DEBUG
43 #else
44 #define MPRINT(x, ...)
45 #endif
46 
47 /** How to parse a Detail listen section
48  *
49  */
52  type), .func = type_parse },
53  { FR_CONF_OFFSET_TYPE_FLAGS("transport", FR_TYPE_VOID, 0, proto_detail_t, io_submodule),
54  .func = transport_parse, .dflt = "file" },
55 
56  /*
57  * Add this as a synonym so normal humans can understand it.
58  */
59  { FR_CONF_OFFSET("max_entry_size", proto_detail_t, max_packet_size) } ,
60 
61  /*
62  * For performance tweaking. NOT for normal humans.
63  */
64  { FR_CONF_OFFSET("max_packet_size", proto_detail_t, max_packet_size) } ,
65  { FR_CONF_OFFSET("num_messages", proto_detail_t, num_messages) } ,
66 
67  { FR_CONF_OFFSET("exit_when_done", proto_detail_t, exit_when_done) },
68 
69  { FR_CONF_OFFSET("priority", proto_detail_t, priority) },
70 
72 };
73 
74 static fr_dict_t const *dict_freeradius;
75 
78  { .out = &dict_freeradius, .proto = "freeradius" },
79 
80  { NULL }
81 };
82 
89 
92  { .out = &attr_packet_dst_ip_address, .name = "Net.Dst.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
93  { .out = &attr_packet_dst_port, .name = "Net.Dst.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
94  { .out = &attr_packet_original_timestamp, .name = "Packet-Original-Timestamp", .type = FR_TYPE_DATE, .dict = &dict_freeradius },
95  { .out = &attr_packet_src_ip_address, .name = "Net.Src.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
96  { .out = &attr_packet_src_port, .name = "Net.Src.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
97  { .out = &attr_protocol, .name = "Protocol", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
98 
99  { NULL }
100 };
101 
102 /** Wrapper around dl_instance which translates the packet-type into a submodule name
103  *
104  * @param[in] ctx to allocate data in (instance of proto_detail).
105  * @param[out] out Where to write a dl_module_inst_t containing the module handle and instance.
106  * @param[in] parent Base structure address.
107  * @param[in] ci #CONF_PAIR specifying the name of the type module.
108  * @param[in] rule unused.
109  * @return
110  * - 0 on success.
111  * - -1 on failure.
112  */
113 static int type_parse(UNUSED TALLOC_CTX *ctx, void *out, void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
114 {
115  proto_detail_t *inst = talloc_get_type_abort(parent, proto_detail_t);
116  fr_dict_enum_value_t const *type_enum;
117  CONF_PAIR *cp = cf_item_to_pair(ci);
118  char const *value = cf_pair_value(cp);
119 
120  *((char const **) out) = value;
121 
123  if (!inst->dict) {
124  cf_log_err(ci, "Please define 'namespace' in this virtual server");
125  return -1;
126  }
127 
128  inst->attr_packet_type = fr_dict_attr_by_name(NULL, fr_dict_root(inst->dict), "Packet-Type");
129  if (!inst->attr_packet_type) {
130  cf_log_err(ci, "Failed to find 'Packet-Type' attribute");
131  return -1;
132  }
133 
134  if (!value) {
135  cf_log_err(ci, "No value given for 'type'");
136  return -1;
137  }
138 
139  type_enum = fr_dict_enum_by_name(inst->attr_packet_type, value, -1);
140  if (!type_enum) {
141  cf_log_err(ci, "Invalid type \"%s\"", value);
142  return -1;
143  }
144 
145  inst->code = type_enum->value->vb_uint32;
146  return 0;
147 }
148 
149 /** Wrapper around dl_instance
150  *
151  * @param[in] ctx to allocate data in (instance of proto_detail).
152  * @param[out] out Where to write a dl_module_inst_t containing the module handle and instance.
153  * @param[in] parent Base structure address.
154  * @param[in] ci #CONF_PAIR specifying the name of the type module.
155  * @param[in] rule unused.
156  * @return
157  * - 0 on success.
158  * - -1 on failure.
159  */
160 static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
161  CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
162 {
163  char const *name = cf_pair_value(cf_item_to_pair(ci));
164  dl_module_inst_t *parent_inst;
165  CONF_SECTION *listen_cs = cf_item_to_section(cf_parent(ci));
166  CONF_SECTION *transport_cs;
167  dl_module_inst_t *dl_mod_inst;
168 
169  transport_cs = cf_section_find(listen_cs, name, NULL);
170 
171  /*
172  * Allocate an empty section if one doesn't exist
173  * this is so defaults get parsed.
174  */
175  if (!transport_cs) transport_cs = cf_section_alloc(listen_cs, listen_cs, name, NULL);
176 
177  parent_inst = cf_data_value(cf_data_find(listen_cs, dl_module_inst_t, "proto_detail"));
178  fr_assert(parent_inst);
179 
180  if (dl_module_instance(ctx, &dl_mod_inst, parent_inst,
181  DL_MODULE_TYPE_SUBMODULE, name, dl_module_inst_name_from_conf(transport_cs)) < 0) return -1;
182  if (dl_module_conf_parse(dl_mod_inst, transport_cs) < 0) {
183  talloc_free(dl_mod_inst);
184  return -1;
185  }
186  *((dl_module_inst_t **)out) = dl_mod_inst;
187 
188  return 0;
189 }
190 
191 /** Decode the packet, and set the request->process function
192  *
193  */
194 static int mod_decode(void const *instance, request_t *request, uint8_t *const data, size_t data_len)
195 {
197  int num, lineno;
198  uint8_t const *p, *end;
199  fr_pair_t *vp;
200  fr_pair_list_t tmp_list;
201  fr_dcursor_t cursor;
202  time_t timestamp = 0;
203  fr_pair_parse_t root, relative;
204 
205  RHEXDUMP3(data, data_len, "proto_detail decode packet");
206 
207  request->dict = inst->dict;
208  request->packet->code = inst->code;
209 
210  /*
211  * Set default addresses
212  */
213  request->packet->socket.fd = -1;
214  request->packet->socket.inet.src_ipaddr.af = AF_INET;
215  request->packet->socket.inet.src_ipaddr.addr.v4.s_addr = htonl(INADDR_NONE);
216  request->packet->socket.inet.dst_ipaddr = request->packet->socket.inet.src_ipaddr;
217 
218  request->reply->socket.inet.src_ipaddr = request->packet->socket.inet.src_ipaddr;
219  request->reply->socket.inet.dst_ipaddr = request->packet->socket.inet.src_ipaddr;
220 
221  end = data + data_len;
222 
223  MPRINT("HEADER %s", data);
224 
225  if (sscanf((char const *) data, "%*s %*s %*d %*d:%*d:%*d %d", &num) != 1) {
226  REDEBUG("Malformed header '%s'", (char const *) data);
227  return -1;
228  }
229 
230  /*
231  * Skip the header
232  */
233  for (p = data; p < end; p++) {
234  if (!*p) break;
235  }
236 
237  lineno = 1;
238  fr_pair_dcursor_init(&cursor, &request->request_pairs);
239  fr_dcursor_tail(&cursor); /* Ensure we only free what we add on error */
240  fr_pair_list_init(&tmp_list);
241 
242  /*
243  * Parse each individual line.
244  */
245  while (p < end) {
246  /*
247  * Each record begins with a zero byte. If the
248  * next byte is also zero, that's the end of
249  * record indication.
250  */
251  if ((end - p) < 2) break;
252  if (!p[1]) break;
253 
254  /*
255  * Already checked in the "read" routine. But it
256  * doesn't hurt to re-check it here.
257  */
258  if ((*p != '\0') && (*p != '\t')) {
259  REDEBUG("Malformed line %d", lineno);
260  error:
261  fr_dcursor_free_list(&cursor);
262  return -1;
263  }
264 
265  p += 2;
266 
267  MPRINT("LINE :%s", p);
268 
269  /*
270  * Skip this for backwards compatibility.
271  */
272  if (strncasecmp((char const *) p, "Request-Authenticator", 21) == 0) goto next;
273 
274  /*
275  * The original time at which we received the
276  * packet. We need this to properly calculate
277  * Acct-Delay-Time.
278  */
279  if (strncasecmp((char const *) p, "Timestamp = ", 12) == 0) {
280  p += 12;
281 
282  timestamp = atoi((char const *) p);
283 
284  vp = fr_pair_afrom_da(request->request_ctx, attr_packet_original_timestamp);
285  if (vp) {
286  vp->vp_date = fr_unix_time_from_sec(timestamp);
287  fr_dcursor_append(&cursor, vp);
288  }
289  goto next;
290  }
291 
292  /*
293  * This should also have been caught.
294  */
295  if (strncasecmp((char const *) p, "Donestamp", 9) == 0) {
296  goto next;
297  }
298 
299  /*
300  * Ensure temporary list is empty before each use
301  */
302  fr_pair_list_free(&tmp_list);
303 
304  /*
305  * Reinitialize every time.
306  *
307  * @todo - maybe we want to keep "relative' around between lines?
308  * So that the detail file reader can read:
309  *
310  * foo = {}
311  * .bar = baz
312  *
313  * and get
314  *
315  * foo = { bar = baz }
316  *
317  * But doing that would require updating the
318  * detail file writer to track parent / child
319  * relationships, which we're not yet prepared to
320  * do.
321  *
322  * @todo - this also doesn't create nested attributes properly,
323  * as the write will write:
324  *
325  * foo.bar = baz
326  *
327  * and then the final pair "foo" is _appended_ to the input list, without paying
328  * any attention to what's going on!
329  *
330  * We likely just want to pass in request_pairs the parse function, AND also don't
331  * mash "relative" between calls.
332  */
333  root = (fr_pair_parse_t) {
334  .ctx = request->request_ctx,
335  .da = fr_dict_root(request->dict),
336  .list = &tmp_list,
337  };
338  relative = (fr_pair_parse_t) { };
339 
340  if ((fr_pair_list_afrom_substr(&root, &relative,
341  &FR_SBUFF_IN((char const *) p, (data + data_len) - p)) > 0) && !fr_pair_list_empty(&tmp_list)) {
342  vp = fr_pair_list_head(&tmp_list);
343  fr_pair_list_append(&request->request_pairs, &tmp_list);
344  } else {
345  vp = NULL;
346  RWDEBUG("Ignoring line %d - :%s", lineno, p);
347  }
348 
349  /*
350  * Set the original src/dst ip/port
351  */
352  if (vp) {
353  if (vp->da == attr_packet_src_ip_address) {
354  request->packet->socket.inet.src_ipaddr = vp->vp_ip;
355  } else if (vp->da == attr_packet_dst_ip_address) {
356  request->packet->socket.inet.dst_ipaddr = vp->vp_ip;
357  } else if (vp->da == attr_packet_src_port) {
358  request->packet->socket.inet.src_port = vp->vp_uint16;
359  } else if (vp->da == attr_packet_dst_port) {
360  request->packet->socket.inet.dst_port = vp->vp_uint16;
361  } else if (vp->da == attr_protocol) {
362  request->dict = fr_dict_by_protocol_num(vp->vp_uint32);
363  if (!request->dict) {
364  REDEBUG("Invalid protocol: %pP", vp);
365  goto error;
366  }
367  }
368  }
369 
370  next:
371  lineno++;
372  while ((p < end) && (*p)) p++;
373  }
374 
375  /*
376  * Let the app_io take care of populating additional fields in the request
377  */
378  return inst->app_io->decode(inst->app_io_instance, request, data, data_len);
379 }
380 
381 static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
382 {
383  if (buffer_len < 1) return -1;
384 
385  *buffer = request->reply->code;
386  return 1;
387 }
388 
389 static int mod_priority_set(void const *instance, UNUSED uint8_t const *buffer, UNUSED size_t buflen)
390 {
392 
393  /*
394  * Return the configured priority.
395  */
396  return inst->priority;
397 }
398 
399 
400 /** Open listen sockets/connect to external event source
401  *
402  * @param[in] instance Ctx data for this application.
403  * @param[in] sc to add our file descriptor to.
404  * @param[in] conf Listen section parsed to give us instance.
405  * @return
406  * - 0 on success.
407  * - -1 on failure.
408  */
409 static int mod_open(void *instance, fr_schedule_t *sc, CONF_SECTION *conf)
410 {
411  fr_listen_t *li;
412  proto_detail_t *inst = talloc_get_type_abort(instance, proto_detail_t);
413 
414  /*
415  * Build the #fr_listen_t. This describes the complete
416  * path, data takes from the socket to the decoder and
417  * back again.
418  */
419  li = talloc_zero(inst, fr_listen_t);
420  talloc_set_destructor(li, fr_io_listen_free);
421 
422  li->app_io = inst->app_io;
423  li->thread_instance = talloc_zero_array(NULL, uint8_t, li->app_io->common.thread_inst_size);
424  talloc_set_name(li->thread_instance, "proto_%s_thread_t", inst->app_io->common.name);
425  li->app_io_instance = inst->app_io_instance;
426 
427  li->app = &proto_detail;
428  li->app_instance = instance;
429  li->server_cs = inst->server_cs;
430 
431  /*
432  * Set configurable parameters for message ring buffer.
433  */
434  li->default_message_size = inst->max_packet_size;
435  li->num_messages = inst->num_messages;
436 
437  /*
438  * Open the file.
439  */
440  if (inst->app_io->open(li) < 0) {
441  cf_log_err(conf, "Failed opening %s file", inst->app_io->common.name);
442  talloc_free(li);
443  return -1;
444  }
445 
446  fr_assert(li->app_io->get_name);
447  li->name = li->app_io->get_name(li);
448 
449  /*
450  * Testing: allow it to read a "detail.work" file
451  * directly.
452  */
453  if (strcmp(inst->io_submodule->module->dl->name, "proto_detail_work") == 0) {
454  if (!fr_schedule_listen_add(sc, li)) {
455  talloc_free(li);
456  return -1;
457  }
458 
459  inst->listen = li;
460  return 0;
461  }
462 
463  if (li->non_socket_listener) {
464  /*
465  * Add listener. Will insert polling timer.
466  */
467  if (!fr_schedule_listen_add(sc, li)) {
468  talloc_free(li);
469  return -1;
470  }
471  } else {
472  /*
473  * Watch the directory for changes.
474  */
475  if (!fr_schedule_directory_add(sc, li)) {
476  talloc_free(li);
477  return -1;
478  }
479  }
480 
481  DEBUG("Listening on %s bound to virtual server %s",
482  li->name, cf_section_name2(li->server_cs));
483 
484  inst->listen = li; /* Probably won't need it, but doesn't hurt */
485  inst->sc = sc;
486 
487  return 0;
488 }
489 
490 
491 /** Instantiate the application
492  *
493  * Instantiate I/O and type submodules.
494  *
495  * @return
496  * - 0 on success.
497  * - -1 on failure.
498  */
499 static int mod_instantiate(module_inst_ctx_t const *mctx)
500 {
501  proto_detail_t *inst = talloc_get_type_abort(mctx->inst->data, proto_detail_t);
502  CONF_SECTION *conf = mctx->inst->conf;
503 
504  /*
505  * Instantiate the I/O module. But DON'T instantiate the
506  * work submodule. We leave that until later.
507  */
508  if (inst->app_io->common.instantiate &&
509  (inst->app_io->common.instantiate(MODULE_INST_CTX(inst->io_submodule)) < 0)) {
510  cf_log_err(conf, "Instantiation failed for \"%s\"", inst->app_io->common.name);
511  return -1;
512  }
513 
514  /*
515  * These configuration items are not printed by default,
516  * because normal people shouldn't be touching them.
517  */
518  if (!inst->max_packet_size) inst->max_packet_size = inst->app_io->default_message_size;
519 
520  if (!inst->num_messages) inst->num_messages = 2;
521 
522  FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, >=, 2);
523  FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, <=, 65535);
524 
525  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 1024);
526  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65536);
527 
528  if (!inst->priority) inst->priority = PRIORITY_NORMAL;
529 
530  /*
531  * If the IO is "file" and not the worker, instantiate the worker now.
532  */
533  if (strcmp(inst->io_submodule->module->dl->name, "proto_detail_work") != 0) {
534  if (inst->work_io->common.instantiate &&
535  (inst->work_io->common.instantiate(MODULE_INST_CTX(inst->work_submodule)) < 0)) {
536  cf_log_err(inst->work_io_conf, "Instantiation failed for \"%s\"", inst->work_io->common.name);
537  return -1;
538  }
539  }
540 
541  return 0;
542 }
543 
544 /** Bootstrap the application
545  *
546  * Bootstrap I/O and type submodules.
547  *
548  * @return
549  * - 0 on success.
550  * - -1 on failure.
551  */
552 static int mod_bootstrap(module_inst_ctx_t const *mctx)
553 {
554  proto_detail_t *inst = talloc_get_type_abort(mctx->inst->data, proto_detail_t);
555  CONF_SECTION *conf = mctx->inst->conf;
556 
557  /*
558  * The listener is inside of a virtual server.
559  */
560  inst->server_cs = cf_item_to_section(cf_parent(conf));
561  inst->cs = conf;
562  inst->self = &proto_detail;
563 
564  /*
565  * No IO module, it's an empty listener. That's not
566  * allowed for the detail file reader.
567  */
568  if (!inst->io_submodule) {
569  cf_log_err(conf, "Virtual server for detail files requires a 'transport' configuration");
570  return -1;
571  }
572 
573  /*
574  * Bootstrap the I/O module
575  */
576  inst->app_io = (fr_app_io_t const *) inst->io_submodule->module->common;
577  inst->app_io_instance = inst->io_submodule->data;
578  inst->app_io_conf = inst->io_submodule->conf;
579 
580  if (inst->app_io->common.bootstrap && (inst->app_io->common.bootstrap(MODULE_INST_CTX(inst->io_submodule)) < 0)) {
581  cf_log_err(inst->app_io_conf, "Bootstrap failed for \"%s\"", inst->app_io->common.name);
582  return -1;
583  }
584 
585  /*
586  * If we're not loading the work submodule directly, then try to load it here.
587  */
588  if (strcmp(inst->io_submodule->module->dl->name, "proto_detail_work") != 0) {
589  CONF_SECTION *transport_cs;
590  dl_module_inst_t *parent_inst;
591 
592  inst->work_submodule = NULL;
593 
594  transport_cs = cf_section_find(inst->cs, "work", NULL);
595  parent_inst = cf_data_value(cf_data_find(inst->cs, dl_module_inst_t, "proto_detail"));
596  fr_assert(parent_inst);
597 
598  if (!transport_cs) {
599  transport_cs = cf_section_dup(inst->cs, inst->cs, inst->app_io_conf,
600  "work", NULL, false);
601  if (!transport_cs) {
602  cf_log_err(inst->cs, "Failed to create configuration for worker");
603  return -1;
604  }
605  }
606 
607  if (dl_module_instance(parent_inst, &inst->work_submodule,
608  parent_inst,
609  DL_MODULE_TYPE_SUBMODULE, "work", dl_module_inst_name_from_conf(transport_cs)) < 0) {
610  cf_log_perr(inst->cs, "Failed to load proto_detail_work");
611  return -1;
612  }
613 
614  if (dl_module_conf_parse(inst->work_submodule, transport_cs) < 0) {
615  TALLOC_FREE(inst->work_submodule);
616  return -1;
617  }
618 
619  /*
620  * Boot strap the work module.
621  */
622  inst->work_io = (fr_app_io_t const *) inst->work_submodule->module->common;
623  inst->work_io_instance = inst->work_submodule->data;
624  inst->work_io_conf = inst->work_submodule->conf;
625 
626  if (inst->work_io->common.bootstrap &&
627  (inst->work_io->common.bootstrap(MODULE_INST_CTX(inst->work_submodule)) < 0)) {
628  cf_log_err(inst->work_io_conf, "Bootstrap failed for \"%s\"", inst->work_io->common.name);
629  TALLOC_FREE(inst->work_submodule);
630  return -1;
631  }
632  }
633 
634  return 0;
635 }
636 
637 
639  .common = {
640  .magic = MODULE_MAGIC_INIT,
641  .name = "detail",
642  .config = proto_detail_config,
643  .inst_size = sizeof(proto_detail_t),
644 
645  .bootstrap = mod_bootstrap,
647  },
648  .open = mod_open,
649  .decode = mod_decode,
650  .encode = mod_encode,
651  .priority = mod_priority_set
652 };
static int const char char buffer[256]
Definition: acutest.h:574
module_t common
Common fields to all loadable modules.
Definition: app_io.h:34
fr_io_name_t get_name
get the socket name
Definition: app_io.h:70
Public structure describing an I/O path for a protocol.
Definition: app_io.h:33
module_t common
Common fields provided by all modules.
Definition: application.h:72
Describes a new application (protocol)
Definition: application.h:71
#define UNUSED
Definition: build.h:313
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:486
#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
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: cf_parse.h:406
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition: cf_parse.h:421
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _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:241
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
Common header for all CONF_* types.
Definition: cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition: cf_priv.h:70
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: cf_util.c:629
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition: cf_util.c:970
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition: cf_util.c:1511
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition: cf_util.c:1680
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:649
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
Definition: cf_util.c:894
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_data_find(_cf, _type, _name)
Definition: cf_util.h:220
#define cf_parent(_cf)
Definition: cf_util.h:98
#define cf_log_perr(_cf, _fmt,...)
Definition: cf_util.h:272
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition: cf_util.h:137
#define PRIORITY_NORMAL
Definition: channel.h:151
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 void * fr_dcursor_tail(fr_dcursor_t *cursor)
Wind cursor to the tail item in the list.
Definition: dcursor.h:258
static void fr_dcursor_free_list(fr_dcursor_t *cursor)
Free the current item and all items after it.
Definition: dcursor.h:659
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
Definition: dict_util.c:2860
fr_dict_t const * fr_dict_by_protocol_num(unsigned int num)
Lookup a protocol by its number.
Definition: dict_util.c:2187
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
fr_value_box_t const * value
Enum value (what name maps to).
Definition: dict.h:213
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:2992
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
Value of an enumerated attribute.
Definition: dict.h:209
Test enumeration values.
Definition: dict_test.h:92
int dl_module_instance(TALLOC_CTX *ctx, dl_module_inst_t **out, dl_module_inst_t const *parent, dl_module_type_t type, char const *mod_name, char const *inst_name)
Load a module and parse its CONF_SECTION in one operation.
Definition: dl_module.c:552
char const * dl_module_inst_name_from_conf(CONF_SECTION *conf)
Avoid boilerplate when setting the module instance name.
Definition: dl_module.c:584
int dl_module_conf_parse(dl_module_inst_t *dl_inst, CONF_SECTION *conf)
Definition: dl_module.c:594
@ DL_MODULE_TYPE_SUBMODULE
Driver (or method in the case of EAP)
Definition: dl_module.h:71
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
A module/inst tuple.
Definition: dl_module.h:162
size_t num_messages
for the message ring buffer
Definition: listen.h:52
bool non_socket_listener
special internal listener that does not use sockets.
Definition: listen.h:45
char const * name
printable name for this socket - set by open
Definition: listen.h:29
void const * app_instance
Definition: listen.h:38
size_t default_message_size
copied from app_io, but may be changed
Definition: listen.h:51
fr_app_t const * app
Definition: listen.h:37
void const * app_io_instance
I/O path configuration context.
Definition: listen.h:32
int fr_io_listen_free(fr_listen_t *li)
Definition: master.c:2915
CONF_SECTION * server_cs
CONF_SECTION of the server.
Definition: listen.h:40
void * thread_instance
thread / socket context
Definition: listen.h:33
fr_app_io_t const * app_io
I/O path functions.
Definition: listen.h:31
#define RWDEBUG(fmt,...)
Definition: log.h:361
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition: log.h:705
talloc_free(reap)
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
Definition: merged_model.c:111
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
int strncasecmp(char *s1, char *s2, int n)
Definition: missing.c:36
#define MODULE_INST_CTX(_dl_inst)
Wrapper to create a module_inst_ctx_t as a compound literal.
Definition: module_ctx.h:153
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:278
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
Definition: pair_legacy.c:150
struct fr_pair_parse_s fr_pair_parse_t
TALLOC_CTX * ctx
Definition: pair_legacy.h:43
static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
Definition: proto_detail.c:381
static fr_dict_attr_t const * attr_protocol
Definition: proto_detail.c:88
fr_app_t proto_detail
Definition: proto_detail.c:638
static int type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static int mod_open(void *instance, fr_schedule_t *sc, CONF_SECTION *conf)
Open listen sockets/connect to external event source.
Definition: proto_detail.c:409
static fr_dict_attr_t const * attr_packet_src_port
Definition: proto_detail.c:87
static fr_dict_t const * dict_freeradius
Definition: proto_detail.c:74
#define MPRINT(x,...)
Definition: proto_detail.c:44
static int mod_decode(void const *instance, request_t *request, uint8_t *const data, size_t data_len)
Decode the packet, and set the request->process function.
Definition: proto_detail.c:194
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Bootstrap the application.
Definition: proto_detail.c:552
static fr_dict_attr_t const * attr_packet_original_timestamp
Definition: proto_detail.c:85
static int mod_priority_set(void const *instance, UNUSED uint8_t const *buffer, UNUSED size_t buflen)
Definition: proto_detail.c:389
fr_dict_attr_autoload_t proto_detail_dict_attr[]
Definition: proto_detail.c:91
fr_dict_autoload_t proto_detail_dict[]
Definition: proto_detail.c:77
static fr_dict_attr_t const * attr_packet_dst_ip_address
Definition: proto_detail.c:83
static int mod_instantiate(module_inst_ctx_t const *mctx)
Instantiate the application.
Definition: proto_detail.c:499
static fr_dict_attr_t const * attr_packet_src_ip_address
Definition: proto_detail.c:86
static fr_dict_attr_t const * attr_packet_dst_port
Definition: proto_detail.c:84
static conf_parser_t const proto_detail_config[]
How to parse a Detail listen section.
Definition: proto_detail.c:50
static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Detail master protocol handler.
#define REDEBUG(fmt,...)
Definition: radclient.h:52
static rs_t * conf
Definition: radsniff.c:53
static char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
#define FR_SBUFF_IN(_start, _len_or_end)
fr_network_t * fr_schedule_directory_add(fr_schedule_t *sc, fr_listen_t *li)
Add a directory NOTE_EXTEND to a scheduler.
Definition: schedule.c:855
fr_network_t * fr_schedule_listen_add(fr_schedule_t *sc, fr_listen_t *li)
Add a fr_listen_t to a scheduler.
Definition: schedule.c:823
The scheduler.
Definition: schedule.c:125
size_t thread_inst_size
Definition: module.h:151
static const uchar sc[16]
Definition: smbdes.c:115
if(!subtype_vp) goto fail
fr_assert(0)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
#define talloc_get_type_abort_const
Definition: talloc.h:270
static fr_unix_time_t fr_unix_time_from_sec(int64_t sec)
Definition: time.h:447
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
Definition: pair_inline.c:125
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
Definition: pair_inline.c:113
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
Definition: pair_inline.c:182
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:590
static fr_slen_t parent
Definition: pair.h:844
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984
fr_dict_t const * virtual_server_dict_by_child_ci(CONF_ITEM const *ci)
Return the namespace for a given virtual server specified by a CONF_ITEM within the virtual server.