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