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