The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
proto_bfd.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: 4c394e4251781396e7de9c865f7a2f1ac933915e $
19  * @file proto_bfd.c
20  * @brief RADIUS 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/listen.h>
26 #include <freeradius-devel/server/module_rlm.h>
27 #include <freeradius-devel/internal/internal.h>
28 
29 #include "proto_bfd.h"
30 
31 extern fr_app_t proto_bfd;
32 
33 static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
34 static int auth_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule);
35 
36 /** How to parse a BFD listen section
37  *
38  */
39 static conf_parser_t const proto_bfd_config[] = {
40  { FR_CONF_OFFSET_TYPE_FLAGS("transport", FR_TYPE_VOID, 0, proto_bfd_t, io.submodule),
41  .func = transport_parse },
42 
44 };
45 
46 static const conf_parser_t peer_config[] = {
47  { FR_CONF_OFFSET("min_transmit_interval", bfd_session_t, desired_min_tx_interval ) },
48  { FR_CONF_OFFSET("min_receive_interval", bfd_session_t, required_min_rx_interval ) },
49  { FR_CONF_OFFSET("max_timeouts", bfd_session_t, detect_multi ) },
50  { FR_CONF_OFFSET("demand", bfd_session_t, demand_mode ) },
51 
52  { FR_CONF_OFFSET_TYPE_FLAGS("auth_type", FR_TYPE_VOID, 0, bfd_session_t, auth_type ),
53  .func = auth_type_parse },
54 
55  { FR_CONF_OFFSET("port", bfd_session_t, port ) },
56 
58 };
59 
60 static fr_dict_t const *dict_bfd;
61 
64  { .out = &dict_bfd, .proto = "bfd" },
65  { NULL }
66 };
67 
73 
76  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_bfd},
77 
78  { .out = &attr_bfd_packet, .name = "Packet", .type = FR_TYPE_STRUCT, .dict = &dict_bfd},
79  { .out = &attr_my_discriminator, .name = "Packet.my-discriminator", .type = FR_TYPE_UINT32, .dict = &dict_bfd},
80  { .out = &attr_your_discriminator, .name = "Packet.your-discriminator", .type = FR_TYPE_UINT32, .dict = &dict_bfd},
81 
82  { .out = &attr_additional_data, .name = "Additional-Data", .type = FR_TYPE_GROUP, .dict = &dict_bfd},
83  { NULL }
84 };
85 
86 /*
87  * They all have to be UDP.
88  */
89 static int8_t client_cmp(void const *one, void const *two)
90 {
91  fr_client_t const *a = one;
92  fr_client_t const *b = two;
93 
94  return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr);
95 }
96 
97 /** Wrapper around dl_instance
98  *
99  * @param[in] ctx to allocate data in (instance of proto_bfd).
100  * @param[out] out Where to write a dl_module_inst_t containing the module handle and instance.
101  * @param[in] parent Base structure address.
102  * @param[in] ci #CONF_PAIR specifying the name of the type module.
103  * @param[in] rule unused.
104  * @return
105  * - 0 on success.
106  * - -1 on failure.
107  */
108 static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
109 {
110  char const *name = cf_pair_value(cf_item_to_pair(ci));
111  dl_module_inst_t *parent_inst;
112  proto_bfd_t *inst;
113  CONF_SECTION *listen_cs = cf_item_to_section(cf_parent(ci));
114  CONF_SECTION *transport_cs;
115  dl_module_inst_t *dl_mod_inst;
116 
117  transport_cs = cf_section_find(listen_cs, name, NULL);
118 
119  parent_inst = cf_data_value(cf_data_find(listen_cs, dl_module_inst_t, "proto_bfd"));
120  fr_assert(parent_inst);
121 
122  /*
123  * Set the allowed codes so that we can compile them as
124  * necessary.
125  */
126  inst = talloc_get_type_abort(parent_inst->data, proto_bfd_t);
127  inst->io.transport = name;
128 
129  /*
130  * Allocate an empty section if one doesn't exist
131  * this is so defaults get parsed.
132  */
133  if (!transport_cs) {
134  transport_cs = cf_section_alloc(listen_cs, listen_cs, name, NULL);
135  inst->io.app_io_conf = transport_cs;
136  }
137 
138  if (dl_module_instance(ctx, &dl_mod_inst, parent_inst,
139  DL_MODULE_TYPE_SUBMODULE, name, dl_module_inst_name_from_conf(transport_cs)) < 0) return -1;
140  if (dl_module_conf_parse(dl_mod_inst, transport_cs) < 0) {
141  talloc_free(dl_mod_inst);
142  return -1;
143  }
144  *((dl_module_inst_t **)out) = dl_mod_inst;
145 
146  return 0;
147 }
148 
149 /** Parse auth_type
150  *
151  * @param[in] ctx to allocate data in (instance of proto_bfd).
152  * @param[out] out Where to write the auth_type value
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 auth_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
161 {
162  char const *name = cf_pair_value(cf_item_to_pair(ci));
163  int auth_type;
164 
166  if (auth_type < 0) {
167  cf_log_err(ci, "Invalid value for 'auth_type'");
168  return -1;
169  }
170 
171  *(bfd_auth_type_t *) out = auth_type;
172 
173  return 0;
174 }
175 
176 
177 /** Decode the packet
178  *
179  */
180 static int mod_decode(UNUSED void const *instance, request_t *request, uint8_t *const data, size_t data_len)
181 {
182  fr_io_track_t const *track = talloc_get_type_abort_const(request->async->packet_ctx, fr_io_track_t);
183  fr_io_address_t const *address = track->address;
184  fr_client_t const *client;
185  fr_pair_t *vp, *reply, *my, *your;
186  bfd_wrapper_t const *wrapper = (bfd_wrapper_t const *) data;
187  bfd_packet_t const *bfd = (bfd_packet_t const *) wrapper->packet;
188 
189  /*
190  * Set the request dictionary so that we can do
191  * generic->protocol attribute conversions as
192  * the request runs through the server.
193  */
194  request->dict = dict_bfd;
195 
196  client = address->radclient;
197 
198  /*
199  * Hacks for now until we have a lower-level decode routine.
200  */
201  request->packet->code = bfd->state;
202  request->packet->id = fr_nbo_to_uint32((uint8_t const *) &bfd->my_disc);
203  request->reply->id = request->packet->id;
204 
205  request->packet->data = talloc_memdup(request->packet, data, data_len);
206  request->packet->data_len = data_len;
207 
208  /*
209  * Set the rest of the fields.
210  */
211  request->client = UNCONST(fr_client_t *, client);
212 
213  request->packet->socket = address->socket;
214  fr_socket_addr_swap(&request->reply->socket, &address->socket);
215 
216  REQUEST_VERIFY(request);
217 
218  /*
219  * Decode the packet into the reply.
220  */
221  if (wrapper->type == BFD_WRAPPER_SEND_PACKET) {
222  if (fr_bfd_decode(request->reply_ctx, &request->reply_pairs,
223  (uint8_t const *) bfd, bfd->length,
224  client->secret, talloc_array_length(client->secret) - 1) < 0) {
225  RPEDEBUG("Failed decoding packet");
226  return -1;
227  }
228 
229  request->reply->code = bfd->state;
230 
231  return 0;
232  }
233 
234  if (fr_bfd_decode(request->request_ctx, &request->request_pairs,
235  (uint8_t const *) bfd, bfd->length,
236  client->secret, talloc_array_length(client->secret) - 1) < 0) {
237  RPEDEBUG("Failed decoding packet");
238  return -1;
239  }
240 
241  /*
242  * Initialize the reply.
243  */
244  vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_bfd_packet);
245  if (!vp) return -1;
246 
247  reply = fr_pair_copy(request->reply_ctx, vp);
248  fr_pair_append(&request->reply_pairs, reply);
249 
250  my = fr_pair_find_by_da_nested(&reply->vp_group, NULL, attr_my_discriminator);
251  your = fr_pair_find_by_da_nested(&reply->vp_group, NULL, attr_your_discriminator);
252 
253  if (my && your) {
254  uint32_t tmp = your->vp_uint32;
255 
256  your->vp_uint32 = my->vp_uint32;
257  my->vp_uint32 = tmp;
258  }
259 
260  if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
261  RPEDEBUG("Failed decoding 'Net.*' packet");
262  return -1;
263  }
264 
265  return 0;
266 }
267 
268 static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
269 {
270 // proto_bfd_t const *inst = talloc_get_type_abort_const(instance, proto_bfd_t);
271  fr_io_track_t *track = talloc_get_type_abort(request->async->packet_ctx, fr_io_track_t);
272  fr_io_address_t const *address = track->address;
273  fr_client_t const *client;
274  bfd_wrapper_t const *wrapper = (bfd_wrapper_t const *) request->packet->data;
275  bfd_packet_t const *bfd = (bfd_packet_t const *) wrapper->packet;
276  fr_pair_t *vp;
277  ssize_t slen;
278  fr_dbuff_t dbuff;
279 
280  /*
281  * Process layer NAK, or "Do not respond".
282  */
283  if ((buffer_len == 1) || (wrapper->type == BFD_WRAPPER_RECV_PACKET) || (wrapper->type == BFD_WRAPPER_STATE_CHANGE)) {
284  return 0;
285  }
286 
287  client = address->radclient;
288  fr_assert(client);
289 
290  fr_packet_pairs_to_packet(request->reply, &request->reply_pairs);
291 
292  /*
293  * Dynamic client stuff
294  */
295  if (client->dynamic && !client->active) {
296  fr_client_t *new_client;
297 
298  fr_assert(buffer_len >= sizeof(client));
299 
300  /*
301  * Allocate the client. If that fails, send back a NAK.
302  *
303  * @todo - deal with NUMA zones? Or just deal with this
304  * client being in different memory.
305  *
306  * Maybe we should create a CONF_SECTION from the client,
307  * and pass *that* back to mod_write(), which can then
308  * parse it to create the actual client....
309  */
310  new_client = client_afrom_request(NULL, request);
311  if (!new_client) {
312  PERROR("Failed creating new client");
313  *buffer = true;
314  return 1;
315  }
316 
317  memcpy(buffer, &new_client, sizeof(new_client));
318  return sizeof(new_client);
319  }
320 
321  fr_assert((wrapper->packet + bfd->length) == (request->packet->data + request->packet->data_len));
322 
323  /*
324  * Don't bother re-encoding the packet.
325  */
326  memcpy(buffer, bfd, bfd->length);
327 
328  fr_assert(fr_bfd_packet_ok(NULL, buffer, bfd->length));
329 
330  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_additional_data);
331  if (!vp) return bfd->length;
332 
333  fr_dbuff_init(&dbuff, buffer + bfd->length, buffer_len - bfd->length);
334  slen = fr_internal_encode_list(&dbuff, &vp->vp_group, NULL);
335  if (slen <= 0) return bfd->length;
336 
337  return bfd->length + slen;
338 }
339 
340 /** Open listen sockets/connect to external event source
341  *
342  * @param[in] instance Ctx data for this application.
343  * @param[in] sc to add our file descriptor to.
344  * @param[in] conf Listen section parsed to give us instance.
345  * @return
346  * - 0 on success.
347  * - -1 on failure.
348  */
349 static int mod_open(void *instance, fr_schedule_t *sc, UNUSED CONF_SECTION *conf)
350 {
351  proto_bfd_t *inst = talloc_get_type_abort(instance, proto_bfd_t);
352 
353  inst->io.app = &proto_bfd;
354  inst->io.app_instance = instance;
355 
356  /*
357  * io.app_io should already be set
358  */
359  return fr_master_io_listen(inst, &inst->io, sc,
360  inst->max_packet_size, inst->num_messages);
361 }
362 
363 /** Instantiate the application
364  *
365  * Instantiate I/O and type submodules.
366  *
367  * @return
368  * - 0 on success.
369  * - -1 on failure.
370  */
371 static int mod_instantiate(module_inst_ctx_t const *mctx)
372 {
373  proto_bfd_t *inst = talloc_get_type_abort(mctx->inst->data, proto_bfd_t);
374 
375  /*
376  * No IO module, it's an empty listener.
377  */
378  if (!inst->io.submodule) return 0;
379 
380  /*
381  * These configuration items are not printed by default,
382  * because normal people shouldn't be touching them.
383  */
384  if (!inst->max_packet_size && inst->io.app_io) inst->max_packet_size = inst->io.app_io->default_message_size;
385 
386  if (!inst->num_messages) inst->num_messages = 256;
387 
388  FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, >=, 32);
389  FR_INTEGER_BOUND_CHECK("num_messages", inst->num_messages, <=, 65535);
390 
391  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, >=, 1024);
392  FR_INTEGER_BOUND_CHECK("max_packet_size", inst->max_packet_size, <=, 65535);
393 
394  /*
395  * Instantiate the master io submodule
396  */
398 }
399 
400 
401 /** Bootstrap the application
402  *
403  * Bootstrap I/O and type submodules.
404  *
405  * @return
406  * - 0 on success.
407  * - -1 on failure.
408  */
409 static int mod_bootstrap(module_inst_ctx_t const *mctx)
410 {
411  proto_bfd_t *inst = talloc_get_type_abort(mctx->inst->data, proto_bfd_t);
412  CONF_SECTION *server;
413 
414  /*
415  * Ensure that the server CONF_SECTION is always set.
416  */
417  inst->io.server_cs = cf_item_to_section(cf_parent(mctx->inst->conf));
418 
419  /*
420  * No IO module, it's an empty listener.
421  */
422  if (!inst->io.submodule) return 0;
423 
424  /*
425  * Tell the master handler about the main protocol instance.
426  */
427  inst->io.app = &proto_bfd;
428  inst->io.app_instance = inst;
429 
430  /*
431  * We will need this for dynamic clients and connected sockets.
432  */
433  inst->io.dl_inst = dl_module_instance_by_data(inst);
434  fr_assert(inst != NULL);
435 
436  server = inst->io.server_cs;
437 
438  inst->peers = cf_data_value(cf_data_find(server, fr_rb_tree_t, "peers"));
439  if (!inst->peers) {
440  CONF_SECTION *cs = NULL;
441 
442  inst->peers = fr_rb_inline_talloc_alloc(inst, fr_client_t, node, client_cmp, NULL);
443  if (!inst->peers) return -1;
444 
445  while ((cs = cf_section_find_next(server, cs, "peer", CF_IDENT_ANY))) {
446  fr_client_t *c;
447  bfd_session_t *peer;
448 
449  if (cf_section_rules_push(cs, peer_config) < 0) return -1;
450 
451  c = client_afrom_cs(cs, cs, server, sizeof(bfd_session_t));
452  if (!c) {
453  error:
454  cf_log_err(cs, "Failed to parse peer %s", cf_section_name2(cs));
455  talloc_free(inst->peers);
456  return -1;
457  }
458 
459  if (c->proto != IPPROTO_UDP) {
460  cf_log_err(cs, "Peer must use 'proto = udp' in %s", cf_section_name2(cs));
461  goto error;
462  }
463 
464  peer = (bfd_session_t *) c;
465 
466  FR_TIME_DELTA_BOUND_CHECK("peer.min_transmit_interval", peer->desired_min_tx_interval, >=, fr_time_delta_from_usec(32));
467  FR_TIME_DELTA_BOUND_CHECK("peer.min_transmit_interval", peer->desired_min_tx_interval, <=, fr_time_delta_from_sec(2));
468 
469  FR_TIME_DELTA_BOUND_CHECK("peer.min_recieve_interval", peer->required_min_rx_interval, >=, fr_time_delta_from_usec(32));
470  FR_TIME_DELTA_BOUND_CHECK("peer.min_received_interval", peer->required_min_rx_interval, <=, fr_time_delta_from_sec(2));
471 
472  FR_INTEGER_BOUND_CHECK("peer.max_timeouts", peer->detect_multi, >=, 1);
473  FR_INTEGER_BOUND_CHECK("peer.max_timeouts", peer->detect_multi, <=, 10);
474 
475  if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix != 32)) ||
476  ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix != 128))) {
477  cf_log_err(cs, "Invalid IP prefix - cannot use ip/mask for BFD");
478  goto error;
479  }
480 
481  /*
482  * Secret and auth_type handling.
483  */
484  if (c->secret) {
485  if (!*c->secret) {
486  cf_log_err(cs, "Secret cannot be an empty string");
487  goto error;
488  }
489 
490  peer->secret_len = talloc_array_length(c->secret) - 1;
491  }
492 
493  switch (peer->auth_type) {
494  case BFD_AUTH_RESERVED:
495  if (c->secret) cf_log_warn(cs, "Ignoring 'secret' due to 'auth_type = none'");
496  break;
497 
498  case BFD_AUTH_SIMPLE:
499  case BFD_AUTH_KEYED_MD5:
501  if (!c->secret) {
502  cf_log_err(cs, "A 'secret' must be specified when using 'auth_type = simple'");
503  goto error;
504  }
505 
506  if (strlen(c->secret) > 16) {
507  cf_log_err(cs, "Length of 'secret' must be no more than 16 octets for 'auth_type = simple'");
508  goto error;
509  }
510  break;
511 
512  case BFD_AUTH_KEYED_SHA1:
514  if (!c->secret) {
515  cf_log_err(cs, "A 'secret' must be specified when using 'auth_type = ...'");
516  goto error;
517  }
518 
519  if (strlen(c->secret) > 20) {
520  cf_log_err(cs, "Length of 'secret' must be no more than 16 octets for 'auth_type = simple'");
521  goto error;
522  }
523  break;
524 
525  }
526 
527  c->active = true;
528 
529  if (!fr_rb_insert(inst->peers, c)) {
530  cf_log_err(cs, "Failed to add peer %s", cf_section_name2(cs));
531  goto error;
532  }
533  }
534 
535  (void) cf_data_add(server, inst->peers, "peers", false);
536  }
537 
538  /*
539  * Bootstrap the master IO handler.
540  */
542 }
543 
544 static int mod_load(void)
545 {
546  if (fr_bfd_global_init() < 0) {
547  PERROR("Failed initialising protocol library");
548  return -1;
549  }
550  return 0;
551 }
552 
553 static void mod_unload(void)
554 {
556 }
557 
559  .common = {
560  .magic = MODULE_MAGIC_INIT,
561  .name = "bfd",
562  .config = proto_bfd_config,
563  .inst_size = sizeof(proto_bfd_t),
564  .onload = mod_load,
565  .unload = mod_unload,
566  .bootstrap = mod_bootstrap,
568  },
569  .dict = &dict_bfd,
570  .open = mod_open,
571  .decode = mod_decode,
572  .encode = mod_encode,
573 };
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
module_t common
Common fields provided by all modules.
Definition: application.h:72
Describes a new application (protocol)
Definition: application.h:71
bfd_auth_type_t
Definition: bfd.h:52
@ BFD_AUTH_MET_KEYED_MD5
Definition: bfd.h:56
@ BFD_AUTH_MET_KEYED_SHA1
Definition: bfd.h:58
@ BFD_AUTH_SIMPLE
Definition: bfd.h:54
@ BFD_AUTH_KEYED_SHA1
Definition: bfd.h:57
@ BFD_AUTH_KEYED_MD5
Definition: bfd.h:55
@ BFD_AUTH_RESERVED
Definition: bfd.h:53
ssize_t fr_bfd_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len, char const *secret, size_t secret_len)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#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
#define cf_section_rules_push(_cs, _rule)
Definition: cf_parse.h:658
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:497
#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
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_find_next(CONF_SECTION const *cs, CONF_SECTION const *prev, char const *name1, char const *name2)
Return the next matching section.
Definition: cf_util.c:991
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:265
#define cf_data_add(_cf, _data, _name, _free)
Definition: cf_util.h:231
#define cf_data_find(_cf, _type, _name)
Definition: cf_util.h:220
#define cf_parent(_cf)
Definition: cf_util.h:98
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition: cf_util.h:137
#define cf_log_warn(_cf, _fmt,...)
Definition: cf_util.h:266
#define CF_IDENT_ANY
Definition: cf_util.h:78
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
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
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
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
dl_module_inst_t const * dl_module_instance_by_data(void const *data)
Lookup a dl_module_inst_t via instance data.
Definition: dl_module.c:215
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
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1332
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
Definition: inet.h:69
int af
Address family.
Definition: inet.h:64
fr_socket_t socket
src/dst ip and port.
Definition: base.h:336
fr_client_t const * radclient
old-style client definition
Definition: base.h:338
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: client.h:80
char const * secret
Secret PSK.
Definition: client.h:87
bool active
for dynamic clients
Definition: client.h:91
int proto
Protocol number.
Definition: client.h:115
bool dynamic
Whether the client was dynamically defined.
Definition: client.h:90
Describes a host allowed to send packets to the server.
Definition: client.h:77
#define PERROR(_fmt,...)
Definition: log.h:228
#define RPEDEBUG(fmt,...)
Definition: log.h:376
void fr_packet_pairs_to_packet(fr_packet_t *packet, fr_pair_list_t const *list)
Convert pairs to information in a packet.
Definition: packet.c:136
int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
Allocate a "Net." struct with src/dst host and port.
Definition: packet.c:86
talloc_free(reap)
size_t secret_len
doesn't change while we're running
Definition: session.h:106
fr_time_delta_t required_min_rx_interval
intervals between receives
Definition: session.h:82
@ BFD_WRAPPER_STATE_CHANGE
Definition: session.h:128
@ BFD_WRAPPER_SEND_PACKET
Definition: session.h:127
@ BFD_WRAPPER_RECV_PACKET
Definition: session.h:126
uint8_t packet[]
Definition: session.h:145
bfd_auth_type_t auth_type
what kind of authentication is used
Definition: session.h:101
uint32_t detect_multi
Definition: session.h:79
fr_time_delta_t desired_min_tx_interval
intervals between transmits
Definition: session.h:81
uint32_t type
Definition: session.h:142
fr_app_io_t fr_master_app_io
Definition: master.c:3131
int fr_master_io_listen(TALLOC_CTX *ctx, fr_io_instance_t *inst, fr_schedule_t *sc, size_t default_message_size, size_t num_messages)
Definition: master.c:2923
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition: master.h:54
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
Definition: merged_model.c:119
@ FR_TYPE_VOID
User data.
Definition: merged_model.c:127
@ FR_TYPE_GROUP
A grouping of other attributes.
Definition: merged_model.c:124
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
#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
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
Definition: nbo.h:158
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition: pair.c:688
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1340
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition: pair.c:484
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
Definition: pair.c:765
static int mod_load(void)
Definition: proto_bfd.c:544
static fr_dict_attr_t const * attr_packet_type
Definition: proto_bfd.c:68
static ssize_t mod_encode(UNUSED void const *instance, request_t *request, uint8_t *buffer, size_t buffer_len)
Definition: proto_bfd.c:268
static int8_t client_cmp(void const *one, void const *two)
Definition: proto_bfd.c:89
static fr_dict_attr_t const * attr_bfd_packet
Definition: proto_bfd.c:69
static conf_parser_t const proto_bfd_config[]
How to parse a BFD listen section.
Definition: proto_bfd.c:39
static fr_dict_attr_t const * attr_my_discriminator
Definition: proto_bfd.c:70
static fr_dict_attr_t const * attr_additional_data
Definition: proto_bfd.c:72
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Bootstrap the application.
Definition: proto_bfd.c:409
fr_dict_attr_autoload_t proto_bfd_dict_attr[]
Definition: proto_bfd.c:75
static void mod_unload(void)
Definition: proto_bfd.c:553
static int mod_decode(UNUSED void const *instance, request_t *request, uint8_t *const data, size_t data_len)
Decode the packet.
Definition: proto_bfd.c:180
fr_app_t proto_bfd
Definition: proto_bfd.c:558
fr_dict_autoload_t proto_bfd_dict[]
Definition: proto_bfd.c:63
static fr_dict_attr_t const * attr_your_discriminator
Definition: proto_bfd.c:71
static int auth_type_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
static const conf_parser_t peer_config[]
Definition: proto_bfd.c:46
static fr_dict_t const * dict_bfd
Definition: proto_bfd.c:60
static int mod_instantiate(module_inst_ctx_t const *mctx)
Instantiate the application.
Definition: proto_bfd.c:371
static int mod_open(void *instance, fr_schedule_t *sc, UNUSED CONF_SECTION *conf)
Open listen sockets/connect to external event source.
Definition: proto_bfd.c:349
static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
An instance of a proto_radius listen section.
Definition: proto_bfd.h:33
int fr_bfd_global_init(void)
Definition: base.c:221
void fr_bfd_global_free(void)
Definition: base.c:244
fr_table_num_ordered_t const bfd_auth_type_table[]
Definition: base.c:70
bool fr_bfd_packet_ok(char const **err, uint8_t const *packet, size_t packet_len)
Definition: base.c:83
ssize_t fr_internal_encode_list(fr_dbuff_t *dbuff, fr_pair_list_t const *list, void *encode_ctx)
Encode a list of pairs using the internal encoder.
Definition: encode.c:303
static rs_t * conf
Definition: radsniff.c:53
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition: rb.c:624
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
Definition: rb.h:246
The main red black tree structure.
Definition: rb.h:73
#define REQUEST_VERIFY(_x)
Definition: request.h:275
static char const * name
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
The scheduler.
Definition: schedule.c:125
module_instantiate_t instantiate
Definition: module.h:146
module_instantiate_t bootstrap
Definition: module.h:145
static const uchar sc[16]
Definition: smbdes.c:115
fr_client_t * client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *server_cs, size_t extra)
Allocate a new client from a config section.
Definition: client.c:697
fr_client_t * client_afrom_request(TALLOC_CTX *ctx, request_t *request)
Create a new client, consuming all attributes in the control list of the request.
Definition: client.c:915
fr_assert(0)
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
Definition: table.h:134
#define talloc_get_type_abort_const
Definition: talloc.h:270
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition: time.h:588
static fr_time_delta_t fr_time_delta_from_usec(int64_t usec)
Definition: time.h:566
static fr_slen_t parent
Definition: pair.h:844
static void fr_socket_addr_swap(fr_socket_t *dst, fr_socket_t const *src)
Swap src/dst information of a fr_socket_t.
Definition: socket.h:121
static fr_slen_t data
Definition: value.h:1259
static size_t char ** out
Definition: value.h:984