From: Alan T. DeKok Date: Thu, 2 Mar 2023 02:06:37 +0000 (-0500) Subject: move client list to simple rbtree X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec284b75a3d4f74aa265c8ccc822dd3c3b156628;p=thirdparty%2Ffreeradius-server.git move client list to simple rbtree so that we can loop over it ourselves. And because we can't have ip/mask for BFD. The packets are always sent to a particular IP --- diff --git a/src/listen/bfd/proto_bfd.c b/src/listen/bfd/proto_bfd.c index b97e6f019d2..9dd27b9f2d4 100644 --- a/src/listen/bfd/proto_bfd.c +++ b/src/listen/bfd/proto_bfd.c @@ -75,6 +75,17 @@ fr_dict_attr_autoload_t proto_bfd_dict_attr[] = { { NULL } }; +/* + * They all have to be UDP. + */ +static int8_t client_cmp(void const *one, void const *two) +{ + fr_client_t const *a = one; + fr_client_t const *b = two; + + return fr_ipaddr_cmp(&a->ipaddr, &b->ipaddr); +} + /** Wrapper around dl_instance * * @param[in] ctx to allocate data in (instance of proto_bfd). @@ -423,11 +434,11 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) server = inst->io.server_cs; - inst->peers = cf_data_value(cf_data_find(server, fr_client_list_t, NULL)); + inst->peers = cf_data_value(cf_data_find(server, fr_rb_tree_t, "peers")); if (!inst->peers) { CONF_SECTION *cs = NULL; - inst->peers = client_list_init(server); + inst->peers = fr_rb_inline_talloc_alloc(inst, fr_client_t, node, client_cmp, NULL); if (!inst->peers) return -1; while ((cs = cf_section_find_next(server, cs, "peer", CF_IDENT_ANY))) { @@ -460,13 +471,19 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) FR_INTEGER_BOUND_CHECK("peer.max_timeouts", peer->max_timeouts, >=, 1); FR_INTEGER_BOUND_CHECK("peer.max_timeouts", peer->max_timeouts, <=, 10); - if (!client_add(inst->peers, c)) { + if (((c->ipaddr.af == AF_INET) && (c->ipaddr.prefix != 32)) || + ((c->ipaddr.af == AF_INET6) && (c->ipaddr.prefix != 128))) { + cf_log_err(cs, "Invalid IP prefix - cannot use ip/mask for BFD"); + goto error; + } + + if (!fr_rb_insert(inst->peers, c)) { cf_log_err(cs, "Failed to add peer %s", cf_section_name2(cs)); goto error; } } - (void) cf_data_add(server, inst->peers, NULL, true); + (void) cf_data_add(server, inst->peers, "peers", false); } /* diff --git a/src/listen/bfd/proto_bfd.h b/src/listen/bfd/proto_bfd.h index 8c84c15dc8c..0de1304270f 100644 --- a/src/listen/bfd/proto_bfd.h +++ b/src/listen/bfd/proto_bfd.h @@ -35,7 +35,7 @@ typedef struct { uint32_t max_packet_size; //!< for message ring buffer. uint32_t num_messages; //!< for message ring buffer. - fr_client_list_t *peers; + fr_rb_tree_t *peers; } proto_bfd_t; typedef struct { diff --git a/src/listen/bfd/proto_bfd_udp.c b/src/listen/bfd/proto_bfd_udp.c index 99d74576ac3..dc815fe1bed 100644 --- a/src/listen/bfd/proto_bfd_udp.c +++ b/src/listen/bfd/proto_bfd_udp.c @@ -47,6 +47,8 @@ typedef struct { typedef struct { CONF_SECTION *cs; //!< our configuration + fr_event_list_t *el; + fr_ipaddr_t ipaddr; //!< IP address to listen on. char const *interface; //!< Interface to bind to. @@ -63,7 +65,7 @@ typedef struct { bool send_buff_is_set; //!< Whether we were provided with a send_buff bool dynamic_clients; //!< whether we have dynamic clients - fr_client_list_t *clients; //!< local clients + fr_rb_tree_t *peers; //!< our peers fr_trie_t *trie; //!< for parsed networks fr_ipaddr_t *allow; //!< allowed networks for dynamic clients @@ -390,14 +392,11 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) server_cs = cf_item_to_section(ci); /* - * Look up local clients, if they exist. - * - * @todo - ensure that we only parse clients which are - * for IPPROTO_UDP, and require a "secret". + * Look up peer list. */ - inst->clients = cf_data_value(cf_data_find(server_cs, fr_client_list_t, NULL)); - if (!inst->clients) { - cf_log_err(conf, "Failed finding local clients"); + inst->peers = cf_data_value(cf_data_find(server_cs, fr_rb_tree_t, "peers")); + if (!inst->peers) { + cf_log_err(conf, "Failed finding peer list"); return -1; } @@ -406,18 +405,11 @@ static int mod_bootstrap(module_inst_ctx_t const *mctx) static fr_client_t *mod_client_find(fr_listen_t *li, fr_ipaddr_t const *ipaddr, int ipproto) { - proto_bfd_udp_t const *inst = talloc_get_type_abort_const(li->app_io_instance, proto_bfd_udp_t); - fr_client_t *client; + proto_bfd_udp_t const *inst = talloc_get_type_abort_const(li->app_io_instance, proto_bfd_udp_t); - /* - * Prefer local clients. - */ - if (inst->clients) { - client = client_find(inst->clients, ipaddr, ipproto); - if (client) return client; - } + if (ipproto != IPPROTO_UDP) return NULL; - return client_find(NULL, ipaddr, ipproto); + return fr_rb_find(inst->peers, &(fr_client_t) { .ipaddr = *ipaddr, .proto = IPPROTO_UDP }); } fr_app_io_t proto_bfd_udp = {