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