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