The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
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: 05d21569fdc5b79feeb02269f1cf847ed062ecdd $
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/util/udp.h>
26#include <freeradius-devel/util/trie.h>
27#include <freeradius-devel/bfd/bfd.h>
28#include <freeradius-devel/io/application.h>
29#include <freeradius-devel/io/listen.h>
30#include <freeradius-devel/io/schedule.h>
31
32#include "session.h"
33
35
36typedef struct {
37 char const *name; //!< socket name
38 int sockfd;
39
40 fr_io_address_t *connection; //!< for connected sockets.
41
42 fr_stats_t stats; //!< statistics for this socket
43
45
46typedef struct {
47 CONF_SECTION *cs; //!< our configuration
48 char const *server_name; //!< virtual server name
49
50 fr_ipaddr_t ipaddr; //!< IP address to listen on.
51
52 char const *interface; //!< Interface to bind to.
53 char const *port_name; //!< Name of the port for getservent().
54
55 uint32_t recv_buff; //!< How big the kernel's receive buffer should be.
56 uint32_t send_buff; //!< How big the kernel's send buffer should be.
57
58 uint16_t port; //!< Port to listen on.
59
60 uint8_t ttl; //!< default ttl
61
62 bool only_state_changes; //!< on read(), only send packets which signal a state change
63
64 bool recv_buff_is_set; //!< Whether we were provided with a recv_buff
65 bool send_buff_is_set; //!< Whether we were provided with a send_buff
66 bool dynamic_clients; //!< whether we have dynamic clients
67
68 fr_rb_tree_t *peers; //!< our peers
69
70 fr_trie_t *trie; //!< for parsed networks
71 fr_ipaddr_t *allow; //!< allowed networks for dynamic clients
72 fr_ipaddr_t *deny; //!< denied networks for dynamic clients
74
75
82
83
88
89 { FR_CONF_OFFSET("interface", proto_bfd_udp_t, interface) },
90 { FR_CONF_OFFSET("port_name", proto_bfd_udp_t, port_name) },
91
92 { FR_CONF_OFFSET("port", proto_bfd_udp_t, port) },
93
94 { FR_CONF_OFFSET("ttl", proto_bfd_udp_t, ttl), .dflt = "255" },
95
96 { FR_CONF_OFFSET("only_state_changes", proto_bfd_udp_t, only_state_changes), .dflt = "yes" },
97
98 { FR_CONF_OFFSET_IS_SET("recv_buff", FR_TYPE_UINT32, 0, proto_bfd_udp_t, recv_buff) },
99 { FR_CONF_OFFSET_IS_SET("send_buff", FR_TYPE_UINT32, 0, proto_bfd_udp_t, send_buff) },
100
101// { FR_CONF_OFFSET("dynamic_clients", proto_bfd_udp_t, dynamic_clients) } ,
102 { FR_CONF_POINTER("networks", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) networks_config },
103
105};
106
107
109 size_t buffer_len, size_t *leftover)
110{
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 fr_rb_find((void **)&client, 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);
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
195 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
233static 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 */
246{
249 proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
250
251 int sockfd;
252 fr_ipaddr_t ipaddr = inst->ipaddr;
253 uint16_t port = inst->port;
254
255 li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true);
256 if (sockfd < 0) {
257 cf_log_err(li->listen->cs, "Failed opening UDP socket - %s", fr_strerror());
258 error:
259 return -1;
260 }
261
262 li->app_io_addr = fr_socket_addr_alloc_inet_src(li, IPPROTO_UDP, 0, &inst->ipaddr, port);
263
264 /*
265 * Set SO_REUSEPORT before bind, so that all packets can
266 * listen on the same destination IP address.
267 */
268 if (1) {
269 int on = 1;
270
271 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
272 cf_log_err(li->listen->cs, "Failed to set socket 'reuseport' - %s", fr_syserror(errno));
273 close(sockfd);
274 return -1;
275 }
276 }
277
278#ifdef SO_RCVBUF
279 if (inst->recv_buff_is_set) {
280 int opt;
281
282 opt = inst->recv_buff;
283 if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(int)) < 0) {
284 cf_log_warn(li->listen->cs, "Failed setting 'recv_buf' - %s", fr_syserror(errno));
285 }
286 }
287#endif
288
289#ifdef SO_SNDBUF
290 if (inst->send_buff_is_set) {
291 int opt;
292
293 opt = inst->send_buff;
294 if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(int)) < 0) {
295 cf_log_warn(li->listen->cs, "Failed setting 'send_buf' - %s", fr_syserror(errno));
296 }
297 }
298#endif
299
300#ifdef IP_TTL
301 {
302 int opt;
303
304 opt = inst->ttl;
305 if (setsockopt(sockfd, IPPROTO_IP, IP_TTL, &opt, sizeof(opt)) < 0) {
306 cf_log_warn(li->listen->cs, "Failed setting 'ttl' - %s", fr_syserror(errno));
307 }
308 }
309#endif
310
311 /*
312 * @todo - cache ifindex for use with udpfromto.
313 */
314 if (fr_socket_bind(sockfd, inst->interface, &ipaddr, &port) < 0) {
315 close(sockfd);
316 cf_log_err(li->listen->cs, "Failed binding socket - %s", fr_strerror());
317 cf_log_err(li->listen->cs, DOC_ROOT_REF(troubleshooting/network/bind));
318 goto error;
319 }
320
321 thread->sockfd = sockfd;
322
323 fr_assert((cf_parent(inst->cs) != NULL) && (cf_parent(cf_parent(inst->cs)) != NULL)); /* listen { ... } */
324
325 thread->name = fr_app_io_socket_name(thread, &proto_bfd_udp,
326 NULL, 0,
327 &inst->ipaddr, inst->port,
328 inst->interface);
329
330 return 0;
331}
332
333/** Set the file descriptor for this socket.
334 *
335 */
336static int mod_fd_set(fr_listen_instance_t *li, int fd)
337{
340 proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
341
342 thread->sockfd = fd;
343
344 thread->name = fr_app_io_socket_name(thread, &proto_bfd_udp,
345 &thread->connection->socket.inet.src_ipaddr, thread->connection->socket.inet.src_port,
346 &inst->ipaddr, inst->port,
347 inst->interface);
348
349 return 0;
350}
351
352static char const *mod_name(fr_listen_instance_t *li)
353{
354 proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
355
356 return thread->name;
357}
358
359
360static int mod_instantiate(module_inst_ctx_t const *mctx)
361{
362 proto_bfd_udp_t *inst = talloc_get_type_abort(mctx->mi->data, proto_bfd_udp_t);
363 CONF_SECTION *conf = mctx->mi->conf;
364 size_t num;
365 CONF_ITEM *ci;
366 CONF_SECTION *server_cs;
368 bfd_session_t *peer;
369
370 inst->cs = conf;
371
372 /*
373 * Complain if no "ipaddr" is set.
374 */
375 if (inst->ipaddr.af == AF_UNSPEC) {
376 cf_log_err(conf, "No 'ipaddr' was specified in the 'udp' section");
377 return -1;
378 }
379
380 if (inst->recv_buff_is_set) {
381 FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, >=, 32);
382 FR_INTEGER_BOUND_CHECK("recv_buff", inst->recv_buff, <=, INT_MAX);
383 }
384
385 if (inst->send_buff_is_set) {
386 FR_INTEGER_BOUND_CHECK("send_buff", inst->send_buff, >=, 256);
387 FR_INTEGER_BOUND_CHECK("send_buff", inst->send_buff, <=, (1 << 30));
388 }
389
390 FR_INTEGER_BOUND_CHECK("ttl", inst->ttl, >=, 64);
391
392 if (!inst->port) {
393 struct servent *s;
394
395 if (!inst->port_name) {
396 cf_log_err(conf, "No 'port' was specified in the 'udp' section");
397 return -1;
398 }
399
400 s = getservbyname(inst->port_name, "udp");
401 if (!s) {
402 cf_log_err(conf, "Unknown value for 'port_name = %s", inst->port_name);
403 return -1;
404 }
405
406 inst->port = ntohs(s->s_port);
407 }
408
409 /*
410 * Parse and create the trie for dynamic clients, even if
411 * there's no dynamic clients.
412 */
413 num = talloc_array_length(inst->allow);
414 if (!num) {
415 if (inst->dynamic_clients) {
416 cf_log_err(conf, "The 'allow' subsection MUST contain at least one 'network' entry when 'dynamic_clients = true'.");
417 return -1;
418 }
419 } else {
420 inst->trie = fr_master_io_network(inst, inst->ipaddr.af, inst->allow, inst->deny);
421 if (!inst->trie) {
422 cf_log_perr(conf, "Failed creating list of networks");
423 return -1;
424 }
425 }
426
427 ci = cf_section_to_item(mctx->mi->parent->conf); /* listen { ... } */
428 fr_assert(ci != NULL);
429 ci = cf_parent(ci);
430 fr_assert(ci != NULL);
431
432 server_cs = cf_item_to_section(ci);
433 inst->server_name = cf_section_name2(server_cs);
434
435 /*
436 * Look up peer list.
437 */
438 inst->peers = cf_data_value(cf_data_find(server_cs, fr_rb_tree_t, "peers"));
439 if (!inst->peers) {
440 cf_log_err(conf, "Failed finding peer list");
441 return -1;
442 }
443
444 /*
445 * Walk over the list of peers, associating them with this listener.
446 */
447 for (peer = fr_rb_iter_init_inorder(inst->peers, &iter);
448 peer != NULL;
449 peer = fr_rb_iter_next_inorder(inst->peers, &iter)) {
450 if (peer->client.ipaddr.af != inst->ipaddr.af) continue;
451
452 if (peer->inst) continue;
453
454 /*
455 * unspecified src_ipaddr is us, OR our address
456 * matches.
457 */
459 (fr_ipaddr_cmp(&peer->client.src_ipaddr, &inst->ipaddr) == 0))) continue;
460
461 peer->inst = inst;
462 peer->client.src_ipaddr = inst->ipaddr; /* override inaddr_any */
463
464 /*
465 * Cache these so that they don't get recalculated on every packet.
466 */
468 fr_ipaddr_to_sockaddr(&peer->local_sockaddr, &peer->local_salen, &inst->ipaddr, inst->port);
469
470 if (bfd_session_init(peer) < 0) {
471 return -1;
472 }
473 }
474
475 return 0;
476}
477
479{
481 fr_client_t *client;
482
483 if (ipproto != IPPROTO_UDP) return NULL;
484
485 fr_rb_find((void **)&client, inst->peers, &(fr_client_t) { .ipaddr = *ipaddr, .proto = IPPROTO_UDP });
486
487 return client;
488}
489
490/** Set the event list for a new socket
491 *
492 * @param[in] li the listener
493 * @param[in] el the event list
494 * @param[in] nr context from the network side
495 */
497{
499 proto_bfd_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_bfd_udp_thread_t);
501 bfd_session_t *peer;
502
503 /*
504 * Walk over the list of peers, associating them with this listener.
505 */
506 for (peer = fr_rb_iter_init_inorder(inst->peers, &iter);
507 peer != NULL;
508 peer = fr_rb_iter_next_inorder(inst->peers, &iter)) {
509 if (peer->inst != inst) continue;
510
511 peer->el = el;
512 peer->listen = li;
513 peer->nr = (fr_network_t *) nr;
514 peer->sockfd = thread->sockfd;
515 peer->server_name = inst->server_name;
516 peer->only_state_changes = inst->only_state_changes;
517
518 bfd_session_start(peer);
519 }
520}
521
522
524 .common = {
525 .magic = MODULE_MAGIC_INIT,
526 .name = "bfd_udp",
528 .inst_size = sizeof(proto_bfd_udp_t),
529 .thread_inst_size = sizeof(proto_bfd_udp_thread_t),
530 .instantiate = mod_instantiate
531 },
532 .default_message_size = FR_BFD_HEADER_LENGTH + 64, /* enough for some auth packets */
533 .track_duplicates = false,
534
535 .open = mod_open,
536 .read = mod_read,
537 .write = mod_write,
538 .fd_set = mod_fd_set,
539 .network_get = mod_network_get,
540 .event_list_set = mod_event_list_set,
541 .client_find = mod_client_find,
542 .get_name = mod_name,
543};
static int const char char buffer[256]
Definition acutest.h:641
char const * fr_app_io_socket_name(TALLOC_CTX *ctx, fr_app_io_t const *app_io, fr_ipaddr_t const *src_ipaddr, uint16_t src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t 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
static int packet_ctx
the tests pass only the address of packet_ctx
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define UNUSED
Definition build.h:415
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:722
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:572
#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:280
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Definition cf_parse.h:483
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:460
#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:350
#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:294
#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:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
Common header for all CONF_* types.
Definition cf_priv.h:54
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1405
void * cf_data_value(CONF_DATA const *cd)
Return the user assigned value of CONF_DATA.
Definition cf_util.c:1922
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:725
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:671
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_data_find(_cf, _type, _name)
Definition cf_util.h:295
#define cf_parent(_cf)
Definition cf_util.h:115
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:341
#define ERROR(fmt,...)
Definition dhcpclient.c:40
static int sockfd
Definition dhcpclient.c:55
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
#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:1399
fr_cmp_ret_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
Definition inet.c:1353
int af
Address family.
Definition inet.h:64
IPv4/6 prefix.
fr_socket_t socket
src/dst ip and port.
Definition base.h:342
fr_client_t const * radclient
old-style client definition
Definition base.h:344
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 PDEBUG2(_fmt,...)
Definition log.h:277
uint64_t total_responses
Definition stats.h:38
uint64_t total_requests
Definition stats.h:35
uint64_t total_packets_dropped
Definition stats.h:44
uint64_t total_malformed_requests
Definition stats.h:42
Stores all information relating to an event list.
Definition event.c:375
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:144
void bfd_session_start(bfd_session_t *session)
Definition session.c:1101
int bfd_session_init(bfd_session_t *session)
Definition session.c:1077
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
fr_listen_instance_t * listen
associated listener
Definition session.h:42
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
socklen_t remote_salen
Definition session.h:49
bfd_session_state_t session_state
our view of the session state
Definition session.h:63
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
@ BFD_WRAPPER_RECV_PACKET
Definition session.h:126
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_listen_t * listen
the listener this is a socket of.
Definition listen.h:65
int fd
file descriptor for this socket - set by open
Definition listen.h:67
void const * app_io_instance
I/O path configuration context.
Definition listen.h:34
CONF_SECTION * cs
of this listener
Definition listen.h:39
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition listen.h:71
void * thread_instance
thread / socket context
Definition listen.h:69
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:3221
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition master.h:55
unsigned short uint16_t
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
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().
static fr_client_t * mod_client_find(fr_listen_instance_t *li, fr_ipaddr_t const *ipaddr, int ipproto)
bool dynamic_clients
whether we have dynamic clients
bool only_state_changes
on read(), only send packets which signal a state change
uint16_t port
Port to listen on.
fr_stats_t stats
statistics for this socket
char const * name
socket name
CONF_SECTION * cs
our configuration
static int mod_open(fr_listen_instance_t *li)
Open a UDP listener for RADIUS.
char const * server_name
virtual server name
char const * interface
Interface to bind to.
fr_io_address_t * connection
for connected sockets.
static const conf_parser_t udp_listen_config[]
bool send_buff_is_set
Whether we were provided with a send_buff.
static void mod_network_get(int *ipproto, bool *dynamic_clients, fr_trie_t const **trie, void *instance)
static ssize_t mod_read(fr_listen_instance_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
static void mod_event_list_set(fr_listen_instance_t *li, fr_event_list_t *el, void *nr)
Set the event list for a new socket.
static const conf_parser_t networks_config[]
fr_rb_tree_t * peers
our peers
static int mod_fd_set(fr_listen_instance_t *li, int fd)
Set the file descriptor for this socket.
bool recv_buff_is_set
Whether we were provided with a recv_buff.
static char const * mod_name(fr_listen_instance_t *li)
uint32_t recv_buff
How big the kernel's receive buffer should be.
static ssize_t mod_write(fr_listen_instance_t *li, void *packet_ctx, UNUSED fr_time_t request_time, uint8_t *buffer, size_t buffer_len, UNUSED size_t written)
fr_ipaddr_t * allow
allowed networks for dynamic clients
fr_ipaddr_t ipaddr
IP address to listen on.
uint32_t send_buff
How big the kernel's send buffer should be.
fr_trie_t * trie
for parsed networks
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_app_io_t proto_bfd_udp
uint8_t ttl
default ttl
fr_ipaddr_t * deny
denied networks for dynamic clients
char const * fr_bfd_packet_names[FR_BFD_CODE_MAX]
Definition base.c:64
bool fr_bfd_packet_ok(char const **err, uint8_t const *packet, size_t packet_len)
Definition base.c:84
#define fr_assert(_expr)
Definition rad_assert.h:37
#define DEBUG2(fmt,...)
static int ipproto
Definition radclient.c:91
static rs_t * conf
Definition radsniff.c:52
int fr_rb_find(void **found, fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:586
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
Definition rb.c:850
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:876
Iterator structure for in-order traversal of an rbtree.
Definition rb.h:319
The main red black tree structure.
Definition rb.h:71
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:355
void * data
Module's instance data.
Definition module.h:297
module_instance_t const * parent
Parent module's instance (if any).
Definition module.h:363
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:207
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:841
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:200
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:117
"server local" time.
Definition time.h:69
#define UDP_FLAGS_CONNECTED
Definition udp.h:38
ssize_t 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:421
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:249
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:558
#define DOC_ROOT_REF(_x)
Definition version.h:90
#define fr_box_ipaddr(_val)
Definition value.h:348