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
{ 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).
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))) {
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);
}
/*
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 {
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.
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
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;
}
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 = {