The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 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
37typedef 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
47typedef 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
83
84
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
109static 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);
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
194static 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
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 */
245static 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 */
333static 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
348static 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
356static 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 */
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 */
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 */
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",
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:576
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:167
#define UNUSED
Definition build.h:315
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:502
#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:323
#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:432
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
#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:579
Common header for all CONF_* types.
Definition cf_priv.h:49
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
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_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
Definition cf_util.c:738
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
#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:824
#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.
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:2767
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition master.h:54
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().
bool dynamic_clients
whether we have dynamic clients
bool only_state_changes
on read(), only send packets which signal a state change
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)
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
char const * server_name
virtual server name
char const * interface
Interface to bind to.
static fr_client_t * mod_client_find(fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto)
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.
static int mod_open(fr_listen_t *li)
Open a UDP listener for RADIUS.
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 const conf_parser_t networks_config[]
fr_rb_tree_t * peers
our peers
bool recv_buff_is_set
Whether we were provided with a recv_buff.
uint32_t recv_buff
How big the kernel's receive buffer should be.
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_fd_set(fr_listen_t *li, int fd)
Set the file descriptor for this socket.
static char const * mod_name(fr_listen_t *li)
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
fr_ipaddr_t * deny
denied networks for dynamic clients
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
#define fr_assert(_expr)
Definition rad_assert.h:38
static int ipproto
#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_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_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
Definition rb.c:850
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
Definition rb.c:577
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
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
Definition module.h:198
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
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
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