The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
proto_bfd_udp.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: 2e40eb6b90eedd466c1025ff99b87ac7cf054f8c $
19  * @file proto_bfd_udp.c
20  * @brief BFD handler for UDP.
21  *
22  * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
23  */
24 #include <netdb.h>
25 #include <freeradius-devel/server/protocol.h>
26 #include <freeradius-devel/util/udp.h>
27 #include <freeradius-devel/util/trie.h>
28 #include <freeradius-devel/bfd/bfd.h>
29 #include <freeradius-devel/io/application.h>
30 #include <freeradius-devel/io/listen.h>
31 #include <freeradius-devel/io/schedule.h>
32 
33 #include "session.h"
34 
36 
37 typedef struct {
38  char const *name; //!< socket name
39  int sockfd;
40 
41  fr_io_address_t *connection; //!< for connected sockets.
42 
43  fr_stats_t stats; //!< statistics for this socket
44 
46 
47 typedef struct {
48  CONF_SECTION *cs; //!< our configuration
49  char const *server_name; //!< virtual server name
50 
51  fr_ipaddr_t ipaddr; //!< IP address to listen on.
52 
53  char const *interface; //!< Interface to bind to.
54  char const *port_name; //!< Name of the port for getservent().
55 
56  uint32_t recv_buff; //!< How big the kernel's receive buffer should be.
57  uint32_t send_buff; //!< How big the kernel's send buffer should be.
58 
59  uint16_t port; //!< Port to listen on.
60 
61  uint8_t ttl; //!< default ttl
62 
63  bool only_state_changes; //!< on read(), only send packets which signal a state change
64 
65  bool recv_buff_is_set; //!< Whether we were provided with a recv_buff
66  bool send_buff_is_set; //!< Whether we were provided with a send_buff
67  bool dynamic_clients; //!< whether we have dynamic clients
68 
69  fr_rb_tree_t *peers; //!< our peers
70 
71  fr_trie_t *trie; //!< for parsed networks
72  fr_ipaddr_t *allow; //!< allowed networks for dynamic clients
73  fr_ipaddr_t *deny; //!< denied networks for dynamic clients
75 
76 
77 static const conf_parser_t networks_config[] = {
80 
82 };
83 
84 
85 static const conf_parser_t udp_listen_config[] = {
87  { FR_CONF_OFFSET_TYPE_FLAGS("ipv4addr", FR_TYPE_IPV4_ADDR, 0, proto_bfd_udp_t, ipaddr) },
88  { FR_CONF_OFFSET_TYPE_FLAGS("ipv6addr", FR_TYPE_IPV6_ADDR, 0, proto_bfd_udp_t, ipaddr) },
89 
90  { FR_CONF_OFFSET("interface", proto_bfd_udp_t, interface) },
91  { FR_CONF_OFFSET("port_name", proto_bfd_udp_t, port_name) },
92 
93  { FR_CONF_OFFSET("port", proto_bfd_udp_t, port) },
94 
95  { FR_CONF_OFFSET("ttl", proto_bfd_udp_t, ttl), .dflt = "255" },
96 
97  { FR_CONF_OFFSET("only_state_changes", proto_bfd_udp_t, only_state_changes), .dflt = "yes" },
98 
99  { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, proto_bfd_udp_t, recv_buff) },
100  { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, proto_bfd_udp_t, send_buff) },
101 
102 // { FR_CONF_OFFSET("dynamic_clients", proto_bfd_udp_t, dynamic_clients) } ,
103  { FR_CONF_POINTER("networks", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) networks_config },
104 
106 };
107 
108 
109 static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len,
110  size_t *leftover)
111 {
113  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
114  fr_io_address_t *address, **address_p;
115  fr_client_t *client;
116 
117  int flags;
118  ssize_t data_size;
119  size_t packet_len;
120 
121  bfd_packet_t *packet;
122  char const *err = NULL;
123  bfd_state_change_t state_change;
124  bfd_wrapper_t *wrapper = (bfd_wrapper_t *) buffer;
125 
126  *leftover = 0; /* always for UDP */
127 
128  /*
129  * Where the addresses should go. This is a special case
130  * for proto_bfd.
131  */
132  address_p = (fr_io_address_t **)packet_ctx;
133  address = *address_p;
134 
135  /*
136  * Tell udp_recv if we're connected or not.
137  */
138  flags = UDP_FLAGS_CONNECTED * (thread->connection != NULL);
139 
140  data_size = udp_recv(thread->sockfd, flags, &address->socket, wrapper->packet, buffer_len - offsetof(bfd_wrapper_t, packet), recv_time_p);
141  if (data_size < 0) {
142  PDEBUG2("proto_bfd_udp got read error");
143  return data_size;
144  }
145 
146  if (!data_size) {
147  DEBUG2("proto_bfd_udp got no data: ignoring");
148  return 0;
149  }
150 
151  /*
152  * Try to find the client before looking at any packet data.
153  */
154  client = fr_rb_find(inst->peers, &(fr_client_t) { .ipaddr = address->socket.inet.src_ipaddr, .proto = IPPROTO_UDP });
155  if (!client) {
156  DEBUG2("BFD %s - Received invalid packet on %s - unknown client %pV:%u", inst->server_name, thread->name,
157  fr_box_ipaddr(address->socket.inet.src_ipaddr), address->socket.inet.src_port);
158  thread->stats.total_packets_dropped++;
159  return 0;
160  }
161 
162  packet_len = data_size;
163 
164  if (!fr_bfd_packet_ok(&err, wrapper->packet, packet_len)) {
165  DEBUG2("BFD %s - Received invalid packet on %s - %s", inst->server_name, thread->name, err);
167  return 0;
168  }
169 
170  thread->stats.total_requests++;
171  packet = (bfd_packet_t *) wrapper->packet;
172 
173  /*
174  * Print out what we received.
175  */
176  DEBUG2("BFD %s peer %s received %s", client->shortname, inst->server_name, fr_bfd_packet_names[packet->state]);
177 
178  /*
179  * Run the BFD state machine. Depending on that result,
180  * we either send the packet through to unlang, or not.
181  */
182  state_change = bfd_session_process((bfd_session_t *) client, packet);
183 
184  if ((state_change == BFD_STATE_CHANGE_INVALID) || (state_change == BFD_STATE_CHANGE_ADMIN_DOWN)) return 0;
185 
186  if ((state_change == BFD_STATE_CHANGE_NONE) && inst->only_state_changes) return 0;
187 
188  wrapper->type = BFD_WRAPPER_RECV_PACKET;
189  wrapper->state_change = state_change;
190 
191  return sizeof(wrapper) + packet_len;
192 }
193 
194 static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, UNUSED fr_time_t request_time,
195  uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
196 {
197  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
198  fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
199  bfd_session_t *session;
200  ssize_t rcode;
201 #ifndef NDEBUG
202  char const *err;
203 #endif
204 
205  /*
206  * @todo - share a stats interface with the parent? or
207  * put the stats in the listener, so that proto_bfd
208  * can update them, too.. <sigh>
209  */
210  thread->stats.total_responses++;
211 
212  session = UNCONST(bfd_session_t *, track->address->radclient);
213 
214  fr_assert(buffer_len >= FR_BFD_HEADER_LENGTH);
215 
216  fr_assert(fr_bfd_packet_ok(&err, buffer, buffer_len));
217 
218  DEBUG("BFD %s peer %s sending %s",
219  session->server_name, session->client.shortname, fr_bfd_packet_names[session->session_state]);
220 
221  rcode = sendfromto(session->sockfd, buffer, buffer_len, 0, 0,
222  (struct sockaddr *) &session->local_sockaddr, session->local_salen,
223  (struct sockaddr *) &session->remote_sockaddr, session->remote_salen);
224  if (rcode < 0) {
225  ERROR("Failed sending packet: %s", fr_syserror(errno));
226  bfd_session_admin_down(session);
227  return 0;
228  }
229 
230  return rcode;
231 }
232 
233 static void mod_network_get(int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance)
234 {
235  proto_bfd_udp_t *inst = talloc_get_type_abort(instance, proto_bfd_udp_t);
236 
237  *ipproto = IPPROTO_UDP;
238  *dynamic_clients = inst->dynamic_clients;
239  *trie = inst->trie;
240 }
241 
242 /** Open a UDP listener for RADIUS
243  *
244  */
245 static int mod_open(fr_listen_t *li)
246 {
248  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
249 
250  int sockfd;
251  fr_ipaddr_t ipaddr = inst->ipaddr;
252  uint16_t port = inst->port;
253 
254  li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true);
255  if (sockfd < 0) {
256  PERROR("Failed opening UDP socket");
257  error:
258  return -1;
259  }
260 
261  li->app_io_addr = fr_socket_addr_alloc_inet_src(li, IPPROTO_UDP, 0, &inst->ipaddr, port);
262 
263  /*
264  * Set SO_REUSEPORT before bind, so that all packets can
265  * listen on the same destination IP address.
266  */
267  if (1) {
268  int on = 1;
269 
270  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
271  ERROR("Failed to set socket 'reuseport': %s", fr_syserror(errno));
272  return -1;
273  }
274  }
275 
276 #ifdef SO_RCVBUF
277  if (inst->recv_buff_is_set) {
278  int opt;
279 
280  opt = inst->recv_buff;
281  if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(int)) < 0) {
282  WARN("Failed setting 'recv_buf': %s", fr_syserror(errno));
283  }
284  }
285 #endif
286 
287 #ifdef SO_SNDBUF
288  if (inst->send_buff_is_set) {
289  int opt;
290 
291  opt = inst->send_buff;
292  if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(int)) < 0) {
293  WARN("Failed setting 'send_buf': %s", fr_syserror(errno));
294  }
295  }
296 #endif
297 
298 #ifdef IP_TTL
299  {
300  int opt;
301 
302  opt = inst->ttl;
303  if (setsockopt(sockfd, IPPROTO_IP, IP_TTL, &opt, sizeof(opt)) < 0) {
304  WARN("Failed setting 'ttl': %s", fr_syserror(errno));
305  }
306  }
307 #endif
308 
309  /*
310  * @todo - cache ifindex for use with udpfromto.
311  */
312  if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) {
313  close(sockfd);
314  PERROR("Failed binding socket");
315  goto error;
316  }
317 
318  thread->sockfd = sockfd;
319 
320  fr_assert((cf_parent(inst->cs) != NULL) && (cf_parent(cf_parent(inst->cs)) != NULL)); /* listen { ... } */
321 
322  thread->name = fr_app_io_socket_name(thread, &proto_bfd_udp,
323  NULL, 0,
324  &inst->ipaddr, inst->port,
325  inst->interface);
326 
327  return 0;
328 }
329 
330 /** Set the file descriptor for this socket.
331  *
332  */
333 static int mod_fd_set(fr_listen_t *li, int fd)
334 {
336  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
337 
338  thread->sockfd = fd;
339 
340  thread->name = fr_app_io_socket_name(thread, &proto_bfd_udp,
341  &thread->connection->socket.inet.src_ipaddr, thread->connection->socket.inet.src_port,
342  &inst->ipaddr, inst->port,
343  inst->interface);
344 
345  return 0;
346 }
347 
348 static char const *mod_name(fr_listen_t *li)
349 {
350  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
351 
352  return thread->name;
353 }
354 
355 
356 static int mod_instantiate(module_inst_ctx_t const *mctx)
357 {
358  proto_bfd_udp_t *inst = talloc_get_type_abort(mctx->mi->data, proto_bfd_udp_t);
359  CONF_SECTION *conf = mctx->mi->conf;
360  size_t num;
361  CONF_ITEM *ci;
362  CONF_SECTION *server_cs;
364  bfd_session_t *peer;
365 
366  inst->cs = conf;
367 
368  /*
369  * Complain if no "ipaddr" is set.
370  */
371  if (inst->ipaddr.af == AF_UNSPEC) {
372  cf_log_err(conf, "No 'ipaddr' was specified in the 'udp' section");
373  return -1;
374  }
375 
376  if (inst->recv_buff_is_set) {
377  FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, >=, 32);
378  FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, <=, INT_MAX);
379  }
380 
381  if (inst->send_buff_is_set) {
382  FR_INTEGER_BOUND_CHECK("send_buff", inst->send_buff, >=, 256);
383  FR_INTEGER_BOUND_CHECK("send_buff", inst->send_buff, <=, (1 << 30));
384  }
385 
386  FR_INTEGER_BOUND_CHECK("ttl", inst->ttl, >=, 64);
387 
388  if (!inst->port) {
389  struct servent *s;
390 
391  if (!inst->port_name) {
392  cf_log_err(conf, "No 'port' was specified in the 'udp' section");
393  return -1;
394  }
395 
396  s = getservbyname(inst->port_name, "udp");
397  if (!s) {
398  cf_log_err(conf, "Unknown value for 'port_name = %s", inst->port_name);
399  return -1;
400  }
401 
402  inst->port = ntohl(s->s_port);
403  }
404 
405  /*
406  * Parse and create the trie for dynamic clients, even if
407  * there's no dynamic clients.
408  */
409  num = talloc_array_length(inst->allow);
410  if (!num) {
411  if (inst->dynamic_clients) {
412  cf_log_err(conf, "The 'allow' subsection MUST contain at least one 'network' entry when 'dynamic_clients = true'.");
413  return -1;
414  }
415  } else {
416  inst->trie = fr_master_io_network(inst, inst->ipaddr.af, inst->allow, inst->deny);
417  if (!inst->trie) {
418  cf_log_perr(conf, "Failed creating list of networks");
419  return -1;
420  }
421  }
422 
423  ci = cf_section_to_item(mctx->mi->parent->conf); /* listen { ... } */
424  fr_assert(ci != NULL);
425  ci = cf_parent(ci);
426  fr_assert(ci != NULL);
427 
428  server_cs = cf_item_to_section(ci);
429  inst->server_name = cf_section_name2(server_cs);
430 
431  /*
432  * Look up peer list.
433  */
434  inst->peers = cf_data_value(cf_data_find(server_cs, fr_rb_tree_t, "peers"));
435  if (!inst->peers) {
436  cf_log_err(conf, "Failed finding peer list");
437  return -1;
438  }
439 
440  /*
441  * Walk over the list of peers, associating them with this listener.
442  */
443  for (peer = fr_rb_iter_init_inorder(&iter, inst->peers);
444  peer != NULL;
445  peer = fr_rb_iter_next_inorder(&iter)) {
446  if (peer->client.ipaddr.af != inst->ipaddr.af) continue;
447 
448  if (peer->inst) continue;
449 
450  /*
451  * unspecified src_ipaddr is us, OR our address
452  * matches.
453  */
454  if (!(fr_ipaddr_is_inaddr_any(&peer->client.src_ipaddr) ||
455  (fr_ipaddr_cmp(&peer->client.src_ipaddr, &inst->ipaddr) == 0))) continue;
456 
457  peer->inst = inst;
458  peer->client.src_ipaddr = inst->ipaddr; /* override inaddr_any */
459 
460  /*
461  * Cache these so that they don't get recalculated on every packet.
462  */
463  fr_ipaddr_to_sockaddr(&peer->remote_sockaddr, &peer->remote_salen, &peer->client.ipaddr, peer->port);
464  fr_ipaddr_to_sockaddr(&peer->local_sockaddr, &peer->local_salen, &inst->ipaddr, inst->port);
465 
466  if (bfd_session_init(peer) < 0) {
467  return -1;
468  }
469  }
470 
471  return 0;
472 }
473 
475 {
477 
478  if (ipproto != IPPROTO_UDP) return NULL;
479 
480  return fr_rb_find(inst->peers, &(fr_client_t) { .ipaddr = *ipaddr, .proto = IPPROTO_UDP });
481 }
482 
483 /** Set the event list for a new socket
484  *
485  * @param[in] li the listener
486  * @param[in] el the event list
487  * @param[in] nr context from the network side
488  */
489 static void mod_event_list_set(fr_listen_t *li, fr_event_list_t *el, void *nr)
490 {
492  proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
494  bfd_session_t *peer;
495 
496  /*
497  * Walk over the list of peers, associating them with this listener.
498  */
499  for (peer = fr_rb_iter_init_inorder(&iter, inst->peers);
500  peer != NULL;
501  peer = fr_rb_iter_next_inorder(&iter)) {
502  if (peer->inst != inst) continue;
503 
504  peer->el = el;
505  peer->listen = li;
506  peer->nr = (fr_network_t *) nr;
507  peer->sockfd = thread->sockfd;
508  peer->server_name = inst->server_name;
509  peer->only_state_changes = inst->only_state_changes;
510 
511  bfd_session_start(peer);
512  }
513 }
514 
515 
517  .common = {
518  .magic = MODULE_MAGIC_INIT,
519  .name = "bfd_udp",
520  .config = udp_listen_config,
521  .inst_size = sizeof(proto_bfd_udp_t),
522  .thread_inst_size = sizeof(proto_bfd_udp_thread_t),
523  .instantiate = mod_instantiate
524  },
525  .default_message_size = FR_BFD_HEADER_LENGTH + 64, /* enough for some auth packets */
526  .track_duplicates = false,
527 
528  .open = mod_open,
529  .read = mod_read,
530  .write = mod_write,
531  .fd_set = mod_fd_set,
532  .network_get = mod_network_get,
533  .event_list_set = mod_event_list_set,
534  .client_find = mod_client_find,
535  .get_name = mod_name,
536 };
static int const char char buffer[256]
Definition: acutest.h:574
char const * fr_app_io_socket_name(TALLOC_CTX *ctx, fr_app_io_t const *app_io, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port, char const *interface)
Definition: app_io.c:32
module_t common
Common fields to all loadable modules.
Definition: app_io.h:34
Public structure describing an I/O path for a protocol.
Definition: app_io.h:33
#define FR_BFD_HEADER_LENGTH
Definition: bfd.h:141
#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:627
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition: cf_parse.h:487
#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_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition: cf_parse.h:310
#define FR_CONF_OFFSET_IS_SET(_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:282
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition: cf_parse.h:419
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition: cf_parse.h:399
#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:564
Common header for all CONF_* types.
Definition: cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition: cf_util.c:738
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1185
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition: cf_util.c:1763
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition: cf_util.c:684
#define cf_log_err(_cf, _fmt,...)
Definition: cf_util.h:289
#define cf_data_find(_cf, _type, _name)
Definition: cf_util.h:244
#define cf_parent(_cf)
Definition: cf_util.h:101
#define cf_log_perr(_cf, _fmt,...)
Definition: cf_util.h:296
fr_dcursor_iter_t iter
Definition: dcursor.h:147
#define ERROR(fmt,...)
Definition: dhcpclient.c:41
static int sockfd
Definition: dhcpclient.c:56
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
static fr_slen_t err
Definition: dict.h:821
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition: inet.c:62
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition: inet.c:1392
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition: inet.c:1346
int af
Address family.
Definition: inet.h:64
IPv4/6 prefix.
Definition: merged_model.c:272
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_socket_t * app_io_addr
for tracking duplicate sockets
Definition: listen.h:35
void const * app_io_instance
I/O path configuration context.
Definition: listen.h:32
void * thread_instance
thread / socket context
Definition: listen.h:33
int fd
file descriptor for this socket - set by open
Definition: listen.h:28
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition: client.h:83
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
Definition: client.h:84
char const * shortname
Client nickname.
Definition: client.h:88
Describes a host allowed to send packets to the server.
Definition: client.h:80
#define PERROR(_fmt,...)
Definition: log.h:228
#define PDEBUG2(_fmt,...)
Definition: log.h:272
Stores all information relating to an event list.
Definition: event.c:411
ssize_t udp_recv(int sockfd, int flags, fr_socket_t *socket_out, void *data, size_t data_len, fr_time_t *when)
Read a UDP packet.
Definition: udp.c:145
void bfd_session_start(bfd_session_t *session)
Definition: session.c:1087
int bfd_session_init(bfd_session_t *session)
Definition: session.c:1063
bfd_state_change_t bfd_session_process(bfd_session_t *session, bfd_packet_t *bfd)
Definition: session.c:150
void bfd_session_admin_down(bfd_session_t *session)
Definition: session.c:75
socklen_t local_salen
Definition: session.h:52
int sockfd
cached for laziness
Definition: session.h:44
struct sockaddr_storage remote_sockaddr
cached for laziness
Definition: session.h:48
bfd_state_change_t
Definition: session.h:131
@ BFD_STATE_CHANGE_INVALID
Definition: session.h:132
@ BFD_STATE_CHANGE_ADMIN_DOWN
we are admin-down
Definition: session.h:134
@ BFD_STATE_CHANGE_NONE
no state change
Definition: session.h:133
fr_listen_t * listen
associated listener
Definition: session.h:42
socklen_t remote_salen
Definition: session.h:49
bfd_session_state_t session_state
our view of the session state
Definition: session.h:63
@ BFD_WRAPPER_RECV_PACKET
Definition: session.h:126
fr_client_t client
might as well reuse this, others need it
Definition: session.h:29
char const * server_name
our name
Definition: session.h:33
bool only_state_changes
copied from proto_bfd_udp.c
Definition: session.h:35
uint8_t packet[]
Definition: session.h:145
uint16_t port
peer port where packets are sent to
Definition: session.h:31
void * inst
proto_bfd_udp instance using this session
Definition: session.h:41
fr_network_t * nr
network side of things
Definition: session.h:46
bfd_state_change_t state_change
Definition: session.h:143
struct sockaddr_storage local_sockaddr
cached for laziness
Definition: session.h:51
fr_event_list_t * el
event list
Definition: session.h:45
uint32_t type
Definition: session.h:142
fr_trie_t * fr_master_io_network(TALLOC_CTX *ctx, int af, fr_ipaddr_t *allow, fr_ipaddr_t *deny)
Create a trie from arrays of allow / deny IP addresses.
Definition: master.c:2752
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition: master.h:54
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
Definition: merged_model.c:92
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
Definition: merged_model.c:88
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
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
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
char const * port_name
Name of the port for getservent().
Definition: proto_bfd_udp.c:54
bool dynamic_clients
whether we have dynamic clients
Definition: proto_bfd_udp.c:67
bool only_state_changes
on read(), only send packets which signal a state change
Definition: proto_bfd_udp.c:63
static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
static fr_client_t * mod_client_find(fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto)
uint16_t port
Port to listen on.
Definition: proto_bfd_udp.c:59
fr_stats_t stats
statistics for this socket
Definition: proto_bfd_udp.c:43
char const * name
socket name
Definition: proto_bfd_udp.c:38
CONF_SECTION * cs
our configuration
Definition: proto_bfd_udp.c:48
char const * server_name
virtual server name
Definition: proto_bfd_udp.c:49
char const * interface
Interface to bind to.
Definition: proto_bfd_udp.c:53
static void mod_event_list_set(fr_listen_t *li, fr_event_list_t *el, void *nr)
Set the event list for a new socket.
fr_io_address_t * connection
for connected sockets.
Definition: proto_bfd_udp.c:41
static int mod_open(fr_listen_t *li)
Open a UDP listener for RADIUS.
static const conf_parser_t udp_listen_config[]
Definition: proto_bfd_udp.c:85
bool send_buff_is_set
Whether we were provided with a send_buff.
Definition: proto_bfd_udp.c:66
static void mod_network_get(int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance)
static char const * mod_name(fr_listen_t *li)
static const conf_parser_t networks_config[]
Definition: proto_bfd_udp.c:77
fr_rb_tree_t * peers
our peers
Definition: proto_bfd_udp.c:69
bool recv_buff_is_set
Whether we were provided with a recv_buff.
Definition: proto_bfd_udp.c:65
uint32_t recv_buff
How big the kernel's receive buffer should be.
Definition: proto_bfd_udp.c:56
fr_ipaddr_t * allow
allowed networks for dynamic clients
Definition: proto_bfd_udp.c:72
fr_ipaddr_t ipaddr
IP address to listen on.
Definition: proto_bfd_udp.c:51
uint32_t send_buff
How big the kernel's send buffer should be.
Definition: proto_bfd_udp.c:57
fr_trie_t * trie
for parsed networks
Definition: proto_bfd_udp.c:71
static int mod_fd_set(fr_listen_t *li, int fd)
Set the file descriptor for this socket.
static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_app_io_t proto_bfd_udp
uint8_t ttl
default ttl
Definition: proto_bfd_udp.c:61
fr_ipaddr_t * deny
denied networks for dynamic clients
Definition: proto_bfd_udp.c:73
char const * fr_bfd_packet_names[FR_BFD_CODE_MAX]
Definition: base.c:63
bool fr_bfd_packet_ok(char const **err, uint8_t const *packet, size_t packet_len)
Definition: base.c:83
static int ipproto
Definition: radclient-ng.c:92
#define DEBUG2(fmt,...)
Definition: radclient.h:43
#define WARN(fmt,...)
Definition: radclient.h:47
static rs_t * conf
Definition: radsniff.c:53
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition: rb.c:850
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
Definition: rb.c:824
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Iterator structure for in-order traversal of an rbtree.
Definition: rb.h:321
The main red black tree structure.
Definition: rb.h:73
CONF_SECTION * conf
Module's instance configuration.
Definition: module.h:329
void * data
Module's instance data.
Definition: module.h:271
module_instance_t const * parent
Parent module's instance (if any).
Definition: module.h:337
fr_uint_t total_responses
Definition: stats.h:45
fr_uint_t total_packets_dropped
Definition: stats.h:51
fr_uint_t total_malformed_requests
Definition: stats.h:49
fr_uint_t total_requests
Definition: stats.h:42
int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 unconnected UDP socket.
Definition: socket.c:867
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition: socket.c:229
fr_assert(0)
eap_aka_sim_process_conf_t * inst
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
#define talloc_get_type_abort_const
Definition: talloc.h:282
"server local" time.
Definition: time.h:69
#define UDP_FLAGS_CONNECTED
Definition: udp.h:38
close(uq->fd)
int sendfromto(int fd, void *buf, size_t len, int flags, int ifindex, struct sockaddr *from, socklen_t from_len, struct sockaddr *to, socklen_t to_len)
Send packet via a file descriptor, setting the src address and outbound interface.
Definition: udpfromto.c:391
static fr_event_list_t * el
static fr_socket_t * fr_socket_addr_alloc_inet_src(TALLOC_CTX *ctx, int proto, int ifindex, fr_ipaddr_t const *ipaddr, int port)
A variant of fr_socket_addr_init_inet_src will also allocates a fr_socket_t.
Definition: socket.h:244
#define fr_box_ipaddr(_val)
Definition: value.h:294