The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
master.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: 2b925809abfd9102c6076124555139817e49e530 $
19 * @file io/master.c
20 * @brief Master IO handler
21 *
22 * @copyright 2018 Alan DeKok (aland@freeradius.org)
23 */
24#include <freeradius-devel/io/listen.h>
25#include <freeradius-devel/io/master.h>
26
27
28#include <freeradius-devel/util/debug.h>
29
30#include <freeradius-devel/util/syserror.h>
31
32typedef struct {
33 fr_event_list_t *el; //!< event list, for the master socket.
34 fr_network_t *nr; //!< network for the master socket
35
36 fr_trie_t *trie; //!< trie of clients
37 fr_heap_t *pending_clients; //!< heap of pending clients
38 fr_heap_t *alive_clients; //!< heap of active dynamic clients
39
40 fr_listen_t *listen; //!< The master IO path
41 fr_listen_t *child; //!< The child (app_io) IO path
42 fr_schedule_t *sc; //!< the scheduler
43
44 // @todo - count num_nak_clients, and num_nak_connections, too
45 uint32_t num_connections; //!< number of dynamic connections
46 uint32_t num_pending_packets; //!< number of pending packets
47 uint64_t client_id; //!< Unique client identifier.
48
49 struct {
50 fr_rate_limit_t accept_failed;
51 fr_rate_limit_t alloc_failed;
52 fr_rate_limit_t bad_type;
53 fr_rate_limit_t conn_alloc_failed;
54 fr_rate_limit_t max_connections;
55 fr_rate_limit_t queue_full;
56 fr_rate_limit_t repeat_nak;
57 fr_rate_limit_t too_many_pending;
58 fr_rate_limit_t tracking_failed;
59 fr_rate_limit_t unknown_client;
60 } rate_limit;
62
63/** A saved packet
64 *
65 */
74
75
76/** Client states
77 *
78 */
79typedef enum {
81 PR_CLIENT_STATIC, //!< static / global clients
82 PR_CLIENT_NAK, //!< negative cache entry
83 PR_CLIENT_DYNAMIC, //!< dynamically defined client
84 PR_CLIENT_CONNECTED, //!< dynamically defined client in a connected socket
85 PR_CLIENT_PENDING, //!< dynamic client pending definition
87
88/*
89 * Dynamic clients are run through the normal src/process/foo state machine.
90 *
91 * request->async->packet_ctx is an fr_io_track_t
92 *
93 * track->dynamic is set to a non-zero value.
94 *
95 * The dynamic client code returns a buffer of 1 byte for a NAK.
96 *
97 * If the client creation is successful, then it does talloc(NULL, fr_client_t),
98 * fills out the structure, and sends the pointer in the buffer (8 bytes).
99 *
100 * This code will take over ownership of the structure, and
101 * create the dynamic client.
102 */
103
105
106/** Client definitions for master IO
107 *
108 */
110 fr_io_connection_t *connection; //!< parent connection
111 fr_io_client_state_t state; //!< state of this client
112 fr_ipaddr_t src_ipaddr; //!< packets come from this address
113 fr_ipaddr_t network; //!< network for dynamic clients
114 fr_client_t *radclient; //!< old-style definition of this client
115
116 int packets; //!< number of packets using this client
117 fr_heap_index_t pending_id; //!< for pending clients
118 fr_heap_index_t alive_id; //!< for all clients
119
120 bool use_connected; //!< does this client allow connected sub-sockets?
121 bool ready_to_delete; //!< are we ready to delete this client?
122 bool in_trie; //!< is the client in the trie?
123
124 fr_io_instance_t const *inst; //!< parent instance for master IO handler
126 fr_timer_t *ev; //!< when we clean up the client
127 fr_rb_tree_t *table; //!< tracking table for packets
128
129 fr_heap_t *pending; //!< pending packets for this client
130 fr_hash_table_t *addresses; //!< list of src/dst addresses used by this client
131
132 pthread_mutex_t mutex; //!< for parent / child signaling
133 fr_hash_table_t *ht; //!< for tracking connected sockets
134};
135
136/** Track a connection
137 *
138 * This structure contains information about the connection,
139 * a pointer to the library instance so that we can clean up on exit,
140 * and the listener.
141 *
142 * It also points to a client structure which is for this connection,
143 * and only this connection.
144 *
145 * Finally, a pointer to the parent client, so that the child can
146 * tell the parent it's alive, and the parent can push packets to the
147 * child.
148 */
150 char const *name; //!< taken from proto_FOO_TRANSPORT
151 int packets; //!< number of packets using this connection
152 fr_io_address_t *address; //!< full information about the connection.
153 fr_listen_t *listen; //!< master listener for this socket
154 fr_listen_t *child; //!< child listener (app_io) for this socket
155 fr_io_client_t *client; //!< our local client (pending or connected).
156 fr_io_client_t *parent; //!< points to the parent client.
157 module_instance_t *mi; //!< for submodule
158
159 bool dead; //!< roundabout way to get the network side to close a socket
160 bool paused; //!< event filter doesn't like resuming something that isn't paused
161 bool in_parent_hash; //!< for tracking thread issues
162 fr_event_list_t *el; //!< event list for this connection
163 fr_network_t *nr; //!< network for this connection
164};
165
168 { 0 }
169};
170
173 { 0 }
174};
175
176static int track_free(fr_io_track_t *track)
177{
178 FR_TIMER_DELETE_RETURN(&track->ev);
179 talloc_free_children(track);
180
181 fr_assert(track->client->packets > 0);
182 track->client->packets--;
183
184 return 0;
185}
186
188{
189 void *found;
190
191 fr_assert(track->client->table != NULL);
192
193 /*
194 * If the tree is being freed, then we don't try to remove ourselves from it. Doing so would
195 * free this node, and therefore corrupt the tree.
196 *
197 * The talloc code will take care of cleaning up the children and events when this chunk is
198 * freed.
199 */
200 if (track->client->table->being_freed) return 0;
201
202 fr_rb_find(&found, track->client->table, track);
203 fr_assert(found != NULL);
204
205 if (fr_rb_delete(track->client->table, track) != 0) {
206 fr_assert(0);
207 }
208
209 return track_free(track);
210}
211
212/*
213 * Return negative numbers to put 'one' at the top of the heap.
214 * Return positive numbers to put 'two' at the top of the heap.
215 */
216static fr_cmp_ret_t pending_packet_cmp(void const *one, void const *two)
217{
220 int ret;
221
222 /*
223 * Higher priority elements are larger than lower
224 * priority elements. So if "a" is larger than "b", we
225 * wish to prefer "a".
226 */
227 ret = CMP_PREFER_LARGER(a->priority, b->priority);
228 if (ret != 0) return ret;
229
230 /*
231 * Smaller numbers mean packets were received earlier.
232 * We want to process packets in time order. So if "a"
233 * is smaller than "b", we wish to prefer "a".
234 *
235 * After that, it doesn't really matter what order the
236 * packets go in. Since we'll never have two identical
237 * "recv_time" values, the code should never get here.
238 */
240}
241
242/*
243 * Order clients in the pending_clients heap, based on the
244 * packets that they contain.
245 */
246static fr_cmp_ret_t pending_client_cmp(void const *one, void const *two)
247{
248 fr_io_pending_packet_t const *a;
249 fr_io_pending_packet_t const *b;
250
253
254 a = fr_heap_peek(c1->pending);
255 b = fr_heap_peek(c2->pending);
256
257 fr_assert(a != NULL);
258 fr_assert(b != NULL);
259
260 return pending_packet_cmp(a, b);
261}
262
263
264static fr_cmp_ret_t address_cmp(void const *one, void const *two)
265{
268 fr_cmp_ret_t ret;
269
270 CMP_RETURN(a, b, socket.inet.src_port);
271 CMP_RETURN(a, b, socket.inet.dst_port);
272 CMP_RETURN(a, b, socket.inet.ifindex);
273
274 ret = fr_ipaddr_cmp(&a->socket.inet.src_ipaddr, &b->socket.inet.src_ipaddr);
275 if (ret != 0) return ret;
276
277 return fr_ipaddr_cmp(&a->socket.inet.dst_ipaddr, &b->socket.inet.dst_ipaddr);
278}
279
280static uint32_t connection_hash(void const *ctx)
281{
284
285 hash = fr_hash(&c->address->socket.inet.src_ipaddr, sizeof(c->address->socket.inet.src_ipaddr));
286 hash = fr_hash_update(&c->address->socket.inet.src_port, sizeof(c->address->socket.inet.src_port), hash);
287
288 hash = fr_hash_update(&c->address->socket.inet.ifindex, sizeof(c->address->socket.inet.ifindex), hash);
289
290 hash = fr_hash_update(&c->address->socket.inet.dst_ipaddr, sizeof(c->address->socket.inet.dst_ipaddr), hash);
291 return fr_hash_update(&c->address->socket.inet.dst_port, sizeof(c->address->socket.inet.dst_port), hash);
292}
293
294static fr_cmp_ret_t connection_cmp(void const *one, void const *two)
295{
298
299 return address_cmp(a->address, b->address);
300}
301
302
303static fr_cmp_ret_t track_cmp(void const *one, void const *two)
304{
307 int ret;
308
309 fr_assert(a->client != NULL);
310 fr_assert(b->client != NULL);
311 fr_assert(a->client == b->client); /* tables are per-client */
312
315
316 /*
317 * Unconnected sockets must check src/dst ip/port.
318 */
319 ret = address_cmp(a->address, b->address);
320 if (ret != 0) return ret;
321
322 /*
323 * Call the per-protocol comparison function.
324 */
327 a->client->radclient,
328 a->packet, b->packet);
329 return CMP(ret, 0);
330}
331
332
333static fr_cmp_ret_t track_connected_cmp(void const *one, void const *two)
334{
337 int ret;
338
339 fr_assert(a->client != NULL);
340 fr_assert(b->client != NULL);
341
344 fr_assert(a->client == b->client);
346
347 /*
348 * Note that we pass the connection "client", as
349 * we may do negotiation specific to this connection.
350 */
354 a->packet, b->packet);
355 return CMP(ret, 0);
356}
357
358
360{
361 fr_io_client_t *client;
362 fr_io_pending_packet_t *pending;
363
364 fr_heap_pop((void **)&client, &thread->pending_clients);
365 if (!client) {
366 fr_assert(thread->num_pending_packets == 0);
367
368 /*
369 * 99% of the time we don't have pending clients.
370 * So we might as well free this, so that the
371 * caller doesn't keep checking us for every packet.
372 */
374 thread->pending_clients = NULL;
375 return NULL;
376 }
377
378 fr_heap_pop((void **)&pending, &client->pending);
379 fr_assert(pending != NULL);
380
381 /*
382 * If the client has more packets pending, add it back to
383 * the heap.
384 */
385 if (fr_heap_num_elements(client->pending) > 0) {
386 if (fr_heap_insert(&thread->pending_clients, client) < 0) {
387 fr_assert(0 == 1);
388 }
389 }
390
391 fr_assert(thread->num_pending_packets > 0);
392 thread->num_pending_packets--;
393
394 return pending;
395}
396
397static fr_client_t *radclient_clone(TALLOC_CTX *ctx, fr_client_t const *parent)
398{
399 fr_client_t *c;
400
401 if (!parent) return NULL;
402
403 c = talloc_zero(ctx, fr_client_t);
404 if (!c) return NULL;
405
406 /*
407 * Do NOT set ipaddr or src_ipaddr. The caller MUST do this!
408 */
409
410#define DUP_FIELD(_x) do { if (parent->_x) {c->_x = talloc_strdup(c, parent->_x); if (!c->_x) {goto error;}}} while (0)
411#define COPY_FIELD(_x) c->_x = parent->_x
412
413 DUP_FIELD(longname);
414 DUP_FIELD(shortname);
416 DUP_FIELD(nas_type);
417 DUP_FIELD(server);
418
419 COPY_FIELD(require_message_authenticator);
420 COPY_FIELD(require_message_authenticator_is_set);
421#ifdef NAS_VIOLATES_RFC
422 COPY_FIELD(allow_vulnerable_clients);
423#endif
424 COPY_FIELD(limit_proxy_state);
425 COPY_FIELD(limit_proxy_state_is_set);
426 /* dynamic MUST be false */
427 COPY_FIELD(server_cs);
428 COPY_FIELD(cs);
429 COPY_FIELD(proto);
430 COPY_FIELD(active);
431
432 COPY_FIELD(use_connected);
433
434#ifdef WITH_TLS
435 COPY_FIELD(tls_required);
436#endif
437
438 c->ipaddr = parent->ipaddr;
439 c->src_ipaddr = parent->src_ipaddr;
440
441 return c;
442
443 /*
444 * @todo - fill in other fields, too!
445 */
446
447error:
448 talloc_free(c);
449 return NULL;
450}
451#undef COPY_FIELD
452#undef DUP_FIELD
453
454
455/** Count the number of connections used by active clients.
456 *
457 * Unfortunately, we also count NAK'd connections, too, even if they
458 * are closed. The alternative is to walk through all connections
459 * for each client, which would be a long time.
460 */
461static int count_connections(UNUSED uint8_t const *key, UNUSED size_t keylen, void *data, void *ctx)
462{
463 fr_io_client_t *client = talloc_get_type_abort(data, fr_io_client_t);
464 int connections;
465
466 pthread_mutex_lock(&client->mutex);
467
468 if (!client->ht) {
469 pthread_mutex_unlock(&client->mutex);
470 return 0;
471 }
472
473 connections = fr_hash_table_num_elements(client->ht);
474 pthread_mutex_unlock(&client->mutex);
475
476 /*
477 * Don't check "use_connected". Pending dynamic clients get an entry in the connection tracking
478 * table before the client is defined, and therefore before "use_connected" is set. As a result,
479 * we can't check the value of "use_connected" until much later.
480 */
481
482 *((uint32_t *) ctx) += connections;
483
484 return 0;
485}
486
487
488static int _client_free(fr_io_client_t *client)
489{
490 /*
491 * The mutex is initialized whenever the connection tracking table is created, which can happen
492 * for pending clients which do not (yet) have "use_connected" set. Since the mutex creation is
493 * conditional on the existence of the connection tracking table, we make the mutex deletion
494 * conditional on the existence of the tracking table.
495 */
496 if (client->ht) (void) pthread_mutex_destroy(&client->mutex);
497
498 TALLOC_FREE(client->pending);
499
500 return 0;
501}
502
504{
505 size_t num;
506
507 fr_assert(!client->connection);
508
509 if (!client->pending) return;
510
511 num = fr_heap_num_elements(client->pending);
512
513 fr_assert(client->thread->num_pending_packets >= num);
514 client->thread->num_pending_packets -= num;
515
516 TALLOC_FREE(client->pending);
517}
518
519
520static int connection_free(fr_io_connection_t *connection)
521{
522 /*
523 * This is it's own talloc context, as there are
524 * thousands of packets associated with it.
525 */
526 TALLOC_FREE(connection->client);
527
528 return 0;
529}
530
531/** Create a new connection.
532 *
533 * Called ONLY from the master socket.
534 */
536 fr_io_thread_t *thread,
537 fr_io_client_t *client, int fd,
538 fr_io_address_t *address,
540{
541 int ret;
542 fr_io_connection_t *connection;
543 module_instance_t *mi = NULL;
544 fr_listen_t *li;
545 fr_client_t *radclient;
546
547
548 /*
549 * Reload the app_io module as a "new" library. This
550 * causes the link count for the library to be correct.
551 * It also allocates a new instance data for it, too.
552 * Passing CONF_SECTION of NULL ensures that there's no
553 * config for it, as we'll just clone it's contents from
554 * the original. It also means that detach should be
555 * called when the instance data is freed.
556 */
557 if (!nak) {
558 CONF_SECTION *cs;
559 char *inst_name;
560
561 if (inst->max_connections || client->radclient->limit.max_connections) {
562 uint32_t max_connections = inst->max_connections ? inst->max_connections : client->radclient->limit.max_connections;
563
564 /*
565 * We've hit the connection limit. Walk
566 * over all clients with connections, and
567 * count the number of connections used.
568 */
569 if (thread->num_connections >= max_connections) {
570 thread->num_connections = 0;
571
572 (void) fr_trie_walk(thread->trie, &thread->num_connections, count_connections);
573
574 if ((thread->num_connections + 1) >= max_connections) {
575 RATE_LIMIT_LOCAL(&thread->rate_limit.max_connections, INFO,
576 "proto_%s - Ignoring connection from client %s - 'max_connections' limit reached.",
577 inst->app->common.name, client->radclient->shortname);
578 if (fd >= 0) close(fd);
579 return NULL;
580 }
581 }
582 }
583
584 /*
585 * Add a client module into a sublist
586 */
587 inst_name = talloc_asprintf(NULL, "%"PRIu64, thread->client_id++);
588 mi = module_instance_copy(inst->clients, inst->submodule, inst_name);
589 talloc_free(inst_name);
590
591 cs = cf_section_dup(mi, NULL, inst->submodule->conf,
592 cf_section_name1(inst->submodule->conf),
593 cf_section_name2(inst->submodule->conf), false);
594
595 /*
596 * Clear the "dynamic_clients" flag, so that the child instantiate routines don't check
597 * the network allow / deny list when instantiating child connections.
598 *
599 * This is a short-term and minimal hack to get the problem fixed. A longer term
600 * solution would be to update fr_master_io_network() so that it sets caches the trie
601 * _and_ the dynamic client flag in connection data structure. Which then means that the
602 * mod_network_get() API could also go away.
603 *
604 * But doing that involves more rearchitecture and code changes, which we're avoiding at
605 * this time.
606 */
607 cf_pair_replace_or_add(cs, "dynamic_clients", "no");
608
609 if (module_instance_conf_parse(mi, cs) < 0) {
610 cf_log_err(inst->server_cs, "Failed parsing module config");
611 goto cleanup;
612 }
613
614 /* Thread local module lists never run bootstrap */
615 if (module_instantiate(mi) < 0) {
616 cf_log_err(inst->server_cs, "Failed instantiating module");
617 goto cleanup;
618 }
619
620 if (module_thread_instantiate(mi, mi, thread->el) < 0) {
621 cf_log_err(inst->server_cs, "Failed instantiating module");
622 goto cleanup;
623 }
624
625 /*
626 * FIXME - Instantiate the new module?!
627 */
628 fr_assert(mi != NULL);
629 } else {
630 mi = talloc_init_const("nak");
631 }
632
633 MEM(connection = talloc_zero(mi, fr_io_connection_t));
634 MEM(connection->address = talloc_memdup(connection, address, sizeof(*address)));
635 (void) talloc_set_name_const(connection->address, "fr_io_address_t");
636
637 connection->parent = client;
638 connection->mi = mi;
639
640 MEM(connection->client = talloc_named(NULL, sizeof(fr_io_client_t), "fr_io_client_t"));
641 memset(connection->client, 0, sizeof(*connection->client));
642
643 MEM(connection->client->radclient = radclient = radclient_clone(connection->client, client->radclient));
644
645 talloc_set_destructor(connection->client, _client_free);
646 talloc_set_destructor(connection, connection_free);
647
650 connection->client->connection = connection;
651
652 /*
653 * Create the packet tracking table for this client.
654 *
655 * #todo - unify the code with static clients?
656 */
657 if (inst->app_io->track_duplicates) {
658 MEM(connection->client->table = fr_rb_inline_talloc_alloc(client, fr_io_track_t, node,
659 track_connected_cmp, NULL));
660 }
661
662 /*
663 * Set this radclient to be dynamic, and active.
664 */
665 radclient->dynamic = true;
666 radclient->active = true;
667
668 /*
669 * address->socket.inet.client points to a "static" client. We want
670 * to clean up everything associated with the connection
671 * when it closes. So we need to point to our own copy
672 * of the client here.
673 */
674 connection->address->radclient = connection->client->radclient;
675 connection->client->inst = inst;
676 connection->client->thread = thread;
677
678 /*
679 * Create a heap for packets which are pending for this
680 * client.
681 */
682 MEM(connection->client->pending = fr_heap_alloc(connection->client, pending_packet_cmp,
683 fr_io_pending_packet_t, heap_id, 0));
684
685 /*
686 * Clients for connected sockets are always a /32 or /128.
687 */
688 connection->client->src_ipaddr = address->socket.inet.src_ipaddr;
689 connection->client->network = address->socket.inet.src_ipaddr;
690
691 /*
692 * Don't initialize mutex or hash table.
693 * Connections cannot spawn other connections.
694 */
695
696 /*
697 * If this client state is pending, then the connection
698 * state is pending, too. That allows NAT gateways to be
699 * defined dynamically, AND for them to have multiple
700 * connections, each with a different client. This
701 * allows for different shared secrets to be used for
702 * different connections. Once the client gets defined
703 * for this connection, it will be either "connected" or
704 * not. If connected, then the parent client remains
705 * PENDING. Otherwise, the parent client is moved to
706 * DYNAMIC
707 *
708 * If this client state is static or dynamic,
709 * then we're just using connected sockets behind
710 * that client. The connections here all use the
711 * same shared secret, but they use different
712 * sockets, so they allow for sharing of IO
713 * across CPUs / threads.
714 */
715 switch (client->state) {
717 connection->client->state = PR_CLIENT_PENDING;
718
719 /*
720 * Needed for rlm_radius, which refuses to proxy packets
721 * that define a dynamic client.
722 */
723 radclient->active = false;
724 break;
725
726 case PR_CLIENT_STATIC:
728 connection->client->state = PR_CLIENT_CONNECTED;
729 break;
730
732 case PR_CLIENT_NAK:
734 fr_assert(0 == 1);
735 goto cleanup;
736 }
737
738 if (!nak) {
739 /*
740 * Get the child listener.
741 */
742 MEM(li = connection->child = talloc(connection, fr_listen_t));
743 memcpy(li, thread->listen, sizeof(*li));
744
745 /*
746 * Glue in the actual app_io
747 */
748 li->connected = true;
749 li->app_io = thread->child->app_io;
750 li->cs = inst->app_io_conf;
751 li->thread_instance = connection;
752 li->app_io_instance = mi->data;
754
755 /*
756 * Create writable thread instance data.
757 */
758 connection->child->thread_instance = talloc_zero_array(NULL, uint8_t,
759 inst->app_io->common.thread_inst_size);
760 talloc_set_destructor(connection->child, fr_io_listen_free);
761 talloc_set_name(connection->child->thread_instance, "proto_%s_thread_t",
762 inst->app_io->common.name);
763
764 /*
765 * This is "const", and the user can't
766 * touch it. So we just reuse the same
767 * configuration everywhere.
768 */
769 connection->child->app_io_instance = inst->app_io_instance;
770
771 /*
772 * Create the listener, based on our listener.
773 */
774 MEM(li = connection->listen = talloc(connection, fr_listen_t));
775
776 /*
777 * Note that our instance is effectively 'const'.
778 *
779 * i.e. we can't add things to it. Instead, we have to
780 * put all variable data into the connection.
781 */
782 memcpy(li, thread->listen, sizeof(*li));
783
784 /*
785 * Glue in the connection to the listener.
786 */
788
789 li->connected = true;
790 li->thread_instance = connection;
791 li->cs = inst->app_io_conf;
794
795 /*
796 * Instantiate the child, and open the socket.
797 */
798 fr_assert(inst->app_io->connection_set != NULL);
799
800 if (inst->app_io->connection_set(connection->child, connection->address) < 0) {
801 DEBUG("proto_%s - Failed setting connection for socket.", inst->app->common.name);
802 goto cleanup;
803 }
804
805 /*
806 * UDP sockets: open a new socket, and then
807 * connect it to the client. This emulates the
808 * behavior of accept().
809 *
810 * Note that there is a small window between the
811 * bind() and connect() where UDP packets for the
812 * wildcard socket can get received by this
813 * socket. We hope that this time frame is as
814 * small as possible.
815 *
816 * i.e. we ignore the problem, and don't
817 * currently check dst ip/port for UDP packets
818 * received on connected sockets.
819 */
820 if (fd < 0) {
821 socklen_t salen;
822 struct sockaddr_storage src;
823
824 if (fr_ipaddr_to_sockaddr(&src, &salen,
825 &connection->address->socket.inet.src_ipaddr,
826 connection->address->socket.inet.src_port) < 0) {
827 DEBUG("proto_%s - Failed getting IP address", inst->app->common.name);
828 talloc_free(mi);
829 return NULL;
830 }
831
832 if (inst->app_io->open(connection->child) < 0) {
833 DEBUG("proto_%s - Failed opening connected socket.", inst->app->common.name);
834 talloc_free(mi);
835 return NULL;
836 }
837
838 fd = connection->child->fd;
839
840 if (connect(fd, (struct sockaddr *) &src, salen) < 0) {
841 ERROR("proto_%s - Failed in connect: %s", inst->app->common.name, fr_syserror(errno));
842 goto cleanup;
843 }
844 } else {
845 connection->child->fd = fd;
846 }
847
848 /*
849 * Set the new FD, and get the module to set it's connection name.
850 */
851 if (inst->app_io->fd_set(connection->child, fd) < 0) {
852 DEBUG3("Failed setting FD to %s", inst->app_io->common.name);
853 goto cleanup;
854 }
855
856 li->fd = fd;
857
858 if (!inst->app_io->get_name) {
859 connection->name = fr_asprintf(connection, "proto_%s from client %pV port "
860 "%u to server %pV port %u",
861 inst->app->common.name,
862 fr_box_ipaddr(connection->address->socket.inet.src_ipaddr),
863 connection->address->socket.inet.src_port,
864 fr_box_ipaddr(connection->address->socket.inet.dst_ipaddr),
865 connection->address->socket.inet.dst_port);
866 } else {
867 connection->name = inst->app_io->get_name(connection->child);
868 }
869
870 /*
871 * Set the names for the listeners.
872 */
873 connection->listen->name = connection->name;
874 connection->child->name = connection->name;
875 }
876
877 /*
878 * If the parent client is still PENDING, lazily create the hash table that tracks its child
879 * connections. We need this so that fr_io_connection_allow() can later find any sibling
880 * connections, and add them to the scheduler once the dynamic client is defined.
881 */
882 if ((client->state == PR_CLIENT_PENDING) && !client->ht) {
883 (void) pthread_mutex_init(&client->mutex, NULL);
884 MEM(client->ht = fr_hash_table_alloc(client, connection_hash, connection_cmp, NULL));
885 }
886
887 /*
888 * Add the connection to the set of connections for this client. Capture the pre-insert size so
889 * we can tell whether this is the first connection (which runs the dynamic-client verification)
890 * or a later connection (which is deferred until the first connection is verified).
891 */
892 pthread_mutex_lock(&client->mutex);
893 if (client->ht) {
894 size_t pre_size = fr_hash_table_num_elements(client->ht);
895
896 if (nak) (void) fr_hash_table_delete(client->ht, nak);
897 ret = fr_hash_table_insert(client->ht, connection);
898 client->ready_to_delete = false;
899 connection->in_parent_hash = true;
900
901 if (ret != 0) {
902 pthread_mutex_unlock(&client->mutex);
903 ERROR("proto_%s - Failed inserting connection into tracking table. "
904 "Closing it, and discarding all packets for connection %s.",
905 inst->app_io->common.name, connection->name);
906 goto cleanup;
907 }
908
909 /*
910 * The first connection for a PENDING parent runs the dynamic client definition. All
911 * later connections will be scheduled by fr_io_connection_allow(), once the parent is
912 * defined (or not). nak placeholders are never scheduled, so they don't count.
913 */
914 if (!nak && (client->state == PR_CLIENT_PENDING) && (pre_size > 0)) {
915 pthread_mutex_unlock(&client->mutex);
916 DEBUG("proto_%s - deferring scheduling of connection %s until parent client %pV is defined",
917 inst->app_io->common.name, connection->name, fr_box_ipaddr(client->src_ipaddr));
918 thread->num_connections++;
919 return connection;
920 }
921 }
922 pthread_mutex_unlock(&client->mutex);
923
924 /*
925 * It's a NAK client. Set the state to NAK, and don't
926 * add it to the scheduler.
927 */
928 if (nak) {
929 INFO("proto_%s - Verification failed for packet from dynamic client %pV - adding IP address to the NAK cache",
930 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
931
932 connection->name = talloc_strdup(connection, nak->name);
933 connection->client->state = PR_CLIENT_NAK;
934 connection->el = nak->el;
935 return connection;
936 }
937
938 DEBUG("proto_%s - starting connection %s", inst->app_io->common.name, connection->name);
939 connection->nr = fr_schedule_listen_add(thread->sc, connection->listen);
940 if (!connection->nr) {
941 ERROR("proto_%s - Failed inserting connection into scheduler. "
942 "Closing it, and diuscarding all packets for connection %s.",
943 inst->app_io->common.name, connection->name);
944 pthread_mutex_lock(&client->mutex);
945 if (client->ht) (void) fr_hash_table_delete(client->ht, connection);
946 pthread_mutex_unlock(&client->mutex);
947
948 cleanup:
949 if (fd >= 0) close(fd);
950 talloc_free(mi);
951 return NULL;
952 }
953
954 /*
955 * We have one more connection. Note that we do
956 * NOT decrement this counter when a connection
957 * closes, as the close is done in a child
958 * thread. Instead, we just let counter hit the
959 * limit, and then walk over the clients to reset
960 * the count.
961 */
962 thread->num_connections++;
963
964 return connection;
965}
966
967
968/*
969 * And here we go into the rabbit hole...
970 *
971 * @todo future - have a similar structure
972 * fr_io_connection_io, which will duplicate some code,
973 * but may make things simpler?
974 */
975static void get_inst(fr_listen_t *li, fr_io_instance_t const **inst, fr_io_thread_t **thread,
976 fr_io_connection_t **connection, fr_listen_t **child)
977{
978 if (!li->connected) {
979 *inst = li->app_io_instance;
980 if (thread) *thread = li->thread_instance;
981 *connection = NULL;
982 if (child) *child = ((fr_io_thread_t *)li->thread_instance)->child;
983
984 } else {
985 fr_assert(connection != NULL);
986
987 *connection = li->thread_instance;
988 *inst = (*connection)->client->inst;
989 if (thread) *thread = NULL;
990 if (child) *child = (*connection)->child;
991 }
992}
993
994
995static fr_client_t *radclient_alloc(TALLOC_CTX *ctx, int ipproto, fr_io_address_t *address)
996{
997 fr_client_t *radclient;
998 char *shortname;
999
1000 MEM(radclient = talloc_zero(ctx, fr_client_t));
1001
1002 fr_value_box_aprint(radclient, &shortname, fr_box_ipaddr(address->socket.inet.src_ipaddr), NULL);
1003 radclient->longname = radclient->shortname = shortname;
1004
1005 radclient->secret = radclient->nas_type = talloc_strdup(radclient, "");
1006
1007 radclient->ipaddr = address->socket.inet.src_ipaddr;
1008
1009 radclient->src_ipaddr = address->socket.inet.dst_ipaddr;
1010
1011 radclient->proto = ipproto;
1012 radclient->dynamic = true;
1013
1014 return radclient;
1015}
1016
1017/*
1018 * Remove a client from the list of "live" clients.
1019 *
1020 * This function is only used for the "main" socket. Clients
1021 * from connections do not use it.
1022 */
1024{
1025 talloc_get_type_abort(client, fr_io_client_t);
1026
1027 fr_assert(client->in_trie);
1028 fr_assert(!client->connection);
1029 fr_assert(client->thread);
1030
1031 if (client->pending) client_pending_free(client);
1032
1033 (void) fr_trie_remove_by_key(client->thread->trie, &client->src_ipaddr.addr, client->src_ipaddr.prefix);
1034
1035 if (client->thread->alive_clients) {
1037 (void) fr_heap_extract(&client->thread->alive_clients, client);
1038 }
1039
1040 /*
1041 * The mutex/ht pair is initialized either for use_connected
1042 * clients (in client_alloc) or for PENDING clients with
1043 * deferred sibling connections (in fr_io_connection_alloc).
1044 * The ht pointer is the canonical signal that the mutex
1045 * was initialized.
1046 */
1047 if (client->ht) (void) pthread_mutex_destroy(&client->mutex);
1048
1049 return 0;
1050}
1051
1052/** Allocate a dynamic client.
1053 *
1054 */
1056 fr_io_instance_t const *inst, fr_io_thread_t *thread, fr_client_t *radclient,
1057 fr_ipaddr_t const *network)
1058{
1059 fr_io_client_t *client;
1060
1061 /*
1062 * Create our own local client. This client
1063 * holds our state which really shouldn't go into
1064 * fr_client_t.
1065 *
1066 * Note that we create a new top-level talloc
1067 * context for this client, as there may be tens
1068 * of thousands of packets associated with this
1069 * client. And we want to avoid problems with
1070 * O(N) issues in talloc.
1071 */
1072 MEM(client = talloc_named(ctx, sizeof(fr_io_client_t), "fr_io_client_t"));
1073 memset(client, 0, sizeof(*client));
1074
1075 client->state = state;
1076 client->src_ipaddr = radclient->ipaddr;
1077 client->radclient = radclient;
1078 client->inst = inst;
1079 client->thread = thread;
1080
1081 if (network) {
1082 client->network = *network;
1083 } else {
1084 client->network = client->src_ipaddr;
1085 }
1086
1087 /*
1088 * At this point, this variable can only be true
1089 * for STATIC clients. PENDING clients may set
1090 * it to true later, after they've been defined.
1091 */
1092 client->use_connected = radclient->use_connected;
1093
1094 /*
1095 * Create the pending heap for pending clients.
1096 */
1097 if (state == PR_CLIENT_PENDING) {
1098 MEM(client->pending = fr_heap_alloc(client, pending_packet_cmp,
1099 fr_io_pending_packet_t, heap_id, 0));
1100 }
1101
1102 /*
1103 * Create the packet tracking table for this client.
1104 */
1105 if (inst->app_io->track_duplicates) {
1106 fr_assert(inst->app_io->track_compare != NULL);
1107 MEM(client->table = fr_rb_inline_talloc_alloc(client, fr_io_track_t, node, track_cmp, NULL));
1108 }
1109
1110 /*
1111 * Allow connected sockets to be set on a
1112 * per-client basis.
1113 */
1114 if (client->use_connected) {
1115 fr_assert(client->state == PR_CLIENT_STATIC);
1116
1117 (void) pthread_mutex_init(&client->mutex, NULL);
1118 MEM(client->ht = fr_hash_table_alloc(client, connection_hash, connection_cmp, NULL));
1119 }
1120
1121 /*
1122 * Add the newly defined client to the trie of
1123 * allowed clients.
1124 */
1125 if (fr_trie_insert_by_key(thread->trie, &client->src_ipaddr.addr, client->src_ipaddr.prefix, client)) {
1126 ERROR("proto_%s - Failed inserting client %s into tracking table. Discarding client, and all packets for it.",
1127 inst->app_io->common.name, client->radclient->shortname);
1128 if (client->ht) (void) pthread_mutex_destroy(&client->mutex);
1129 talloc_free(client);
1130 return NULL;
1131 }
1132
1133 client->in_trie = true;
1134
1135 /*
1136 * It's a static client. Don't insert it into the list of alive clients, as those are only for
1137 * dynamic clients.
1138 */
1139 if (state == PR_CLIENT_STATIC) return client;
1140
1141 fr_assert(thread->alive_clients != NULL);
1142
1143 /*
1144 * Track the live clients so that we can clean
1145 * them up.
1146 */
1147 (void) fr_heap_insert(&thread->alive_clients, client);
1149
1150 /*
1151 * Now that we've inserted it into the heap and
1152 * incremented the numbers, set the destructor
1153 * function.
1154 */
1155 talloc_set_destructor(client, _client_live_free);
1156
1157 return client;
1158}
1159
1160
1162 fr_io_address_t *address,
1163 uint8_t const *packet, size_t packet_len,
1164 fr_time_t recv_time, bool *is_dup)
1165{
1166 size_t len;
1167 fr_io_track_t *track, *old;
1168 TALLOC_CTX *track_ctx = client->inst->app_io->track_duplicates ? (TALLOC_CTX *)client->table : (TALLOC_CTX *)client;
1169
1170 *is_dup = false;
1171
1172 /*
1173 * Allocate a new tracking structure. Most of the time
1174 * there are no duplicates, so this is fine.
1175 */
1176 if (client->connection) {
1177 MEM(track = talloc_zero_pooled_object(track_ctx, fr_io_track_t, 1, sizeof(*track) + 64));
1178 track->address = client->connection->address;
1179 } else {
1180 fr_io_address_t *my_address;
1181
1182 MEM(track = talloc_zero_pooled_object(track_ctx, fr_io_track_t, 1, sizeof(*track) + sizeof(*track->address) + 64));
1183 MEM(track->address = my_address = talloc(track, fr_io_address_t));
1184
1185 *my_address = *address;
1186 my_address->radclient = client->radclient;
1187 }
1188
1189 track->li = li;
1190 track->client = client;
1191
1192 track->timestamp = recv_time;
1193 track->packets = 1;
1194
1195 /*
1196 * We're not tracking duplicates, so just return the
1197 * tracking entry. This tracks src/dst IP/port, client,
1198 * receive time, etc.
1199 */
1200 if (!client->inst->app_io->track_duplicates) {
1201 client->packets++;
1202 talloc_set_destructor(track, track_free);
1203 return track;
1204 }
1205
1206 /*
1207 * We are checking for duplicates, see if there is a dup
1208 * already in the tree.
1209 */
1210 track->packet = client->inst->app_io->track_create(client->inst->app_io_instance,
1211 client->thread->child->thread_instance,
1212 client->radclient,
1213 track, packet, packet_len);
1214 if (!track->packet) {
1215 talloc_free(track);
1216 return NULL;
1217 }
1218
1219 /*
1220 * No existing duplicate. Return the new tracking entry.
1221 */
1222 fr_rb_find((void **)&old, client->table, track);
1223 if (!old) goto do_insert;
1224
1225 fr_assert(old->client == client);
1226
1227 /*
1228 * It cannot be both in the free list and in the tracking table.
1229 *
1230 * 2020-08-17, this assertion fails randomly in travis.
1231 * Which means that "track" was in the free list, *and*
1232 * in the rbtree.
1233 */
1234 fr_assert(old != track);
1235
1236 /*
1237 * The new packet has the same dedup fields as the old
1238 * one, BUT it may be a conflicting packet. Check for
1239 * that via a simple memcmp().
1240 *
1241 * It's an exact duplicate. Drop the new one and
1242 * use the old one.
1243 *
1244 * If there's a cached reply, the caller will take care
1245 * of sending it to the network layer.
1246 */
1247 len = talloc_array_length(old->packet);
1248 if ((len == talloc_array_length(track->packet)) &&
1249 (memcmp(old->packet, track->packet, len) == 0)) {
1250 fr_assert(old != track);
1251
1252 /*
1253 * Ignore duplicates while the client is
1254 * still pending.
1255 */
1256 if (client->state == PR_CLIENT_PENDING) {
1257 DEBUG("Ignoring duplicate packet while client %s is still pending dynamic definition",
1258 client->radclient->shortname);
1259 talloc_free(track);
1260 return NULL;
1261 }
1262
1263 *is_dup = true;
1264 old->packets++;
1265 talloc_free(track);
1266
1267 /*
1268 * Retransmits can sit in the outbound queue for
1269 * a while. We don't want to time out this
1270 * struct while the packet is in the outbound
1271 * queue.
1272 */
1273 FR_TIMER_DISARM(old->ev);
1274 return old;
1275 }
1276
1277 /*
1278 * Else it's a conflicting packet. Which is OK if we
1279 * already have a reply. We just delete the old entry,
1280 * and insert the new one.
1281 *
1282 * If there's no reply, then the old request is still
1283 * "live". Delete the old one from the tracking tree,
1284 * and return the new one.
1285 */
1286 if (old->reply_len || old->do_not_respond) {
1287 talloc_free(old);
1288
1289 } else {
1290 fr_assert(client == old->client);
1291
1292 if (fr_rb_delete(client->table, old) != 0) {
1293 fr_assert(0);
1294 }
1295 FR_TIMER_DELETE(&old->ev);
1296
1297 talloc_set_destructor(old, track_free);
1298
1299 old->discard = true; /* don't send any reply, there's nowhere for it to go */
1300 }
1301
1302do_insert:
1303 if (fr_rb_insert(client->table, track) != 0) {
1304 fr_assert(0);
1305 }
1306
1307 client->packets++;
1308 talloc_set_destructor(track, track_dedup_free);
1309 return track;
1310}
1311
1312
1314{
1315 fr_io_track_t *track = pending->track;
1316
1317 /*
1318 * Note that we don't check timestamps, replies, etc. If
1319 * a packet is pending, then any conflicting packet gets
1320 * the "pending" entry marked as such, and a new entry
1321 * added. Any duplicate packet gets suppressed. And
1322 * because the packets are pending, track->reply MUST be
1323 * NULL.
1324 */
1325 fr_assert(track->packets > 0);
1326 track->packets--;
1327
1328 /*
1329 * No more packets using this tracking entry,
1330 * delete it.
1331 */
1332 if (track->packets == 0) talloc_free(track);
1333
1334 return 0;
1335}
1336
1338 uint8_t const *buffer, size_t packet_len,
1339 fr_io_track_t *track,
1340 int priority)
1341{
1342 fr_io_pending_packet_t *pending;
1343
1344 MEM(pending = talloc_zero(client->pending, fr_io_pending_packet_t));
1345
1346 MEM(pending->buffer = talloc_memdup(pending, buffer, packet_len));
1347 pending->buffer_len = packet_len;
1348 pending->priority = priority;
1349 pending->track = track;
1350 pending->recv_time = track->timestamp; /* there can only be one */
1351
1352 talloc_set_destructor(pending, pending_free);
1353
1354 /*
1355 * Insert the pending packet for this client. If it
1356 * fails, silently discard the packet.
1357 */
1358 if (fr_heap_insert(&client->pending, pending) < 0) {
1359 talloc_free(pending);
1360 return NULL;
1361 }
1362
1363 /*
1364 * We only track pending packets for the
1365 * main socket. For connected sockets,
1366 * we pause the FD, so the number of
1367 * pending packets will always be small.
1368 */
1369 if (!connection) client->thread->num_pending_packets++;
1370
1371 return pending;
1372}
1373
1374
1375/*
1376 * Order clients in the alive_clients heap, based on their IP
1377 * address.
1378 *
1379 * This function is only used for the "main" socket. Clients
1380 * from connections do not use it.
1381 */
1382static fr_cmp_ret_t alive_client_cmp(void const *one, void const *two)
1383{
1386
1387 return fr_ipaddr_cmp(&a->src_ipaddr, &b->src_ipaddr);
1388}
1389
1390/** Implement 99% of the read routines.
1391 *
1392 * The app_io->read does the transport-specific data read.
1393 */
1394static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p,
1395 uint8_t *buffer, size_t buffer_len, size_t *leftover)
1396{
1397 fr_io_instance_t const *inst;
1398 fr_io_thread_t *thread;
1399 ssize_t packet_len = -1;
1400 fr_time_t recv_time = fr_time_wrap(0);
1401 fr_io_client_t *client;
1402 fr_io_address_t address;
1403 fr_io_connection_t my_connection, *connection;
1404 fr_io_pending_packet_t *pending = NULL;
1405 fr_io_track_t *track;
1406 fr_listen_t *child;
1407 int value, accept_fd = -1;
1408 uint32_t priority = PRIORITY_NORMAL;
1409
1410/** Log that we ignore clients in debug mode, or when it's enabled for a listener
1411 */
1412#define LOG_IGNORED_CLIENTS(_inst) ((_inst)->log_ignored_clients || fr_debug_lvl >= 1)
1413
1414 get_inst(li, &inst, &thread, &connection, &child);
1415
1416 track = NULL;
1417
1418 /*
1419 * There was data left over from the previous read, go
1420 * get the rest of it now. We MUST do this instead of
1421 * popping a pending packet, because the leftover bytes
1422 * are already in the output buffer.
1423 */
1424 if (*leftover) goto do_read;
1425
1426redo:
1427 /*
1428 * Read one pending packet. The packet may be pending
1429 * because of dynamic client definitions, or because it's
1430 * for a connected UDP socket, and was sent over by the
1431 * "master" UDP socket.
1432 */
1433 if (connection) {
1434 /*
1435 * The connection is dead. Tell the network side
1436 * to close it.
1437 */
1438 if (connection->dead) {
1439 DEBUG("Dead connection %s", connection->name);
1440 return -1;
1441 }
1442
1443 fr_heap_pop((void **)&pending, &connection->client->pending);
1444
1445 } else if (thread->pending_clients) {
1446 pending = pending_packet_pop(thread);
1447
1448 } else {
1449 pending = NULL;
1450 }
1451
1452 if (pending) {
1453 fr_assert(buffer_len >= pending->buffer_len);
1454 track = pending->track;
1455
1456 /*
1457 * Clear the destructor as we now own the
1458 * tracking entry.
1459 */
1460 talloc_set_destructor(pending, NULL);
1461
1462 /*
1463 * We received a conflicting packet while this
1464 * packet was pending. Discard this entry and
1465 * try to get another one.
1466 *
1467 * Note that the pending heap is *simple*. We
1468 * just track priority and recv_time. This means
1469 * it's fast, but also that it's hard to look up
1470 * random packets in the pending heap.
1471 */
1472 if (fr_time_neq(pending->recv_time, track->timestamp)) {
1473 DEBUG3("Discarding old packet");
1474 TALLOC_FREE(pending);
1475 goto redo;
1476 }
1477
1478 /*
1479 * We have a valid packet. Copy it over to the
1480 * caller, and return.
1481 */
1482 *packet_ctx = track;
1483 *leftover = 0;
1484 recv_time = *recv_time_p = pending->recv_time;
1485 client = track->client;
1486
1487 memcpy(buffer, pending->buffer, pending->buffer_len);
1488 packet_len = pending->buffer_len;
1489
1490 /*
1491 * Shouldn't be necessary, but what the heck...
1492 */
1493 memcpy(&address, track->address, sizeof(address));
1494 TALLOC_FREE(pending);
1495
1496 /*
1497 * Skip over all kinds of logic to find /
1498 * allocate the client, when we don't need to do
1499 * it any more.
1500 */
1501 goto have_client;
1502
1503 } else if (!connection && (inst->ipproto == IPPROTO_TCP)) {
1504 struct sockaddr_storage saremote;
1505 socklen_t salen;
1506
1507 salen = sizeof(saremote);
1508
1509 /*
1510 * We're a TCP socket but are NOT connected. We
1511 * must be the master socket. Accept the new
1512 * connection, and figure out src/dst IP/port.
1513 */
1514 accept_fd = accept(child->fd,
1515 (struct sockaddr *) &saremote, &salen);
1516
1517 /*
1518 * Couldn't open a NEW socket, but THIS ONE is
1519 * OK. So don't return -1.
1520 */
1521 if (accept_fd < 0) {
1522 RATE_LIMIT_LOCAL(&thread->rate_limit.accept_failed,
1523 INFO, "proto_%s - failed to accept new socket: %s",
1524 inst->app->common.name, fr_syserror(errno));
1525 return 0;
1526 }
1527
1528 /*
1529 * Set the new descriptor to be non-blocking.
1530 */
1531 (void) fr_nonblock(accept_fd);
1532
1533#ifdef STATIC_ANALYZER
1534 saremote.ss_family = AF_INET; /* static analyzer doesn't know that accept() initializes this */
1535#endif
1536
1537 /*
1538 * Get IP addresses only if we have IP addresses.
1539 */
1540 if ((saremote.ss_family == AF_INET) || (saremote.ss_family == AF_INET6)) {
1541 memset(&address.socket, 0, sizeof(address.socket));
1542 (void) fr_ipaddr_from_sockaddr(&address.socket.inet.src_ipaddr, &address.socket.inet.src_port,
1543 &saremote, salen);
1544 salen = sizeof(saremote);
1545
1546 /*
1547 * @todo - only if the local listen address is "*".
1548 */
1549 (void) getsockname(accept_fd, (struct sockaddr *) &saremote, &salen);
1550 (void) fr_ipaddr_from_sockaddr(&address.socket.inet.dst_ipaddr, &address.socket.inet.dst_port,
1551 &saremote, salen);
1552 address.socket.type = (inst->ipproto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
1553 address.socket.fd = accept_fd;
1554 }
1555
1556 } else {
1557 fr_io_address_t *local_address;
1558
1559 /*
1560 * We're either not a TCP socket, or we are a
1561 * connected TCP socket. Just read it.
1562 */
1563do_read:
1564 local_address = &address;
1565
1566 /*
1567 * @todo - For connected TCP sockets which are
1568 * dynamically defined, the app_io read()
1569 * function should stop reading the socket if the
1570 * server is busy. That change puts TCP
1571 * backpressure on the client.
1572 *
1573 * @todo TLS - for TLS and dynamic sockets, do
1574 * the SSL setup here, but have a structure which
1575 * describes the TLS data and run THAT through
1576 * the dynamic client definition, instead of
1577 * using normal packets. Or, rely on the app_io
1578 * read() function to do all TLS work? Given
1579 * that some protocols have "starttls" beginning
1580 * after a clear-text exchange, it's likely best
1581 * to have yet another layer of trampoline
1582 * functions which do all of the TLS work.
1583 */
1584 packet_len = inst->app_io->read(child, (void **) &local_address, &recv_time,
1585 buffer, buffer_len, leftover);
1586 if (packet_len <= 0) {
1587 return packet_len;
1588 }
1589
1590 /*
1591 * Not allowed? Discard it. The priority()
1592 * function has done any complaining, if
1593 * necessary.
1594 */
1595 if (inst->app->priority) {
1596 value = inst->app->priority(inst->app_instance, buffer, packet_len);
1597 if (value <= 0) {
1598 static fr_rate_limit_t bad_type;
1599
1600 /*
1601 * @todo - unix sockets. We need to use
1602 * the "name" of the socket, in the
1603 * listener?
1604 */
1606 RATE_LIMIT_LOCAL(thread ? &thread->rate_limit.bad_type : &bad_type, INFO,
1607 "proto_%s - ignoring packet from IP %pV. It is not configured as 'type = ...'",
1608 inst->app_io->common.name, fr_box_ipaddr(address.socket.inet.src_ipaddr));
1609 }
1610 return 0;
1611 }
1612 priority = value;
1613 }
1614
1615 /*
1616 * If the connection is pending, pause reading of
1617 * more packets. If mod_write() accepts the
1618 * connection, it will resume reading.
1619 * Otherwise, it will close the socket without
1620 * resuming it.
1621 */
1622 if (connection &&
1623 (connection->client->state == PR_CLIENT_PENDING)) {
1624 fr_assert(!connection->paused);
1625
1626 connection->paused = true;
1627 (void) fr_event_filter_update(connection->el,
1628 child->fd,
1630 }
1631 }
1632
1633 /*
1634 * Look up the client, unless we already have one (for a
1635 * connected socket).
1636 */
1637 if (!connection) {
1638 client = fr_trie_lookup_by_key(thread->trie,
1639 &address.socket.inet.src_ipaddr.addr, address.socket.inet.src_ipaddr.prefix);
1640 fr_assert(!client || !client->connection);
1641
1642 /*
1643 * Verify the cached client is the most specific match.
1644 * A broader subnet may have been cached first, shadowing
1645 * a more specific client definition.
1646 */
1647 if (client && (client->state == PR_CLIENT_STATIC)) {
1648 fr_client_t *radclient;
1649
1650 radclient = inst->app_io->client_find(thread->child,
1651 &address.socket.inet.src_ipaddr, inst->ipproto);
1652 if (radclient && (radclient->ipaddr.prefix > client->src_ipaddr.prefix)) {
1653 client = NULL;
1654 }
1655 }
1656
1657 } else {
1658 client = connection->client;
1659
1660 /*
1661 * We don't care what the read function says
1662 * about address. We have it already.
1663 */
1664 address = *connection->address;
1665 }
1666
1667 /*
1668 * Negative cache entry. Drop the packet.
1669 */
1670 if (client && client->state == PR_CLIENT_NAK) {
1671 if (accept_fd >= 0) close(accept_fd);
1672 return 0;
1673 }
1674
1675 /*
1676 * If there's no client, try to pull one from the global
1677 * / static client list. Or if dynamic clients are
1678 * allowed, try to define a dynamic client.
1679 */
1680 if (!client) {
1681 fr_client_t *radclient = NULL;
1683 fr_ipaddr_t const *network = NULL;
1684 char const *error;
1685
1686 /*
1687 * We MUST be the master socket.
1688 */
1689 fr_assert(!connection);
1690
1691 radclient = inst->app_io->client_find(thread->child, &address.socket.inet.src_ipaddr, inst->ipproto);
1692 if (radclient) {
1694
1695 /*
1696 * Make our own copy that we can modify it.
1697 */
1698 MEM(radclient = radclient_clone(thread, radclient));
1699 radclient->active = true;
1700
1701 } else if (inst->dynamic_clients) {
1702 if (inst->max_clients && (fr_heap_num_elements(thread->alive_clients) >= inst->max_clients)) {
1703 error = "Too many dynamic clients have been defined";
1704 goto ignore;
1705 }
1706
1707 /*
1708 * Look up the allowed networks.
1709 */
1710 network = fr_trie_lookup_by_key(inst->networks, &address.socket.inet.src_ipaddr.addr,
1711 address.socket.inet.src_ipaddr.prefix);
1712 if (!network) {
1713 error = "Address is outside of the the 'allow' network range";
1714 goto ignore;
1715 }
1716
1717 /*
1718 * It exists, but it's a "deny" rule, ignore it.
1719 */
1720 if (network->af == AF_UNSPEC) {
1721 error = "Address is forbidden by the 'deny' network range";
1722 goto ignore;
1723 }
1724
1725 /*
1726 * Allocate our local radclient as a
1727 * placeholder for the dynamic client.
1728 */
1729 radclient = radclient_alloc(thread, inst->ipproto, &address);
1731
1732 } else {
1733 char const *msg;
1734
1735 error = "No matching 'client' definition was found";
1736
1737 ignore:
1738 if (accept_fd < 0) {
1739 msg = "packet";
1740 } else {
1741 msg = "connection attempt";
1742 close(accept_fd);
1743 }
1744
1746 static fr_rate_limit_t unknown_client;
1747 RATE_LIMIT_LOCAL(thread ? &thread->rate_limit.unknown_client : &unknown_client,
1748 ERROR, "proto_%s - Ignoring %s from IP address %pV - %s",
1749 inst->app_io->common.name, msg, fr_box_ipaddr(address.socket.inet.src_ipaddr),
1750 error);
1751 }
1752
1753 return 0;
1754 }
1755
1756 MEM(client = client_alloc(thread, state, inst, thread, radclient, network));
1757
1758 /*
1759 * Parent the dynamic client radclient off the client - it
1760 * is the client which gets freed by the dynamic client timers.
1761 */
1762 if (state == PR_CLIENT_PENDING) talloc_steal(client, radclient);
1763 }
1764
1765have_client:
1766 fr_assert(client->state != PR_CLIENT_INVALID);
1767 fr_assert(client->state != PR_CLIENT_NAK);
1768
1769 /*
1770 * We've accepted a new connection. Go allocate it, and
1771 * let it read from the socket.
1772 */
1773 if (accept_fd >= 0) {
1774 connection = fr_io_connection_alloc(inst, thread, client, accept_fd, &address, NULL);
1775 if (!connection) {
1776 static fr_rate_limit_t alloc_failed;
1777
1778 RATE_LIMIT_LOCAL(thread ? &thread->rate_limit.conn_alloc_failed : &alloc_failed,
1779 ERROR, "Failed to allocate connection from client %s", client->radclient->shortname);
1780 return -1;
1781 }
1782
1783 /*
1784 * The parent is in use - ensure the cleanup timer is disarmed.
1785 */
1786 if (fr_timer_armed(connection->parent->ev)) {
1787 FR_TIMER_DISARM_RETURN(connection->parent->ev);
1788 connection->parent->ready_to_delete = false;
1789 }
1790
1791 return 0;
1792 }
1793
1794 /*
1795 * No connected sockets, OR we are the connected socket.
1796 *
1797 * Track this packet and return it if necessary.
1798 */
1799 if (connection || !client->use_connected) {
1800 fr_io_track_t *to_free = NULL;
1801
1802 /*
1803 * Add the packet to the tracking table, if it's
1804 * not already there. Pending packets will be in
1805 * the tracking table, but won't be counted as
1806 * "live" packets.
1807 */
1808 if (!track) {
1809 static fr_rate_limit_t tracking_failed;
1810 bool is_dup = false;
1811
1812 track = fr_io_track_add(li, client, &address, buffer, packet_len, recv_time, &is_dup);
1813 if (!track) {
1814 RATE_LIMIT_LOCAL(thread ? &thread->rate_limit.tracking_failed : &tracking_failed,
1815 ERROR, "Failed tracking packet from client %s - discarding it",
1816 client->radclient->shortname);
1817 return 0;
1818 }
1819
1820 /*
1821 * If there's a cached reply, just send that and don't do anything else.
1822 */
1823 if (is_dup) {
1824 fr_network_t *nr;
1825
1826 if (track->do_not_respond) {
1827 DEBUG("Ignoring retransmit from client %s - we are not responding to this request", client->radclient->shortname);
1828 return 0;
1829 }
1830
1831 if (track->discard) {
1832 DEBUG("Ignoring transmit from client %s - we previously received a newer / conflicting packet", client->radclient->shortname);
1833 return 0;
1834 }
1835
1836 if (!track->reply) {
1837 fr_assert(!track->finished);
1838 DEBUG("Ignoring retransmit from client %s - we are still processing the request", client->radclient->shortname);
1839 return 0;
1840 }
1841
1842 if (connection) {
1843 nr = connection->nr;
1844 } else {
1845 nr = thread->nr;
1846 }
1847
1848 /*
1849 * @todo - mark things up so that we know to keep 'track' around
1850 * until the packet is actually written to the network. OR, add
1851 * a network API so that the talloc_free() function can remove
1852 * the packet from the queue of packets to be retransmitted.
1853 *
1854 * Perhaps via having fr_network_listen_write() return a pointer
1855 * to the localized message, and then caching that in the tracking
1856 * structure.
1857 */
1858 DEBUG("Sending duplicate reply to client %s", client->radclient->shortname);
1859 fr_network_listen_write(nr, li, track->reply, track->reply_len,
1860 track, track->timestamp);
1861 return 0;
1862 }
1863
1864 /*
1865 * Got to free this if we don't process the packet.
1866 */
1867 to_free = track;
1868 }
1869
1870 /*
1871 * This is a pending dynamic client. See if we
1872 * have to either run the dynamic client code to
1873 * define the client, OR to push the packet onto
1874 * the pending queue for this client.
1875 */
1876 if (client->state == PR_CLIENT_PENDING) {
1877 /*
1878 * Track pending packets for the master
1879 * socket. Connected sockets are paused
1880 * as soon as they are defined, so we
1881 * won't be reading any more packets from
1882 * them.
1883 *
1884 * Since we don't have pending packets
1885 * for connected sockets, we don't need
1886 * to track pending packets.
1887 */
1888 if (!connection && inst->max_pending_packets && (thread->num_pending_packets >= inst->max_pending_packets)) {
1889 RATE_LIMIT_LOCAL(&thread->rate_limit.too_many_pending,
1890 ERROR, "Too many pending dynamic client packets for listener - discarding packet from %pV",
1891 fr_box_ipaddr(client->src_ipaddr));
1892
1893 discard:
1894 talloc_free(to_free);
1895 return 0;
1896 }
1897
1898 /*
1899 * Allocate the pending packet structure.
1900 */
1901 pending = fr_io_pending_alloc(connection, client, buffer, packet_len,
1902 track, priority);
1903 if (!pending) {
1904 static fr_rate_limit_t alloc_failed;
1905 RATE_LIMIT_LOCAL(thread ? &thread->rate_limit.alloc_failed : &alloc_failed,
1906 ERROR, "proto_%s - Failed allocating space for dynamic client %pV - discarding packet",
1907 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
1908 goto discard;
1909 }
1910
1911 if (fr_heap_num_elements(client->pending) > 1) {
1912 DEBUG("Verification is still pending for dynamic client %pV - queuing additional packet(s)",
1913 fr_box_ipaddr(client->src_ipaddr));
1914 return 0;
1915 }
1916
1917 /*
1918 * Tell this packet that it's defining a
1919 * dynamic client.
1920 */
1921 track->dynamic = recv_time;
1922
1923 INFO("proto_%s - Verification started for packet from dynamic client %pV - queuing new packets",
1924 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
1925 }
1926
1927 /*
1928 * Remove all cleanup timers for the client /
1929 * connection. It's still in use, so we don't
1930 * want to clean it up.
1931 */
1932 if (fr_timer_armed(client->ev)) {
1933 FR_TIMER_DISARM_RETURN(client->ev);
1934 client->ready_to_delete = false;
1935 }
1936
1937 /*
1938 * Remove cleanup timers for the connection parent.
1939 */
1940 if (connection && fr_timer_armed(connection->parent->ev)) {
1941 FR_TIMER_DISARM_RETURN(connection->parent->ev);
1942 connection->parent->ready_to_delete = false;
1943 }
1944
1945 /*
1946 * Return the packet.
1947 */
1948 *recv_time_p = track->timestamp;
1949 *packet_ctx = track;
1950 return packet_len;
1951 }
1952
1953 /*
1954 *
1955 */
1956 fr_assert(!pending);
1957
1958 /*
1959 * This must be the main UDP socket which creates
1960 * connections.
1961 */
1962 fr_assert(inst->ipproto == IPPROTO_UDP);
1963
1964 /*
1965 * We're using connected sockets, but this socket isn't
1966 * connected. It must be the master socket. The master
1967 * can either be STATIC, DYNAMIC, or PENDING. Whatever
1968 * the state, the child socket will take care of handling
1969 * the packet. e.g. dynamic clients, etc.
1970 */
1971 {
1972 bool nak = false;
1973
1974 my_connection.address = &address;
1975
1976 pthread_mutex_lock(&client->mutex);
1977 fr_hash_table_find((void **)&connection, client->ht, &my_connection);
1978 if (connection) nak = (connection->client->state == PR_CLIENT_NAK);
1979 pthread_mutex_unlock(&client->mutex);
1980
1981 /*
1982 * The connection is in NAK state, ignore packets
1983 * for it.
1984 */
1985 if (nak) {
1986 RATE_LIMIT_LOCAL(&thread->rate_limit.repeat_nak, ERROR, "proto_%s - Discarding repeated packet from NAK'd dynamic client %pV",
1987 inst->app_io->common.name, fr_box_ipaddr(address.socket.inet.src_ipaddr));
1988
1989 DEBUG("Discarding packet to NAKed connection %s", connection->name);
1990 return 0;
1991 }
1992 }
1993
1994 /*
1995 * No existing connection, create one.
1996 */
1997 if (!connection) {
1998 connection = fr_io_connection_alloc(inst, thread, client, -1, &address, NULL);
1999 if (!connection) {
2000 RATE_LIMIT_LOCAL(&thread->rate_limit.conn_alloc_failed,
2001 ERROR, "Failed to allocate connection from client %s. Discarding packet.", client->radclient->shortname);
2002 return 0;
2003 }
2004 }
2005
2006 DEBUG("Sending packet to connection %s", connection->name);
2007
2008 /*
2009 * Inject the packet into the connected socket. It will
2010 * process the packet as if it came in from the network.
2011 *
2012 * @todo future - after creating the connection, put the
2013 * current packet into connection->pending, instead of
2014 * inject?, and then call fr_network_listen_read() from
2015 * the child's instantiation routine???
2016 *
2017 * @todo TCP - for ACCEPT sockets, we don't have a
2018 * packet, so don't do this. Instead, the connection
2019 * will take care of figuring out what to do.
2020 *
2021 * We don't need "to_free" after this, as it will be
2022 * tracked in the connected socket.
2023 */
2024 if (fr_network_listen_inject(connection->nr, connection->listen,
2025 buffer, packet_len, recv_time) < 0) {
2026 RATE_LIMIT_LOCAL(&thread->rate_limit.queue_full, PERROR,
2027 "proto_%s - Discarding packet from dynamic client %pV - cannot push packet to connected socket",
2028 inst->app_io->common.name, fr_box_ipaddr(address.socket.inet.src_ipaddr));
2029 /*
2030 * Don't return an error, because that will cause the listener to close its socket.
2031 */
2032 }
2033
2034 return 0;
2035}
2036
2037/** Inject a packet to a connection.
2038 *
2039 * Always called in the context of the network.
2040 */
2041static int mod_inject(fr_listen_t *li, uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time)
2042{
2043 fr_io_instance_t const *inst;
2044 int priority;
2045 bool is_dup = false;
2046 fr_io_connection_t *connection;
2047 fr_io_pending_packet_t *pending;
2048 fr_io_track_t *track;
2049
2050 get_inst(li, &inst, NULL, &connection, NULL);
2051
2052 if (!connection) {
2053 DEBUG2("Received injected packet for an unconnected socket.");
2054 return -1;
2055 }
2056
2057 if (inst->app->priority) {
2058 priority = inst->app->priority(inst->app_instance, buffer, buffer_len);
2059 if (priority <= 0) {
2060 return -1;
2061 }
2062 } else {
2063 priority = PRIORITY_NORMAL;
2064 }
2065
2066 /*
2067 * Track this packet, because that's what mod_read expects.
2068 */
2069 track = fr_io_track_add(li, connection->client, connection->address,
2070 buffer, buffer_len, recv_time, &is_dup);
2071 if (!track) {
2072 DEBUG2("Failed injecting packet to tracking table");
2073 return -1;
2074 }
2075
2076 talloc_get_type_abort(track, fr_io_track_t);
2077
2078 /*
2079 * @todo future - what to do with duplicates?
2080 */
2081 fr_assert(!is_dup);
2082
2083 /*
2084 * Remember to restore this packet later.
2085 */
2086 pending = fr_io_pending_alloc(connection, connection->client, buffer, buffer_len,
2087 track, priority);
2088 if (!pending) {
2089 DEBUG2("Failed injecting packet due to allocation error");
2090 return -1;
2091 }
2092
2093 return 0;
2094}
2095
2096/** Open a new listener
2097 *
2098 */
2099static int mod_open(fr_listen_t *li)
2100{
2101 fr_io_thread_t *thread;
2102 fr_io_instance_t const *inst;
2103
2104 thread = li->thread_instance;
2105 inst = li->app_io_instance;
2106
2107 if (inst->app_io->open(thread->child) < 0) return -1;
2108
2109 li->fd = thread->child->fd; /* copy this back up */
2110
2111 /*
2112 * Set the name of the socket.
2113 */
2114 if (!li->app_io->get_name) {
2115 li->name = li->app_io->common.name;
2116 } else {
2117 li->name = li->app_io->get_name(li);
2118 }
2119
2120 /*
2121 * Note that we're opening a child socket, so we don't
2122 * put it into the list of global listeners.
2123 */
2124
2125 return 0;
2126}
2127
2128
2129/** Set the event list for a new socket
2130 *
2131 * @param[in] li the listener
2132 * @param[in] el the event list
2133 * @param[in] nr context from the network side
2134 */
2136{
2137 fr_io_instance_t const *inst;
2138 fr_io_connection_t *connection;
2139 fr_io_thread_t *thread;
2140 fr_listen_t *child;
2141
2142 get_inst(li, &inst, &thread, &connection, &child);
2143
2144 /*
2145 * We're not doing IO, so there are no timers for
2146 * cleaning up packets, dynamic clients, or connections.
2147 */
2148 if (!inst->submodule) return;
2149
2150 if (inst->app_io->event_list_set) {
2151 inst->app_io->event_list_set(child, el, nr);
2152 }
2153
2154 /*
2155 * Set event list and network side for this socket.
2156 */
2157 if (!connection) {
2158 thread->el = el;
2159 thread->nr = nr;
2160
2161 } else {
2162 connection->el = el;
2163 connection->nr = nr;
2164 }
2165}
2166
2167
2168static void client_expiry_timer(fr_timer_list_t *tl, fr_time_t now, void *uctx)
2169{
2170 fr_io_client_t *client = talloc_get_type_abort(uctx, fr_io_client_t);
2171 fr_io_instance_t const *inst;
2172 fr_io_connection_t *connection;
2173 fr_time_delta_t delay;
2174 int connections;
2175
2176 /*
2177 * No event list? We don't need to expire the client.
2178 */
2179 if (!tl) return;
2180
2181 // @todo - print out what we plan on doing next
2182 connection = client->connection;
2183 inst = client->inst;
2184
2185 fr_assert(client->state != PR_CLIENT_STATIC);
2186
2187 /*
2188 * Called from the read or write functions with
2189 * now==0, to signal that we have to *set* the timer.
2190 */
2191 if (fr_time_eq(now, fr_time_wrap(0))) {
2192 /*
2193 * The timer is already set, don't do anything.
2194 */
2195 if (fr_timer_armed(client->ev)) return;
2196
2197 switch (client->state) {
2199 fr_assert(connection != NULL);
2200 delay = inst->idle_timeout;
2202 (fr_time_delta_lt(client->radclient->limit.idle_timeout, inst->idle_timeout))) {
2203 delay = client->radclient->limit.idle_timeout;
2204 }
2205 break;
2206
2207 case PR_CLIENT_DYNAMIC:
2208 delay = inst->dynamic_timeout;
2209 break;
2210
2211 case PR_CLIENT_NAK:
2212 delay = inst->nak_lifetime;
2213 break;
2214
2215 default:
2216 fr_assert(0 == 1);
2217 return;
2218 }
2219
2220 DEBUG("TIMER - setting idle timeout to %pVs for connection from client %s", fr_box_time_delta(delay), client->radclient->shortname);
2221
2222 goto reset_timer;
2223 }
2224
2225 /*
2226 * It's a negative cache entry. Just delete it.
2227 */
2228 if (client->state == PR_CLIENT_NAK) {
2229 INFO("proto_%s - Expiring NAK'd dynamic client %pV - permitting new packets to be verified",
2230 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
2231
2232 delete_client:
2233 fr_assert(client->packets == 0);
2234
2235 /*
2236 * It's a connected socket. Remove it from the
2237 * parents list of connections, and delete it.
2238 */
2239 if (connection) {
2240 pthread_mutex_lock(&connection->parent->mutex);
2241 if (connection->in_parent_hash) {
2242 connection->in_parent_hash = false;
2243 (void) fr_hash_table_delete(connection->parent->ht, connection);
2244 }
2245 pthread_mutex_unlock(&connection->parent->mutex);
2246
2247 /*
2248 * Mark the connection as dead, and tell
2249 * the network side to stop reading from
2250 * it.
2251 */
2252 connection->dead = true;
2253 fr_network_listen_read(connection->nr, connection->listen);
2254 return;
2255 }
2256
2257 talloc_free(client);
2258 return;
2259 }
2260
2261 DEBUG2("TIMER - checking status of dynamic client %s %pV", client->radclient->shortname, fr_box_ipaddr(client->src_ipaddr));
2262
2263 /*
2264 * It's a dynamically defined client. If no one is using
2265 * it, clean it up after an idle timeout.
2266 */
2267 if ((client->state == PR_CLIENT_DYNAMIC) ||
2268 (client->state == PR_CLIENT_CONNECTED)) {
2269 if (client->packets > 0) {
2270 client->ready_to_delete = false;
2271 return;
2272 }
2273
2274 /*
2275 * No packets, check / set idle timeout.
2276 */
2277 goto idle_timeout;
2278 }
2279
2280 /*
2281 * The client is pending definition. It's either a
2282 * dynamic client which has timed out, OR it's a
2283 * "place-holder" client for connected sockets.
2284 */
2285 fr_assert(client->state == PR_CLIENT_PENDING);
2286
2287 /*
2288 * This is a dynamic client pending definition.
2289 * But it's taken too long to define, so we just
2290 * delete the client, and all packets for it. A
2291 * new packet will cause the dynamic definition
2292 * to be run again.
2293 */
2294 if (!client->use_connected) {
2295 if (!client->packets) {
2296 DEBUG("proto_%s - No packets are using unconnected socket", inst->app_io->common.name);
2297 goto delete_client;
2298 }
2299
2300 /*
2301 * Tell the writer to NOT dynamically define the
2302 * client. We've run into a problem. Then,
2303 * return. The writer will take care of calling
2304 * us again when it notices that a PENDING client
2305 * is ready to delete.
2306 *
2307 * TBH... that shouldn't happen? We should rely
2308 * on the write to do this all of the time...
2309 */
2310 client->ready_to_delete = true;
2311 return;
2312 }
2313
2314 fr_assert(!connection);
2315
2316 /*
2317 * Find out how many connections are using this
2318 * client.
2319 */
2320 pthread_mutex_lock(&client->mutex);
2321 fr_assert(client->ht != NULL);
2322 connections = fr_hash_table_num_elements(client->ht);
2323 pthread_mutex_unlock(&client->mutex);
2324
2325 /*
2326 * No connections are using this client. If
2327 * we've passed the idle timeout, then just
2328 * delete it. Otherwise, set an idle timeout (as
2329 * above);
2330 */
2331 if (!connections) {
2332idle_timeout:
2333 /*
2334 * We didn't receive any packets during the
2335 * idle_timeout, just delete it.
2336 */
2337 if (client->ready_to_delete) {
2338 if (connection) {
2339 DEBUG("proto_%s - idle timeout for connection %s", inst->app_io->common.name, connection->name);
2340 } else {
2341 DEBUG("proto_%s - idle timeout for client %s", inst->app_io->common.name, client->radclient->shortname);
2342 }
2343 goto delete_client;
2344 }
2345
2346 /*
2347 * No packets and no idle timeout set, go set
2348 * idle timeut.
2349 */
2350 client->ready_to_delete = true;
2351 delay = client->state == PR_CLIENT_DYNAMIC ? inst->dynamic_timeout : inst->idle_timeout;
2352 goto reset_timer;
2353 }
2354
2355 /*
2356 * There are live sub-connections. Poll again after a
2357 * long period of time. Once all of the connections are
2358 * closed, we can then delete this client.
2359 *
2360 * @todo - maybe just leave it? we want to be able to
2361 * clean up this client after a while tho... especially
2362 * if the total number of clients is limited.
2363 */
2364 client->ready_to_delete = false;
2365 delay = inst->check_interval;
2366
2367reset_timer:
2368 if (fr_timer_in(client, tl, &client->ev,
2369 delay, false, client_expiry_timer, client) < 0) {
2370 ERROR("proto_%s - Failed adding timeout for dynamic client %s. It will be permanent!",
2371 inst->app_io->common.name, client->radclient->shortname);
2372 return;
2373 }
2374
2375 return;
2376}
2377
2378
2379/*
2380 * Expire cached packets after cleanup_delay time
2381 */
2382static void packet_expiry_timer(fr_timer_list_t *tl, fr_time_t now, void *uctx)
2383{
2384 fr_io_track_t *track = talloc_get_type_abort(uctx, fr_io_track_t);
2385 fr_io_client_t *client = track->client;
2386 fr_io_instance_t const *inst = client->inst;
2387
2388 /*
2389 * Insert the timer if requested.
2390 *
2391 * On duplicates this also extends the expiry timer.
2392 */
2393 if (fr_time_eq(now, fr_time_wrap(0)) && !track->discard && inst->app_io->track_duplicates) {
2394 fr_assert(fr_time_delta_ispos(inst->cleanup_delay));
2395 fr_assert(track->do_not_respond || track->reply_len);
2396
2397 track->expires = fr_time_add(fr_time(), inst->cleanup_delay);
2398
2399 /*
2400 * if the timer succeeds, then "track"
2401 * will be cleaned up when the timer
2402 * fires.
2403 */
2404 if (fr_timer_at(track, tl, &track->ev,
2405 track->expires,
2406 false, packet_expiry_timer, track) == 0) {
2407 DEBUG("proto_%s - cleaning up request in %.6fs", inst->app_io->common.name,
2408 fr_time_delta_unwrap(inst->cleanup_delay) / (double)NSEC);
2409 return;
2410 }
2411
2412 DEBUG("proto_%s - Failed adding cleanup_delay for packet. Discarding packet immediately",
2413 inst->app_io->common.name);
2414 }
2415
2416 /*
2417 * So that all cleanup paths can come here, not just the
2418 * timeout ones.
2419 */
2420 if (fr_time_neq(now, fr_time_wrap(0))) {
2421 DEBUG2("TIMER - proto_%s - cleanup delay", inst->app_io->common.name);
2422 } else {
2423 DEBUG2("proto_%s - cleaning up", inst->app_io->common.name);
2424 }
2425
2426 /*
2427 * Delete the tracking entry.
2428 */
2429 talloc_free(track);
2430
2431 /*
2432 * The client isn't dynamic, stop here.
2433 */
2434 if (client->state == PR_CLIENT_STATIC) return;
2435
2436 fr_assert(client->state != PR_CLIENT_NAK);
2437 fr_assert(client->state != PR_CLIENT_PENDING);
2438
2439 /*
2440 * If necessary, call the client expiry timer to clean up
2441 * the client.
2442 */
2443 if (client->packets == 0) {
2444 client_expiry_timer(tl, now, client);
2445 }
2446}
2447
2448static void update_client(fr_io_client_t *client, fr_client_t *radclient)
2449{
2450
2451 /*
2452 * The new client is mostly OK. Copy the various fields
2453 * over.
2454 */
2455#define COPY_FIELD(_dest, _x) _dest->radclient->_x = radclient->_x
2456#define DUP_FIELD(_dest, _x) _dest->radclient->_x = talloc_strdup(_dest->radclient, radclient->_x)
2457
2458 /*
2459 * Only these two fields are set. Other strings in
2460 * radclient are copies of these ones.
2461 */
2464
2465 DUP_FIELD(client, longname);
2466 DUP_FIELD(client, shortname);
2467 DUP_FIELD(client, secret);
2468 DUP_FIELD(client, nas_type);
2469
2470 COPY_FIELD(client, ipaddr);
2471 COPY_FIELD(client, src_ipaddr);
2472 COPY_FIELD(client, require_message_authenticator);
2473 COPY_FIELD(client, require_message_authenticator_is_set);
2474#ifdef NAS_VIOLATES_RFC
2475 COPY_FIELD(client, allow_vulnerable_clients);
2476#endif
2477 COPY_FIELD(client, limit_proxy_state);
2478 COPY_FIELD(client, limit_proxy_state_is_set);
2479 COPY_FIELD(client, use_connected);
2480 COPY_FIELD(client, cs);
2481}
2482
2483/** Tear down any deferred sibling connections under a pending parent.
2484 *
2485 * This function is Cclled from mod_write() when the first connection dynamic-client verification fails (NAK
2486 * or hard reject). Any other connections that were inserted into parent->ht are then freed.
2487 *
2488 * Walk parent->ht, find every deferred sibling, remove it from the hash table, close the socket, and frees
2489 * its module instance (which cascades to the connection itself). The first connection (the one whose
2490 * verification just failed) is identified by conn->nr != NULL and is left alone, as the caller already owns
2491 * its cleanup.
2492 *
2493 * Uses a find-one-then-restart loop rather than iterate-while-deleting, since the deferred sibling count is
2494 * small and the cost is irrelevant on the failure path.
2495 */
2497{
2498 if (!parent->ht) return;
2499
2500 while (true) {
2501 fr_hash_iter_t iter;
2502 fr_io_connection_t *target = NULL;
2503 fr_io_connection_t *conn;
2504
2505 pthread_mutex_lock(&parent->mutex);
2506 for (conn = fr_hash_table_iter_init(parent->ht, &iter);
2507 conn != NULL;
2508 conn = fr_hash_table_iter_next(parent->ht, &iter)) {
2509 if (conn->nr != NULL) continue; /* first child, owned by caller */
2510 if (conn->client->state != PR_CLIENT_PENDING) continue; /* already NAK or promoted */
2511 target = conn;
2512 break;
2513 }
2514 if (target && target->in_parent_hash) {
2515 target->in_parent_hash = false;
2516 (void) fr_hash_table_delete(parent->ht, target);
2517 }
2518 pthread_mutex_unlock(&parent->mutex);
2519
2520 if (!target) break;
2521
2522 DEBUG("proto_%s - cleaning up deferred connection %s after verification failure",
2523 target->client->inst->app_io->common.name, target->name);
2524
2525 if (target->child) {
2526 if (target->client->inst->app_io->close) {
2527 (void) target->client->inst->app_io->close(target->child);
2528 } else if (target->child->fd >= 0) {
2529 close(target->child->fd);
2530 }
2531 }
2532
2533 talloc_free(target->mi);
2534 }
2535}
2536
2537/** Promote a pending dynamic-client parent and all of its child connections.
2538 *
2539 * When multiple TCP connections from the same source IP arrive while the parent client is still
2540 * PR_CLIENT_PENDING, only the first connection is added to the scheduler. Later connection are inserted
2541 * into the parent's hash table, but their fr_schedule_listen_add() call is deferred to this function. When
2542 * the first connection verification completes successfully, every other connection is finished and
2543 * scheduled.
2544 *
2545 * This function:
2546 *
2547 * * Promotes the parent itself to PR_CLIENT_DYNAMIC and re-parents the cs.
2548 *
2549 * * Walks the parent's hash table of connections. For the first connection (already in the scheduler with
2550 * connection->nr set), it resumes reads if the connection was paused. For every later connection,
2551 * (connection->nr == NULL), it copies the verified radclient definition onto the connection and then calls
2552 * fr_schedule_listen_add() to add the connection to the scheduler.
2553 *
2554 * @param parent the parent client whose state and child connections to promote
2555 * @param radclient the verified radclient (typically the calling child's radclient)
2556 */
2558{
2559 fr_hash_iter_t iter;
2560 fr_io_connection_t *conn;
2561 fr_schedule_t *sc = parent->thread->sc;
2562
2563 /*
2564 * Promote the parent itself. Only the first connection to reach here does the work; later
2565 * connections will already see the parent as PR_CLIENT_DYNAMIC.
2566 */
2567 if (parent->state == PR_CLIENT_PENDING) {
2568 parent->radclient->active = true;
2569 parent->state = PR_CLIENT_DYNAMIC;
2570
2571 update_client(parent, radclient);
2572
2573 /*
2574 * Re-parent the conf section used to build this
2575 * client so its lifetime is linked to the parent
2576 * client.
2577 */
2578 talloc_steal(parent->radclient, parent->radclient->cs);
2579 } else {
2581 }
2582
2583 /*
2584 * Walk every child connection of this parent and promote the pending ones. The calling
2585 * connection is itself in parent->ht, so its per-child work is also done here.
2586 */
2587 pthread_mutex_lock(&parent->mutex);
2588 if (parent->ht) {
2589 for (conn = fr_hash_table_iter_init(parent->ht, &iter);
2590 conn != NULL;
2591 conn = fr_hash_table_iter_next(parent->ht, &iter)) {
2592 fr_io_client_t *child = conn->client;
2593
2594 if (child->state != PR_CLIENT_PENDING) continue;
2595
2596 /*
2597 * Connections can't spawn new connections.
2598 */
2599 child->use_connected = child->radclient->use_connected = false;
2600
2601 if (conn->nr == NULL) {
2602 /*
2603 * Deferred connection: its radclient was cloned from the parent's
2604 * placeholder before verification, so copy the now-verified fields onto
2605 * it before adding it to the scheduler.
2606 */
2607 update_client(child, radclient);
2608
2609 child->state = PR_CLIENT_DYNAMIC;
2610 child->radclient->active = true;
2611
2612 DEBUG("proto_%s - scheduling deferred connection %s",
2613 child->inst->app_io->common.name, conn->name);
2614
2615 conn->nr = fr_schedule_listen_add(sc, conn->listen);
2616 if (!conn->nr) {
2617 ERROR("proto_%s - Failed scheduling deferred connection %s",
2618 child->inst->app_io->common.name, conn->name);
2619 /*
2620 * Leave the entry in the hash table; the usual connection
2621 * cleanup path will eventually remove it.
2622 */
2623 }
2624 } else {
2625 /*
2626 * The first connection is already scheduled. Resume reads if it was
2627 * paused, while waiting on verification.
2628 */
2629 if (conn->paused) {
2630 conn->paused = false;
2631 (void) fr_event_filter_update(conn->el, conn->child->fd,
2633 }
2634
2635 child->state = PR_CLIENT_DYNAMIC;
2636 child->radclient->active = true;
2637 }
2638 }
2639 }
2640 pthread_mutex_unlock(&parent->mutex);
2641}
2642
2643static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, fr_time_t request_time,
2644 uint8_t *buffer, size_t buffer_len, size_t written)
2645{
2646 fr_io_instance_t const *inst;
2647 fr_io_thread_t *thread;
2648 fr_io_connection_t *connection;
2649 fr_io_track_t *track = talloc_get_type_abort(packet_ctx, fr_io_track_t);
2650 fr_io_client_t *client;
2651 fr_client_t *radclient;
2652 fr_listen_t *child;
2654 char const *name;
2655
2656 get_inst(li, &inst, &thread, &connection, &child);
2657
2658 client = track->client;
2659 if (connection) {
2660 el = connection->el;
2661 name = connection->name;
2662 } else {
2663 el = thread->el;
2664 name = li->name;
2665 }
2666
2667 DEBUG3("Processing reply for %s", name);
2668
2669 /*
2670 * A fully defined client means that we just send the reply.
2671 */
2672 if (client->state != PR_CLIENT_PENDING) {
2673 ssize_t packet_len;
2674
2675 track->finished = true;
2676
2677 /*
2678 * The request received a conflicting packet, so we
2679 * discard this one.
2680 */
2681 if (fr_time_neq(track->timestamp, request_time) || track->discard) {
2682 fr_assert(track->packets > 0);
2683 track->packets--;
2684 DEBUG3("Suppressing reply as we have a newer / conflicing packet from the same source");
2685 track->discard = true;
2686 goto setup_timer;
2687 }
2688
2689 /*
2690 * We have a NAK packet, or the request has timed
2691 * out, or it was discarded due to a conflicting
2692 * packet. We don't respond, but we do cache the
2693 * "do not respond" reply for a period of time.
2694 */
2695 if ((buffer_len == 1) || track->do_not_respond) {
2696 DEBUG3("Not sending response to request - it is marked as 'do not respond'");
2697 track->do_not_respond = true;
2698 goto setup_timer;
2699 }
2700
2701 /*
2702 * We have a real packet, write it to the network
2703 * via the underlying transport write.
2704 */
2705 packet_len = inst->app_io->write(child, track, request_time,
2706 buffer, buffer_len, written);
2707 if (packet_len <= 0) {
2708 ERROR("Failed writing the reply - not sending any response on %s", name);
2709 track->discard = true;
2710 packet_expiry_timer(el->tl, fr_time_wrap(0), track);
2711 return packet_len;
2712 }
2713
2714 /*
2715 * Only a partial write. The network code will
2716 * take care of calling us again, and we will set
2717 * the expiry timer at that point.
2718 */
2719 if ((size_t) packet_len < buffer_len) {
2720 DEBUG3("Partial write (%zd < %zu)", packet_len, buffer_len);
2721 return packet_len;
2722 }
2723
2724 /*
2725 * We're not tracking duplicates, so just expire
2726 * the packet now.
2727 */
2728 if (!inst->app_io->track_duplicates) {
2729 DEBUG3("Not tracking duplicates - expiring the request");
2730 goto setup_timer;
2731 }
2732
2733 /*
2734 * Cache the reply packet if we're doing dedup.
2735 *
2736 * On resend duplicate reply, the reply is
2737 * already filled out. So we don't do that twice.
2738 */
2739 if (!track->reply) {
2740 DEBUG3("Caching reply");
2741 MEM(track->reply = talloc_memdup(track, buffer, buffer_len));
2742 track->reply_len = buffer_len;
2743 }
2744
2745 /*
2746 * Set the timer to expire the packet.
2747 *
2748 * On dedup this also extends the timer.
2749 */
2750 setup_timer:
2751 packet_expiry_timer(el->tl, fr_time_wrap(0), track);
2752 return buffer_len;
2753 }
2754
2755 /*
2756 * The client is pending, so we MUST have dynamic clients.
2757 *
2758 * If there's a connected socket and no dynamic clients, then the
2759 * client state is set to CONNECTED when the client is created.
2760 */
2761 fr_assert(inst->dynamic_clients);
2762 fr_assert(client->pending != NULL);
2763
2764 /*
2765 * The request failed trying to define the dynamic
2766 * client. Discard the client and all pending packets.
2767 */
2768 if ((buffer_len == 1) && (*buffer == true)) {
2769 DEBUG("Request failed trying to define a new client. Discarding client and pending packets.");
2770
2771 if (!connection) {
2772 talloc_free(client);
2773 return buffer_len;
2774 }
2775
2776 /*
2777 * Free pending packets and tracking table.
2778 * The table is parented by connection->parent, so won't
2779 * be auto-freed when connection->client is freed.
2780 */
2781 TALLOC_FREE(client->pending);
2782 if (client->table) TALLOC_FREE(client->table);
2783
2784 /*
2785 * Remove from parent's hash table so new packets won't
2786 * be routed to this connection.
2787 */
2788 pthread_mutex_lock(&connection->parent->mutex);
2789 if (connection->in_parent_hash) {
2790 connection->in_parent_hash = false;
2791 (void) fr_hash_table_delete(connection->parent->ht, connection);
2792 }
2793 pthread_mutex_unlock(&connection->parent->mutex);
2794
2795 /*
2796 * Tear down any sibling connections that were
2797 * deferred waiting on this verification.
2798 */
2799 fr_io_connection_deny(connection->parent);
2800
2801 /*
2802 * Mark the connection as dead, then trigger the
2803 * standard cleanup path via fr_network_listen_read().
2804 * This calls mod_read(), which sees connection->dead,
2805 * returns -1, and the network layer closes the
2806 * connection through its normal error handling.
2807 */
2808 connection->dead = true;
2809 fr_network_listen_read(connection->nr, connection->listen);
2810
2811 return buffer_len;
2812 }
2813
2814 /*
2815 * The dynamic client was NOT defined. Set it's state to
2816 * NAK, delete all pending packets, and close the
2817 * tracking table.
2818 */
2819 if (buffer_len == 1) {
2820 INFO("proto_%s - Verification failed for packet from dynamic client %pV - adding IP address to the NAK cache",
2821 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
2822
2823 client->state = PR_CLIENT_NAK;
2824 if (!connection) {
2825 client_pending_free(client);
2826 } else {
2827 TALLOC_FREE(client->pending);
2828 }
2829 if (client->table) TALLOC_FREE(client->table);
2830 fr_assert(client->packets == 0);
2831
2832 /*
2833 * Tear down any sibling connections that were
2834 * deferred waiting on this verification. Only
2835 * relevant for the connection case — the !connection
2836 * path never has deferred siblings.
2837 */
2838 if (connection) fr_io_connection_deny(connection->parent);
2839
2840 /*
2841 * If we're a connected UDP socket, allocate a
2842 * new connection which is the place-holder for
2843 * the NAK. We will reject packets from from the
2844 * src/dst IP/port.
2845 *
2846 * The timer will take care of deleting the NAK
2847 * connection (which doesn't have any FDs
2848 * associated with it). The network side will
2849 * call mod_close() when the original connection
2850 * is done, which will then free that connection,
2851 * too.
2852 */
2853 if (connection && (inst->ipproto == IPPROTO_UDP)) {
2854 MEM(connection = fr_io_connection_alloc(inst, thread, client, -1, connection->address, connection));
2855 client_expiry_timer(el->tl, fr_time_wrap(0), connection->client);
2856
2857 errno = ECONNREFUSED;
2858 return -1;
2859 }
2860
2861 /*
2862 * For connected TCP sockets, we just call the
2863 * expiry timer, which will close and free the
2864 * connection.
2865 */
2866 client_expiry_timer(el->tl, fr_time_wrap(0), client);
2867 return buffer_len;
2868 }
2869
2870 fr_assert(buffer_len == sizeof(radclient));
2871
2872 memcpy(&radclient, buffer, sizeof(radclient));
2873
2874 if (!connection) {
2875 fr_ipaddr_t ipaddr;
2876
2877 /*
2878 * Check the encapsulating network against the
2879 * address that the user wants to use, but only
2880 * for unconnected sockets.
2881 */
2882 if (client->network.af != radclient->ipaddr.af) {
2883 DEBUG("Client IP address %pV IP family does not match the source network %pV of the packet.",
2884 fr_box_ipaddr(radclient->ipaddr), fr_box_ipaddr(client->network));
2885 goto error;
2886 }
2887
2888 /*
2889 * Network prefix is more restrictive than the one given
2890 * by the client... that's bad.
2891 */
2892 if (client->network.prefix > radclient->ipaddr.prefix) {
2893 DEBUG("Client IP address %pV is not within the prefix with the defined network %pV",
2894 fr_box_ipaddr(radclient->ipaddr), fr_box_ipaddr(client->network));
2895 goto error;
2896 }
2897
2898 ipaddr = radclient->ipaddr;
2899 fr_ipaddr_mask(&ipaddr, client->network.prefix);
2900 if (fr_ipaddr_cmp(&ipaddr, &client->network) != 0) {
2901 DEBUG("Client IP address %pV is not within the defined network %pV.",
2902 fr_box_ipaddr(radclient->ipaddr), fr_box_ipaddr(client->network));
2903 goto error;
2904 }
2905
2906 /*
2907 * We can't define dynamic clients as networks (for now).
2908 *
2909 * @todo - If we did allow it, we would have to remove
2910 * this client from the trie, update it's IP address, and
2911 * re-add it. We can PROBABLY do this if this client
2912 * isn't already connected, AND radclient->use_connected
2913 * is true. But that's for later...
2914 */
2915 if (((radclient->ipaddr.af == AF_INET) &&
2916 (radclient->ipaddr.prefix != 32)) ||
2917 ((radclient->ipaddr.af == AF_INET6) &&
2918 (radclient->ipaddr.prefix != 128))) {
2919 ERROR("Cannot define a dynamic client as a network");
2920
2921 error:
2922 talloc_free(radclient);
2923
2924 /*
2925 * Remove the pending client from the trie.
2926 */
2927 fr_assert(!connection);
2928 talloc_free(client);
2929 return buffer_len;
2930 }
2931 }
2932
2933 update_client(client, radclient);
2934
2935 // @todo - fill in other fields?
2936
2937 talloc_free(radclient);
2938
2939 radclient = client->radclient; /* laziness */
2940 radclient->server_cs = inst->server_cs;
2941 radclient->server = cf_section_name2(inst->server_cs);
2942
2943 /*
2944 * This is a connected socket, and it's just been
2945 * allowed. Go poke the network side to read from the
2946 * socket.
2947 */
2948 if (connection) {
2949 fr_assert(connection != NULL);
2950 fr_assert(connection->client == client);
2951 fr_assert(client->connection != NULL);
2952
2953 /*
2954 * Promote the parent and every sibling connection.
2955 * This also promotes the current child.
2956 */
2957 fr_io_connection_allow(connection->parent, radclient);
2958
2959 INFO("proto_%s - Verification succeeded for packet from dynamic client %pV - processing queued packets",
2960 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr));
2961 goto finish;
2962 } else {
2963 /*
2964 * Re-parent the conf section used to build this client
2965 * so its lifetime is linked to the client
2966 */
2967 talloc_steal(radclient, radclient->cs);
2968 }
2969
2970 fr_assert(connection == NULL);
2971 fr_assert(client->use_connected == false); /* we weren't sure until now */
2972
2973 /*
2974 * Disallow unsupported configurations.
2975 */
2976 if (radclient->use_connected && !inst->app_io->connection_set) {
2977 DEBUG("proto_%s - cannot use connected sockets as underlying 'transport = %s' does not support it.",
2978 inst->app_io->common.name, inst->submodule->module->exported->name);
2979 goto error;
2980 }
2981
2982
2983 /*
2984 * Dynamic clients can spawn new connections.
2985 */
2986 client->use_connected = radclient->use_connected;
2987
2988 /*
2989 * The admin has defined a client which uses connected
2990 * sockets. Go spawn it
2991 */
2992 if (client->use_connected) {
2993 fr_assert(connection == NULL);
2994
2995
2996 /*
2997 * Leave the state as PENDING. Each connection
2998 * will then cause a dynamic client to be
2999 * defined.
3000 */
3001 (void) pthread_mutex_init(&client->mutex, NULL);
3002 MEM(client->ht = fr_hash_table_alloc(client, connection_hash, connection_cmp, NULL));
3003
3004 } else {
3005 /*
3006 * The client has been allowed.
3007 */
3008 client->state = PR_CLIENT_DYNAMIC;
3009 client->radclient->active = true;
3010
3011 INFO("proto_%s - Verification succeeded for packet from dynamic client %pV - processing %d queued packets",
3012 inst->app_io->common.name, fr_box_ipaddr(client->src_ipaddr),
3013 fr_heap_num_elements(client->pending));
3014 }
3015
3016 /*
3017 * Add this client to the master socket, so that
3018 * mod_read() will see the pending client, pop the
3019 * pending packet, and process it.
3020 *
3021 */
3022 if (!thread->pending_clients) {
3024 fr_io_client_t, pending_id, 0));
3025 }
3026
3028 (void) fr_heap_insert(&thread->pending_clients, client);
3029
3030finish:
3031 /*
3032 * Maybe we defined the client, but the original packet
3033 * timed out, so there's nothing more to do. In that case, set up the expiry timers.
3034 */
3035 if (client->packets == 0) {
3036 client_expiry_timer(el->tl, fr_time_wrap(0), client);
3037 }
3038
3039 /*
3040 * If there are pending packets (and there should be at
3041 * least one), tell the network socket to call our read()
3042 * function again.
3043 */
3044 if (fr_heap_num_elements(client->pending) > 0) {
3045 if (connection) {
3046 fr_network_listen_read(connection->nr, connection->listen);
3047 } else {
3048 fr_network_listen_read(thread->nr, thread->listen);
3049 }
3050 }
3051
3052 return buffer_len;
3053}
3054
3055/** Close the socket.
3056 *
3057 */
3058static int mod_close(fr_listen_t *li)
3059{
3060 fr_io_instance_t const *inst;
3061 fr_io_connection_t *connection;
3062 fr_listen_t *child;
3063
3064 get_inst(li, &inst, NULL, &connection, &child);
3065
3066 if (inst->app_io->close) {
3067 int ret;
3068
3069 ret = inst->app_io->close(child);
3070 if (ret < 0) return ret;
3071 } else {
3072 close(child->fd);
3073// child->fd = -1;
3074 }
3075
3076 if (!connection) return 0;
3077
3078 /*
3079 * We allocated this, so we're responsible for closing
3080 * it.
3081 */
3082 DEBUG("Closing connection %s", connection->name);
3083 if (connection->client->pending) {
3084 TALLOC_FREE(connection->client->pending); /* for any pending packets */
3085 }
3086
3087 /*
3088 * Remove connection from parent hash table
3089 */
3090 pthread_mutex_lock(&connection->parent->mutex);
3091 if (connection->in_parent_hash) {
3092 connection->in_parent_hash = false;
3093 (void) fr_hash_table_delete(connection->parent->ht, connection);
3094 }
3095
3096 /*
3097 * If this is a dynamic client, and the parent has no more connections
3098 * set up the timer to expire the dynamic client.
3099 */
3100 if ((connection->parent->state == PR_CLIENT_DYNAMIC) &&
3101 ((!connection->parent->ht) || (fr_hash_table_num_elements(connection->parent->ht) == 0))) {
3102 client_expiry_timer(connection->el->tl, fr_time_wrap(0), connection->parent);
3103 }
3104 pthread_mutex_unlock(&connection->parent->mutex);
3105
3106 talloc_free(connection->mi);
3107
3108 return 0;
3109}
3110
3111static int mod_instantiate(module_inst_ctx_t const *mctx)
3112{
3113 fr_io_instance_t *inst = mctx->mi->data;
3114 CONF_SECTION *conf = mctx->mi->conf;
3115
3116 inst->mi = mctx->mi;
3117 inst->app_io = (fr_app_io_t const *) inst->submodule->exported;
3118 inst->app_io_conf = inst->submodule->conf;
3119 inst->app_io_instance = inst->submodule->data;
3120
3121 /*
3122 * If we're not tracking duplicates then we don't need a
3123 * cleanup delay.
3124 *
3125 * If we are tracking duplicates, then we must have a non-zero cleanup delay.
3126 */
3127 if (!inst->app_io->track_duplicates) {
3128 inst->cleanup_delay = fr_time_delta_wrap(0);
3129
3130 } else {
3131 FR_TIME_DELTA_BOUND_CHECK("cleanup_delay", inst->cleanup_delay, >=, fr_time_delta_from_sec(1));
3132
3133 if (!inst->app_io->track_create) {
3134 cf_log_err(inst->app_io_conf, "Internal error: 'track_duplicates' is set, but there is no 'track create' function");
3135 return -1;
3136 }
3137 }
3138
3139 /*
3140 * Get various information after bootstrapping the
3141 * application IO module.
3142 */
3143 if (inst->app_io->network_get) {
3144 inst->app_io->network_get(&inst->ipproto, &inst->dynamic_clients, &inst->networks, inst->app_io_instance);
3145 }
3146
3147 if ((inst->ipproto == IPPROTO_TCP) && !inst->app_io->connection_set) {
3148 cf_log_err(inst->app_io_conf, "Missing 'connection set' API for proto_%s", inst->app_io->common.name);
3149 return -1;
3150 }
3151
3152 /*
3153 * Ensure that the dynamic client sections exist
3154 */
3155 if (inst->dynamic_clients) {
3157
3158 if (!cf_section_find(server, "new", "client")) {
3159 cf_log_err(conf, "Cannot use 'dynamic_clients = yes' as the virtual server has no 'new client { ... }' section defined.");
3160 return -1;
3161 }
3162
3163 if (!cf_section_find(server, "add", "client")) {
3164 cf_log_warn(conf, "No 'add client { ... }' section was defined.");
3165 }
3166
3167 if (!cf_section_find(server, "deny", "client")) {
3168 cf_log_warn(conf, "No 'deny client { ... }' section was defined.");
3169 }
3170 }
3171
3172 /*
3173 * Create a list of client modules.
3174 *
3175 * FIXME - Probably only want to do this for connected sockets?
3176 *
3177 * FIXME - We probably want write protect enabled?
3178 */
3179 inst->clients = module_list_alloc(inst, &module_list_type_thread_local, "clients", false);
3181
3182 return 0;
3183}
3184
3185
3186static char const *mod_name(fr_listen_t *li)
3187{
3188 fr_io_thread_t *thread;
3189 fr_io_connection_t *connection;
3190 fr_listen_t *child;
3191 fr_io_instance_t const *inst;
3192
3193 get_inst(li, &inst, &thread, &connection, &child);
3194
3195 fr_assert(child != NULL);
3196 return child->app_io->get_name(child);
3197}
3198
3199/** Create a trie from arrays of allow / deny IP addresses
3200 *
3201 * @param ctx the talloc ctx
3202 * @param af the address family to allow
3203 * @param allow the array of IPs / networks to allow. MUST be talloc'd
3204 * @param deny the array of IPs / networks to deny. MAY be NULL, MUST be talloc'd
3205 * @return
3206 * - fr_trie_t on success
3207 * - NULL on error
3208 */
3209fr_trie_t *fr_master_io_network(TALLOC_CTX *ctx, int af, fr_ipaddr_t *allow, fr_ipaddr_t *deny)
3210{
3211 fr_trie_t *trie;
3212 size_t i, num;
3213
3214 MEM(trie = fr_trie_alloc(ctx, NULL, NULL));
3215
3216 num = talloc_array_length(allow);
3217 fr_assert(num > 0);
3218
3219 for (i = 0; i < num; i++) {
3220 fr_ipaddr_t *network;
3221
3222 /*
3223 * Can't add v4 networks to a v6 socket, or vice versa.
3224 */
3225 if (allow[i].af != af) {
3226 fr_strerror_printf("Address family in entry %zd - 'allow = %pV' "
3227 "does not match 'ipaddr'", i + 1, fr_box_ipaddr(allow[i]));
3228 talloc_free(trie);
3229 return NULL;
3230 }
3231
3232 /*
3233 * Duplicates are bad.
3234 */
3235 network = fr_trie_match_by_key(trie,
3236 &allow[i].addr, allow[i].prefix);
3237 if (network) {
3238 fr_strerror_printf("Cannot add duplicate entry 'allow = %pV'",
3239 fr_box_ipaddr(allow[i]));
3240 talloc_free(trie);
3241 return NULL;
3242 }
3243
3244 /*
3245 * Look for overlapping entries.
3246 * i.e. the networks MUST be disjoint.
3247 *
3248 * Note that this catches 192.168.1/24
3249 * followed by 192.168/16, but NOT the
3250 * other way around. The best fix is
3251 * likely to add a flag to
3252 * fr_trie_alloc() saying "we can only
3253 * have terminal fr_trie_user_t nodes"
3254 */
3255 network = fr_trie_lookup_by_key(trie,
3256 &allow[i].addr, allow[i].prefix);
3257 if (network && (network->prefix <= allow[i].prefix)) {
3258 fr_strerror_printf("Cannot add overlapping entry 'allow = %pV'", fr_box_ipaddr(allow[i]));
3259 fr_strerror_const("Entry is completely enclosed inside of a previously defined network.");
3260 talloc_free(trie);
3261 return NULL;
3262 }
3263
3264 /*
3265 * Insert the network into the trie.
3266 * Lookups will return the fr_ipaddr_t of
3267 * the network.
3268 */
3269 if (fr_trie_insert_by_key(trie,
3270 &allow[i].addr, allow[i].prefix,
3271 &allow[i]) < 0) {
3272 fr_strerror_printf("Failed adding 'allow = %pV' to tracking table", fr_box_ipaddr(allow[i]));
3273 talloc_free(trie);
3274 return NULL;
3275 }
3276 }
3277
3278 /*
3279 * And now check denied networks.
3280 */
3281 num = talloc_array_length(deny);
3282 if (!num) return trie;
3283
3284 /*
3285 * Since the default is to deny, you can only add
3286 * a "deny" inside of a previous "allow".
3287 */
3288 for (i = 0; i < num; i++) {
3289 fr_ipaddr_t *network;
3290
3291 /*
3292 * Can't add v4 networks to a v6 socket, or vice versa.
3293 */
3294 if (deny[i].af != af) {
3295 fr_strerror_printf("Address family in entry %zd - 'deny = %pV' "
3296 "does not match 'ipaddr'", i + 1, fr_box_ipaddr(deny[i]));
3297 talloc_free(trie);
3298 return NULL;
3299 }
3300
3301 /*
3302 * Duplicates are bad.
3303 */
3304 network = fr_trie_match_by_key(trie,
3305 &deny[i].addr, deny[i].prefix);
3306 if (network) {
3307 fr_strerror_printf("Cannot add duplicate entry 'deny = %pV'", fr_box_ipaddr(deny[i]));
3308 talloc_free(trie);
3309 return NULL;
3310 }
3311
3312 /*
3313 * A "deny" can only be within a previous "allow".
3314 */
3315 network = fr_trie_lookup_by_key(trie,
3316 &deny[i].addr, deny[i].prefix);
3317 if (!network) {
3318 fr_strerror_printf("The network in entry %zd - 'deny = %pV' is not "
3319 "contained within a previous 'allow'", i + 1, fr_box_ipaddr(deny[i]));
3320 talloc_free(trie);
3321 return NULL;
3322 }
3323
3324 /*
3325 * We hack the AF in "deny" rules. If
3326 * the lookup gets AF_UNSPEC, then we're
3327 * adding a "deny" inside of a "deny".
3328 */
3329 if (network->af != af) {
3330 fr_strerror_printf("The network in entry %zd - 'deny = %pV' is overlaps "
3331 "with another 'deny' rule", i + 1, fr_box_ipaddr(deny[i]));
3332 talloc_free(trie);
3333 return NULL;
3334 }
3335
3336 /*
3337 * Insert the network into the trie.
3338 * Lookups will return the fr_ipaddr_t of
3339 * the network.
3340 */
3341 if (fr_trie_insert_by_key(trie,
3342 &deny[i].addr, deny[i].prefix,
3343 &deny[i]) < 0) {
3344 fr_strerror_printf("Failed adding 'deny = %pV' to tracking table", fr_box_ipaddr(deny[i]));
3345 talloc_free(trie);
3346 return NULL;
3347 }
3348
3349 /*
3350 * Hack it to make it a deny rule.
3351 */
3352 deny[i].af = AF_UNSPEC;
3353 }
3354
3355 return trie;
3356}
3357
3358
3360{
3361 if (!li->thread_instance) return 0;
3362
3364 return 0;
3365}
3366
3368 size_t default_message_size, size_t num_messages)
3369{
3370 fr_listen_t *li, *child;
3371 fr_io_thread_t *thread;
3372
3373 /*
3374 * No IO paths, so we don't initialize them.
3375 */
3376 if (!inst->app_io) {
3377 fr_assert(!inst->dynamic_clients);
3378 return 0;
3379 }
3380
3381 if (!inst->app_io->common.thread_inst_size) {
3382 fr_strerror_const("IO modules MUST set 'thread_inst_size' when using the master IO handler.");
3383 return -1;
3384 }
3385
3386 /*
3387 * Build the #fr_listen_t. This describes the complete
3388 * path data takes from the socket to the decoder and
3389 * back again.
3390 */
3391 MEM(li = talloc_zero(NULL, fr_listen_t));
3392 talloc_set_destructor(li, fr_io_listen_free);
3393
3394 /*
3395 * The first listener is the one for the application
3396 * (e.g. RADIUS). However, we mangle the IO path to
3397 * point to the master IO handler. That allows all of
3398 * the high-level work (dynamic client checking,
3399 * connected sockets, etc.) to be handled by the master
3400 * IO handler.
3401 *
3402 * This listener is then passed to the network code,
3403 * which calls our trampoline functions to do the actual
3404 * work.
3405 */
3406 li->app = inst->app;
3407 li->app_instance = inst->app_instance;
3408 li->server_cs = inst->server_cs;
3409
3410 /*
3411 * Set configurable parameters for message ring buffer.
3412 */
3413 li->default_message_size = default_message_size;
3414 li->num_messages = num_messages;
3415
3416 /*
3417 * Per-socket data lives here.
3418 */
3419 thread = talloc_zero(NULL, fr_io_thread_t);
3420 thread->listen = li;
3421 thread->sc = sc;
3422
3423 /*
3424 * Create the trie of clients for this socket.
3425 */
3426 MEM(thread->trie = fr_trie_alloc(thread, NULL, NULL));
3427
3428 if (inst->dynamic_clients) {
3430 fr_io_client_t, alive_id, 0));
3431 }
3432
3433 /*
3434 * Set the listener to call our master trampoline function.
3435 */
3436 li->cs = inst->app_io_conf;
3437 li->app_io = &fr_master_app_io;
3438 li->thread_instance = thread;
3439 li->app_io_instance = inst;
3440 li->track_duplicates = inst->app_io->track_duplicates;
3441 if (inst->app_io->hexdump_set) inst->app_io->hexdump_set(li, inst->app_io_instance);
3442
3443 /*
3444 * The child listener points to the *actual* IO path.
3445 *
3446 * We need to create a complete listener here (e.g.
3447 * RADIUS + RADIUS_UDP), because the underlying IO
3448 * functions expect to get passed a full listener.
3449 *
3450 * Once the network side calls us, we will call the child
3451 * listener to do the actual IO.
3452 */
3453 child = thread->child = talloc_zero(li, fr_listen_t);
3454 memcpy(child, li, sizeof(*child));
3455
3456 /*
3457 * Reset these fields to point to the IO instance data.
3458 */
3459 child->app_io = inst->app_io;
3460 child->track_duplicates = inst->app_io->track_duplicates;
3461
3462 if (child->app_io->common.thread_inst_size > 0) {
3463 child->thread_instance = talloc_zero_array(NULL, uint8_t,
3464 inst->app_io->common.thread_inst_size);
3465 talloc_set_destructor(child, fr_io_listen_free);
3466
3467 talloc_set_name(child->thread_instance, "proto_%s_thread_t",
3468 inst->app_io->common.name);
3469
3470 /*
3471 * This is "const", and the user can't
3472 * touch it. So we just reuse the same
3473 * configuration everywhere.
3474 */
3475 child->app_io_instance = inst->app_io_instance;
3476
3477 } else {
3478 child->thread_instance = inst->app_io_instance;
3479 child->app_io_instance = child->thread_instance;
3480 }
3481
3482 /*
3483 * Don't call connection_set() for the main socket. It's
3484 * not connected. Instead, tell the IO path to open the
3485 * socket for us.
3486 */
3487 if (inst->app_io->open(child) < 0) {
3488 talloc_free(li);
3489 return -1;
3490 }
3491
3492 li->fd = child->fd; /* copy this back up */
3493
3494 if (!child->app_io->get_name) {
3495 child->name = child->app_io->common.name;
3496 } else {
3497 child->name = child->app_io->get_name(child);
3498 }
3499 li->name = child->name;
3500
3501 /*
3502 * Record which socket we opened.
3503 */
3504 if (child->app_io_addr) {
3505 fr_listen_t *other;
3506
3507 other = listen_find_any(thread->child);
3508 if (other) {
3509 cf_log_err(other->cs, "Already opened socket %s", other->name);
3510 cf_log_err(li->cs, "Failed opening duplicate socket - cannot use the same configuration for two different listen sections");
3511
3512 talloc_free(li);
3513 return -1;
3514 }
3515
3516 (void) listen_record(child);
3517 }
3518
3519 /*
3520 * Add the socket to the scheduler, where it might end up
3521 * in a different thread.
3522 */
3523 if (!fr_schedule_listen_add(sc, li)) {
3524 talloc_free(li);
3525 return -1;
3526 }
3527
3528 return 0;
3529}
3530
3531/*
3532 * Used to create a tracking structure for fr_network_sendto_worker()
3533 */
3534fr_io_track_t *fr_master_io_track_alloc(fr_listen_t *li, fr_client_t *radclient, fr_ipaddr_t const *src_ipaddr, int src_port,
3535 fr_ipaddr_t const *dst_ipaddr, int dst_port)
3536{
3537 fr_io_instance_t const *inst;
3538 fr_io_thread_t *thread;
3539 fr_io_connection_t *connection;
3540 fr_listen_t *child;
3541 fr_io_track_t *track;
3542 fr_io_client_t *client;
3543 fr_io_address_t *address;
3544 fr_listen_t *parent = talloc_parent(li);
3545
3546 (void) talloc_get_type_abort(parent, fr_listen_t);
3547
3548 get_inst(parent, &inst, &thread, &connection, &child);
3549
3550 fr_assert(child == li);
3551
3552 if (unlikely(!thread)) return NULL;
3553 fr_assert(thread->trie != NULL);
3554
3555 client = fr_trie_lookup_by_key(thread->trie, &src_ipaddr->addr, src_ipaddr->prefix);
3556 if (!client) {
3557 MEM(client = client_alloc(thread, PR_CLIENT_STATIC, inst, thread, radclient, NULL));
3558 }
3559
3560 MEM(track = talloc_zero_pooled_object(client->table, fr_io_track_t, 1, sizeof(*track) + sizeof(*track->address) + 64));
3561 MEM(track->address = address = talloc_zero(track, fr_io_address_t));
3562
3563 track->li = li;
3564 track->client = client;
3565
3566 address->socket.inet.src_port = src_port;
3567 address->socket.inet.dst_port = dst_port;
3568
3569 address->socket.inet.src_ipaddr = *src_ipaddr;
3570 address->socket.inet.dst_ipaddr = *dst_ipaddr;
3571 address->radclient = radclient;
3572
3573 return track;
3574}
3575
3576
3578 .common = {
3579 .magic = MODULE_MAGIC_INIT,
3580 .name = "radius_master_io",
3581
3583 },
3584 .default_message_size = 4096,
3585 .track_duplicates = true,
3586
3587 .read = mod_read,
3588 .write = mod_write,
3589 .inject = mod_inject,
3590
3591 .open = mod_open,
3592 .close = mod_close,
3593 .event_list_set = mod_event_list_set,
3594 .get_name = mod_name,
3595};
static int const char char buffer[256]
Definition acutest.h:576
log_entry msg
Definition acutest.h:794
fr_io_close_t close
Close the transport.
Definition app_io.h:60
module_t common
Common fields to all loadable modules.
Definition app_io.h:34
fr_io_track_create_t track_create
create a tracking structure
Definition app_io.h:64
bool track_duplicates
track duplicate packets
Definition app_io.h:41
fr_io_name_t get_name
get the socket name
Definition app_io.h:70
fr_io_track_cmp_t track_compare
compare two tracking structures
Definition app_io.h:65
Public structure describing an I/O path for a protocol.
Definition app_io.h:33
#define CMP_PREFER_SMALLER(_a, _b)
Evaluates to +1 for a > b, and -1 for a < b.
Definition build.h:105
#define CMP_PREFER_LARGER(_a, _b)
Evaluates to -1 for a > b, and +1 for a < b.
Definition build.h:109
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
Definition build.h:122
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:113
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:540
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
int cf_pair_replace_or_add(CONF_SECTION *cs, char const *ref, char const *value)
Definition cf_util.c:2603
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition cf_util.c:1362
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1348
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:1204
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:695
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
Definition cf_util.c:1035
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
#define cf_parent(_cf)
Definition cf_util.h:118
#define cf_log_warn(_cf, _fmt,...)
Definition cf_util.h:346
#define PRIORITY_NORMAL
Definition channel.h:153
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
Test enumeration values.
Definition dict_test.h:92
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
#define fr_event_filter_update(...)
Definition event.h:239
#define FR_EVENT_RESUME(_s, _f)
Re-add the filter for a func from kevent.
Definition event.h:131
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
Definition event.h:115
Callbacks for the FR_EVENT_FILTER_IO filter.
Definition event.h:188
Structure describing a modification to a filter's state.
Definition event.h:96
void * fr_hash_table_iter_next(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Iterate over entries in a hash table.
Definition hash.c:668
int fr_hash_table_find(void **found, fr_hash_table_t *ht, void const *data)
Find data in a hash table.
Definition hash.c:458
void * fr_hash_table_iter_init(fr_hash_table_t *ht, fr_hash_iter_t *iter)
Initialise an iterator.
Definition hash.c:723
uint32_t fr_hash_update(void const *data, size_t size, uint32_t hash)
Definition hash.c:900
uint32_t fr_hash(void const *data, size_t size)
Definition hash.c:866
int fr_hash_table_delete(fr_hash_table_t *ht, void const *data)
Remove and free data (if a free function was specified)
Definition hash.c:635
uint32_t fr_hash_table_num_elements(fr_hash_table_t *ht)
Definition hash.c:652
int fr_hash_table_insert(fr_hash_table_t *ht, void const *data)
Insert data into a hash table.
Definition hash.c:501
#define fr_hash_table_alloc(_ctx, _hash_node, _cmp_node, _free_node)
Definition hash.h:61
Stores the state of the current iteration operation.
Definition hash.h:41
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:149
int fr_heap_pop(void **out, fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:359
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
Definition heap.c:259
unsigned int fr_heap_index_t
Definition heap.h:82
static void * fr_heap_peek(fr_heap_t *h)
Return the item from the top of the heap but don't pop it.
Definition heap.h:138
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
Definition heap.h:102
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:126
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
Definition heap.h:181
#define FR_HEAP_INDEX_INVALID
Definition heap.h:85
The main heap structure.
Definition heap.h:68
talloc_free(hp)
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition inet.c:1448
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
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
Definition inet.c:218
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
union fr_ipaddr_t::@154 addr
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
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
int fr_network_listen_inject(fr_network_t *nr, fr_listen_t *li, uint8_t const *packet, size_t packet_len, fr_time_t recv_time)
Inject a packet for a listener to read.
Definition network.c:409
void fr_network_listen_read(fr_network_t *nr, fr_listen_t *li)
Signal the network to read from a listener.
Definition network.c:335
void fr_network_listen_write(fr_network_t *nr, fr_listen_t *li, uint8_t const *packet, size_t packet_len, void *packet_ctx, fr_time_t request_time)
Inject a packet for a listener to write.
Definition network.c:361
char const * server
Name of the virtual server client is associated with.
Definition client.h:127
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
Definition client.h:83
char const * secret
Secret PSK.
Definition client.h:90
bool active
for dynamic clients
Definition client.h:114
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
Definition client.h:84
char const * nas_type
Type of client (arbitrary).
Definition client.h:125
int proto
Protocol number.
Definition client.h:141
CONF_SECTION * cs
CONF_SECTION that was parsed to generate the client.
Definition client.h:132
bool dynamic
Whether the client was dynamically defined.
Definition client.h:113
char const * longname
Client identifier.
Definition client.h:87
fr_socket_limit_t limit
Connections per client (TCP clients only).
Definition client.h:142
char const * shortname
Client nickname.
Definition client.h:88
bool use_connected
do we use connected sockets for this client
Definition client.h:115
CONF_SECTION * server_cs
Virtual server that the client is associated with.
Definition client.h:128
Describes a host allowed to send packets to the server.
Definition client.h:80
#define PERROR(_fmt,...)
Definition log.h:233
#define DEBUG3(_fmt,...)
Definition log.h:271
#define RATE_LIMIT_LOCAL(_entry, _log, _fmt,...)
Rate limit messages using a local limiting entry.
Definition log.h:586
Track when a log message was last repeated.
Definition log.h:564
#define fr_time()
Definition event.c:60
Stores all information relating to an event list.
Definition event.c:377
size_t num_messages
for the message ring buffer
Definition listen.h:57
CONF_SECTION * cs
of this listener
Definition listen.h:41
char const * name
printable name for this socket - set by open
Definition listen.h:29
bool track_duplicates
do we track duplicate packets?
Definition listen.h:45
fr_socket_t * app_io_addr
for tracking duplicate sockets
Definition listen.h:36
void const * app_instance
Definition listen.h:39
size_t default_message_size
copied from app_io, but may be changed
Definition listen.h:56
bool connected
is this for a connected socket?
Definition listen.h:44
fr_app_t const * app
Definition listen.h:38
void const * app_io_instance
I/O path configuration context.
Definition listen.h:33
CONF_SECTION * server_cs
CONF_SECTION of the server.
Definition listen.h:42
void * thread_instance
thread / socket context
Definition listen.h:34
int fd
file descriptor for this socket - set by open
Definition listen.h:28
fr_app_io_t const * app_io
I/O path functions.
Definition listen.h:32
fr_listen_t * child
The child (app_io) IO path.
Definition master.c:41
fr_network_t * nr
network for this connection
Definition master.c:163
static void fr_io_connection_allow(fr_io_client_t *parent, fr_client_t *radclient)
Promote a pending dynamic-client parent and all of its child connections.
Definition master.c:2557
static fr_io_track_t * fr_io_track_add(fr_listen_t const *li, fr_io_client_t *client, fr_io_address_t *address, uint8_t const *packet, size_t packet_len, fr_time_t recv_time, bool *is_dup)
Definition master.c:1161
bool in_trie
is the client in the trie?
Definition master.c:122
static fr_io_pending_packet_t * fr_io_pending_alloc(fr_io_connection_t *connection, fr_io_client_t *client, uint8_t const *buffer, size_t packet_len, fr_io_track_t *track, int priority)
Definition master.c:1337
bool paused
event filter doesn't like resuming something that isn't paused
Definition master.c:160
bool in_parent_hash
for tracking thread issues
Definition master.c:161
static fr_client_t * radclient_clone(TALLOC_CTX *ctx, fr_client_t const *parent)
Definition master.c:397
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)
Implement 99% of the read routines.
Definition master.c:1394
static fr_cmp_ret_t address_cmp(void const *one, void const *two)
Definition master.c:264
int packets
number of packets using this connection
Definition master.c:151
uint32_t num_pending_packets
number of pending packets
Definition master.c:46
#define DUP_FIELD(_x)
static int track_dedup_free(fr_io_track_t *track)
Definition master.c:187
fr_rb_tree_t * table
tracking table for packets
Definition master.c:127
fr_time_t recv_time
Definition master.c:69
fr_heap_t * pending_clients
heap of pending clients
Definition master.c:37
bool ready_to_delete
are we ready to delete this client?
Definition master.c:121
static fr_cmp_ret_t pending_packet_cmp(void const *one, void const *two)
Definition master.c:216
static int _client_live_free(fr_io_client_t *client)
Definition master.c:1023
fr_heap_index_t pending_id
for pending clients
Definition master.c:117
static int pending_free(fr_io_pending_packet_t *pending)
Definition master.c:1313
bool use_connected
does this client allow connected sub-sockets?
Definition master.c:120
fr_io_client_t * client
our local client (pending or connected).
Definition master.c:155
static int track_free(fr_io_track_t *track)
Definition master.c:176
fr_app_io_t fr_master_app_io
Definition master.c:3577
static void packet_expiry_timer(fr_timer_list_t *tl, fr_time_t now, void *uctx)
Definition master.c:2382
fr_listen_t * listen
The master IO path.
Definition master.c:40
fr_io_track_t * fr_master_io_track_alloc(fr_listen_t *li, fr_client_t *radclient, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port)
Definition master.c:3534
fr_io_address_t * address
full information about the connection.
Definition master.c:152
fr_listen_t * child
child listener (app_io) for this socket
Definition master.c:154
fr_listen_t * listen
master listener for this socket
Definition master.c:153
fr_timer_t * ev
when we clean up the client
Definition master.c:126
fr_network_t * nr
network for the master socket
Definition master.c:34
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:3209
static fr_io_pending_packet_t * pending_packet_pop(fr_io_thread_t *thread)
Definition master.c:359
static fr_cmp_ret_t connection_cmp(void const *one, void const *two)
Definition master.c:294
static void update_client(fr_io_client_t *client, fr_client_t *radclient)
Definition master.c:2448
fr_ipaddr_t network
network for dynamic clients
Definition master.c:113
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.
Definition master.c:2135
static int mod_open(fr_listen_t *li)
Open a new listener.
Definition master.c:2099
pthread_mutex_t mutex
for parent / child signaling
Definition master.c:132
fr_heap_index_t heap_id
Definition master.c:67
static fr_io_client_t * client_alloc(TALLOC_CTX *ctx, fr_io_client_state_t state, fr_io_instance_t const *inst, fr_io_thread_t *thread, fr_client_t *radclient, fr_ipaddr_t const *network)
Allocate a dynamic client.
Definition master.c:1055
fr_io_instance_t const * inst
parent instance for master IO handler
Definition master.c:124
#define LOG_IGNORED_CLIENTS(_inst)
static fr_cmp_ret_t alive_client_cmp(void const *one, void const *two)
Definition master.c:1382
#define COPY_FIELD(_x)
static void fr_io_connection_deny(fr_io_client_t *parent)
Tear down any deferred sibling connections under a pending parent.
Definition master.c:2496
fr_trie_t * trie
trie of clients
Definition master.c:36
static void client_expiry_timer(fr_timer_list_t *tl, fr_time_t now, void *uctx)
Definition master.c:2168
fr_io_client_state_t
Client states.
Definition master.c:79
@ PR_CLIENT_DYNAMIC
dynamically defined client
Definition master.c:83
@ PR_CLIENT_CONNECTED
dynamically defined client in a connected socket
Definition master.c:84
@ PR_CLIENT_PENDING
dynamic client pending definition
Definition master.c:85
@ PR_CLIENT_INVALID
Definition master.c:80
@ PR_CLIENT_NAK
negative cache entry
Definition master.c:82
@ PR_CLIENT_STATIC
static / global clients
Definition master.c:81
static void get_inst(fr_listen_t *li, fr_io_instance_t const **inst, fr_io_thread_t **thread, fr_io_connection_t **connection, fr_listen_t **child)
Definition master.c:975
static fr_event_update_t pause_read[]
Definition master.c:166
struct fr_io_thread_t::@49 rate_limit
fr_heap_t * alive_clients
heap of active dynamic clients
Definition master.c:38
fr_schedule_t * sc
the scheduler
Definition master.c:42
static fr_io_connection_t * fr_io_connection_alloc(fr_io_instance_t const *inst, fr_io_thread_t *thread, fr_io_client_t *client, int fd, fr_io_address_t *address, fr_io_connection_t *nak)
Create a new connection.
Definition master.c:535
static fr_cmp_ret_t track_cmp(void const *one, void const *two)
Definition master.c:303
fr_hash_table_t * addresses
list of src/dst addresses used by this client
Definition master.c:130
int fr_master_io_listen(fr_io_instance_t *inst, fr_schedule_t *sc, size_t default_message_size, size_t num_messages)
Definition master.c:3367
static int connection_free(fr_io_connection_t *connection)
Definition master.c:520
int fr_io_listen_free(fr_listen_t *li)
Definition master.c:3359
char const * name
taken from proto_FOO_TRANSPORT
Definition master.c:150
fr_heap_index_t alive_id
for all clients
Definition master.c:118
fr_event_list_t * el
event list for this connection
Definition master.c:162
static fr_cmp_ret_t track_connected_cmp(void const *one, void const *two)
Definition master.c:333
fr_io_client_state_t state
state of this client
Definition master.c:111
int packets
number of packets using this client
Definition master.c:116
static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, fr_time_t request_time, uint8_t *buffer, size_t buffer_len, size_t written)
Definition master.c:2643
bool dead
roundabout way to get the network side to close a socket
Definition master.c:159
fr_event_list_t * el
event list, for the master socket.
Definition master.c:33
uint64_t client_id
Unique client identifier.
Definition master.c:47
fr_io_thread_t * thread
Definition master.c:125
static char const * mod_name(fr_listen_t *li)
Definition master.c:3186
module_instance_t * mi
for submodule
Definition master.c:157
static fr_cmp_ret_t pending_client_cmp(void const *one, void const *two)
Definition master.c:246
static int _client_free(fr_io_client_t *client)
Definition master.c:488
static int mod_close(fr_listen_t *li)
Close the socket.
Definition master.c:3058
static uint32_t connection_hash(void const *ctx)
Definition master.c:280
fr_io_connection_t * connection
parent connection
Definition master.c:110
fr_heap_t * pending
pending packets for this client
Definition master.c:129
static int count_connections(UNUSED uint8_t const *key, UNUSED size_t keylen, void *data, void *ctx)
Count the number of connections used by active clients.
Definition master.c:461
fr_hash_table_t * ht
for tracking connected sockets
Definition master.c:133
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition master.c:3111
fr_io_track_t * track
Definition master.c:70
fr_client_t * radclient
old-style definition of this client
Definition master.c:114
fr_ipaddr_t src_ipaddr
packets come from this address
Definition master.c:112
static fr_event_update_t resume_read[]
Definition master.c:171
static void client_pending_free(fr_io_client_t *client)
Definition master.c:503
uint32_t num_connections
number of dynamic connections
Definition master.c:45
fr_io_client_t * parent
points to the parent client.
Definition master.c:156
static fr_client_t * radclient_alloc(TALLOC_CTX *ctx, int ipproto, fr_io_address_t *address)
Definition master.c:995
static int mod_inject(fr_listen_t *li, uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time)
Inject a packet to a connection.
Definition master.c:2041
Client definitions for master IO.
Definition master.c:109
Track a connection.
Definition master.c:149
A saved packet.
Definition master.c:66
fr_timer_t * ev
when we clean up this tracking entry
Definition master.h:43
uint8_t * reply
reply packet (if any)
Definition master.h:47
int packets
number of packets using this entry
Definition master.h:46
fr_time_t dynamic
timestamp for packet doing dynamic client definition
Definition master.h:54
void * app_io_instance
Easy access to the app_io instance.
Definition master.h:106
fr_app_io_t const * app_io
Easy access to the app_io handle.
Definition master.h:105
fr_io_address_t const * address
of this packet.. shared between multiple packets
Definition master.h:55
bool do_not_respond
don't respond
Definition master.h:51
fr_listen_t const * li
listener associated with this tracking structure
Definition master.h:42
bool discard
whether or not we discard the packet
Definition master.h:50
fr_time_t timestamp
when this packet was received
Definition master.h:44
bool finished
are we finished the request?
Definition master.h:52
uint8_t * packet
really a tracking structure, not a packet
Definition master.h:57
size_t reply_len
length of reply, or 1 for "do not reply"
Definition master.h:48
fr_io_client_t * client
client handling this packet.
Definition master.h:56
fr_time_t expires
when this packet expires
Definition master.h:45
The master IO instance.
Definition master.h:73
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
int fr_nonblock(UNUSED int fd)
Definition misc.c:293
fr_cmp_ret_t
Result of an ordering comparison.
Definition misc.h:50
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
#define fr_assert(_expr)
Definition rad_assert.h:37
static int ipproto
static char * secret
#define DEBUG2(fmt,...)
#define INFO(fmt,...)
Definition radict.c:63
static bool cleanup
Definition radsniff.c:59
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
int fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
Definition rb.c:767
int fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
Definition rb.c:637
#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:244
bool being_freed
Prevent double frees in talloc_destructor.
Definition rb.h:94
The main red black tree structure.
Definition rb.h:71
static unsigned int hash(char const *username, unsigned int tablesize)
Definition rlm_passwd.c:132
static char const * name
fr_network_t * fr_schedule_listen_add(fr_schedule_t *sc, fr_listen_t *li)
Add a fr_listen_t to a scheduler.
Definition schedule.c:730
The scheduler.
Definition schedule.c:76
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
void * data
Module's instance data.
Definition module.h:293
module_instantiate_t instantiate
Callback to allow the module to register any per-instance resources like sockets and file handles.
Definition module.h:227
@ MODULE_INSTANCE_BOOTSTRAPPED
Module instance has been bootstrapped, but not yet instantiated.
Definition module.h:266
size_t thread_inst_size
Size of the module's thread-specific instance data.
Definition module.h:246
Module instance data.
Definition module.h:287
fr_time_delta_t idle_timeout
Definition socket.h:38
uint32_t max_connections
Definition socket.h:33
static const uchar sc[16]
Definition smbdes.c:115
module_list_type_t const module_list_type_thread_local
Callbacks for a thread local list.
Definition module.c:587
void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
Set a new bootstrap/instantiate state for a list.
Definition module.c:1876
module_instance_t * module_instance_copy(module_list_t *dst, module_instance_t const *src, char const *inst_name)
Duplicate a module instance, placing it in a new module list.
Definition module.c:1575
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
Definition module.c:1898
int module_thread_instantiate(TALLOC_CTX *ctx, module_instance_t *mi, fr_event_list_t *el)
Allocate thread-local instance data for a module.
Definition module.c:1082
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
Definition module.c:1224
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
Definition module.c:763
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
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
Definition talloc.h:208
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:288
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
Definition talloc.h:127
#define talloc_asprintf
Definition talloc.h:151
#define talloc_strdup(_ctx, _str)
Definition talloc.h:149
void * state
Definition testlib.c:46
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
#define fr_time_delta_lt(_a, _b)
Definition time.h:285
static int64_t fr_time_unwrap(fr_time_t time)
Definition time.h:146
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
#define fr_time_delta_wrap(_time)
Definition time.h:152
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_delta_ispos(_a)
Definition time.h:290
#define fr_time_eq(_a, _b)
Definition time.h:241
#define NSEC
Definition time.h:379
#define fr_time_add(_a, _b)
Add a time/time delta together.
Definition time.h:196
#define fr_time_neq(_a, _b)
Definition time.h:242
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
An event timer list.
Definition timer.c:49
A timer event.
Definition timer.c:83
#define FR_TIMER_DISARM_RETURN(_ev)
Definition timer.h:98
#define FR_TIMER_DELETE(_ev_p)
Definition timer.h:103
#define FR_TIMER_DELETE_RETURN(_ev_p)
Definition timer.h:110
#define fr_timer_in(...)
Definition timer.h:87
#define FR_TIMER_DISARM(_ev)
Definition timer.h:91
static bool fr_timer_armed(fr_timer_t *ev)
Definition timer.h:120
#define fr_timer_at(...)
Definition timer.h:81
void * fr_trie_remove_by_key(fr_trie_t *ft, void const *key, size_t keylen)
Remove a key and return the associated user ctx.
Definition trie.c:2157
fr_trie_t * fr_trie_alloc(TALLOC_CTX *ctx, fr_trie_key_t get_key, fr_free_t free_data)
Allocate a trie.
Definition trie.c:741
int fr_trie_walk(fr_trie_t *ft, void *ctx, fr_trie_walk_t callback)
Definition trie.c:2610
void * fr_trie_lookup_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Lookup a key in a trie and return user ctx, if any.
Definition trie.c:1265
void * fr_trie_match_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Match a key and length in a trie and return user ctx, if any.
Definition trie.c:1289
int fr_trie_insert_by_key(fr_trie_t *ft, void const *key, size_t keylen, void const *data)
Insert a key and user ctx into a trie.
Definition trie.c:1878
static fr_event_list_t * el
static fr_slen_t parent
Definition pair.h:858
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:883
int fd
File descriptor if this is a live socket.
Definition socket.h:86
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Definition socket.h:84
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_ipaddr(_val)
Definition value.h:317
static fr_slen_t data
Definition value.h:1340
#define fr_box_time_delta(_val)
Definition value.h:366
bool listen_record(fr_listen_t *li)
Record that we're listening on a particular IP / port.
fr_listen_t * listen_find_any(fr_listen_t *li)
See if another global listener is using a particular IP / port.