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