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