#include "rsync/rsync.h"
#include "rtr/rtr.h"
#include "rtr/db/vrps.h"
-#include "slurm/slurm_loader.h"
static int
start_rtr_server(void)
error = clients_db_init();
if (error)
goto revert_vrps;
- error = slurm_load();
- if (error)
- goto revert_clients;
error = rtr_listen();
- slurm_cleanup();
-revert_clients:
clients_db_destroy();
revert_vrps:
vrps_destroy();
int
roa_table_foreach_roa(struct roa_table *table, vrp_foreach_cb cb, void *arg)
{
- struct hashable_roa *node;
+ struct hashable_roa *node, *tmp;
int error;
- for (node = table->roas; node != NULL; node = node->hh.next) {
+ HASH_ITER(hh, table->roas, node, tmp) {
error = cb(&node->data, arg);
if (error)
return error;
return 0;
}
+void
+roa_table_remove_roa(struct roa_table *table, struct vrp *del)
+{
+ struct hashable_roa *ptr;
+
+ HASH_FIND(hh, table->roas, del, sizeof(*del), ptr);
+ if (ptr != NULL) {
+ HASH_DELETE(hh, table->roas, ptr);
+ free(ptr);
+ }
+}
+
int
rtrhandler_handle_roa_v4(struct roa_table *table, uint32_t asn,
struct ipv4_prefix const *prefix4, uint8_t max_length)
void roa_table_destroy(struct roa_table *);
int roa_table_foreach_roa(struct roa_table *, vrp_foreach_cb, void *);
+void roa_table_remove_roa(struct roa_table *, struct vrp *);
int rtrhandler_reset(struct roa_table *);
int rtrhandler_handle_roa_v4(struct roa_table *, uint32_t,
#include "data_structure/array_list.h"
#include "object/tal.h"
#include "rtr/db/roa_table.h"
+#include "slurm/slurm_loader.h"
/*
* Storage of VRPs (term taken from RFC 6811 "Validated ROA Payload") and
static void
resize_deltas_db(struct deltas_db *db, struct delta *start)
{
- struct delta *tmp;
+ struct delta *tmp, *ptr;
db->len -= (start - db->array);
while (db->len < db->capacity / 2)
return;
}
memcpy(tmp, start, db->len * sizeof(struct delta));
+ /* Release memory allocated */
+ for (ptr = db->array; ptr < start; ptr++)
+ deltas_destroy(ptr->deltas);
free(db->array);
db->array = tmp;
}
rwlock_write_lock(&lock);
+ error = slurm_apply(new_base);
+ if (error) {
+ rwlock_unlock(&lock);
+ goto revert_base;
+ }
+
if (state.base != NULL) {
error = compute_deltas(state.base, new_base, &deltas);
if (error) {
#include "slurm_db.h"
-#include <stdbool.h>
#include <string.h>
#include "data_structure/array_list.h"
struct al_assertion_bgpsec assertion_bgps_al;
} array_lists_db;
-#define LOCATE_FUNCS(name, type, array_list, equal_cb, filter) \
- static type * \
- name##_locate(array_list *base, type *obj) \
- { \
- type *cursor; \
- \
- ARRAYLIST_FOREACH(base, cursor) \
- if (equal_cb(cursor, obj, filter)) \
- return cursor; \
- \
- return NULL; \
- } \
- \
- static bool \
- name##_exists(array_list *base, type *obj) \
- { \
- return name##_locate(base, obj) != NULL; \
- }
-
-int
+void
slurm_db_init(void)
{
al_filter_prefix_init(&array_lists_db.filter_pfx_al);
al_assertion_prefix_init(&array_lists_db.assertion_pfx_al);
al_filter_bgpsec_init(&array_lists_db.filter_bgps_al);
al_assertion_bgpsec_init(&array_lists_db.assertion_bgps_al);
-
- return 0;
}
static bool
-prefix_filtered_by(struct slurm_prefix *prefix, struct slurm_prefix *filter)
+prefix_filtered_by(struct slurm_prefix *filter, struct slurm_prefix *prefix)
{
+ struct vrp *filter_vrp, *prefix_vrp;
+
+ filter_vrp = &filter->vrp;
+ prefix_vrp = &prefix->vrp;
+
/* Both have ASN */
- if ((prefix->data_flag & SLURM_COM_FLAG_ASN) > 0 &&
- (filter->data_flag & SLURM_COM_FLAG_ASN) > 0)
- return prefix->asn == filter->asn;
+ if ((filter->data_flag & SLURM_COM_FLAG_ASN) > 0 &&
+ (prefix->data_flag & SLURM_COM_FLAG_ASN) > 0)
+ return filter_vrp->asn == prefix_vrp->asn;
/* Both have a prefix of the same type */
- if ((prefix->data_flag & SLURM_PFX_FLAG_PREFIX) > 0 &&
- (filter->data_flag & SLURM_PFX_FLAG_PREFIX) > 0 &&
- prefix->addr_fam == filter->addr_fam &&
- prefix->prefix_length == filter->prefix_length)
- return ((prefix->addr_fam == AF_INET &&
- prefix->ipv4_prefix.s_addr == filter->ipv4_prefix.s_addr) ||
- (prefix->addr_fam == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(prefix->ipv6_prefix.s6_addr32,
- filter->ipv6_prefix.s6_addr32)));
+ if ((filter->data_flag & SLURM_PFX_FLAG_PREFIX) > 0 &&
+ (prefix->data_flag & SLURM_PFX_FLAG_PREFIX) > 0 &&
+ filter_vrp->addr_fam == prefix_vrp->addr_fam &&
+ filter_vrp->prefix_length == prefix_vrp->prefix_length)
+ return ((filter_vrp->addr_fam == AF_INET &&
+ filter_vrp->prefix.v4.s_addr == prefix_vrp->prefix.v4.s_addr) ||
+ (filter_vrp->addr_fam == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(filter_vrp->prefix.v6.s6_addr32,
+ prefix_vrp->prefix.v6.s6_addr32)));
return false;
}
prefix_equal(struct slurm_prefix *left, struct slurm_prefix *right,
bool filter)
{
+ struct vrp *left_vrp, *right_vrp;
bool equal;
+ left_vrp = &left->vrp;
+ right_vrp = &right->vrp;
+
/* Ignore the comments */
if ((left->data_flag & ~SLURM_COM_FLAG_COMMENT) !=
(right->data_flag & ~SLURM_COM_FLAG_COMMENT))
/* It has the same data, compare it */
equal = true;
if ((left->data_flag & SLURM_COM_FLAG_ASN) > 0)
- equal = equal && left->asn == right->asn;
+ equal = equal && left_vrp->asn == right_vrp->asn;
if ((left->data_flag & SLURM_PFX_FLAG_PREFIX) > 0)
- equal = equal && left->prefix_length == right->prefix_length
- && left->addr_fam == right->addr_fam
- && ((left->addr_fam == AF_INET
- && left->ipv4_prefix.s_addr == right->ipv4_prefix.s_addr)
- || (left->addr_fam == AF_INET6
- && IN6_ARE_ADDR_EQUAL(left->ipv6_prefix.s6_addr32,
- right->ipv6_prefix.s6_addr32)));
+ equal = equal
+ && left_vrp->prefix_length == right_vrp->prefix_length
+ && left_vrp->addr_fam == right_vrp->addr_fam
+ && ((left_vrp->addr_fam == AF_INET
+ && left_vrp->prefix.v4.s_addr == right_vrp->prefix.v4.s_addr)
+ || (left_vrp->addr_fam == AF_INET6
+ && IN6_ARE_ADDR_EQUAL(left_vrp->prefix.v6.s6_addr32,
+ right_vrp->prefix.v6.s6_addr32)));
if ((left->data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0)
equal = equal &&
((left->data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0) &&
- left->max_prefix_length == right->max_prefix_length;
+ left_vrp->max_prefix_length == right_vrp->max_prefix_length;
return equal;
}
return equal;
}
-LOCATE_FUNCS(prefix_filter, struct slurm_prefix, struct al_filter_prefix,
- prefix_equal, true)
-LOCATE_FUNCS(bgpsec_filter, struct slurm_bgpsec, struct al_filter_bgpsec,
- bgpsec_equal, true)
-LOCATE_FUNCS(prefix_assertion, struct slurm_prefix, struct al_assertion_prefix,
- prefix_equal, false)
-LOCATE_FUNCS(bgpsec_assertion, struct slurm_bgpsec, struct al_assertion_bgpsec,
- bgpsec_equal, false)
-
-/*
- * Try to persist the @prefix filter, if it already exists or is covered
- * by another filter, then the error -EEXIST is returned; otherwise, returns
- * the result of persisting the @prefix.
- */
-int
-slurm_db_add_prefix_filter(struct slurm_prefix *prefix)
-{
- if (prefix_filter_exists(&array_lists_db.filter_pfx_al, prefix))
- return -EEXIST;
-
- return al_filter_prefix_add(&array_lists_db.filter_pfx_al, prefix);
-}
+#define ADD_FUNCS(name, type, list_name, db_list, equal_cb, filter) \
+ static type * \
+ name##_locate(type *obj) \
+ { \
+ type *cursor; \
+ \
+ ARRAYLIST_FOREACH(db_list, cursor) \
+ if (equal_cb(cursor, obj, filter)) \
+ return cursor; \
+ \
+ return NULL; \
+ } \
+ \
+ static bool \
+ name##_exists(type *obj) \
+ { \
+ return name##_locate(obj) != NULL; \
+ } \
+ \
+ int \
+ slurm_db_add_##name(type *elem) { \
+ if (name##_exists(elem)) \
+ return -EEXIST; \
+ return list_name##_add(db_list, elem); \
+ }
-/*
- * Try to persist the @prefix assertion, if it already exists, then the error
- * -EEXIST is returned; otherwise, returns the result of persisting the
- * @prefix.
- */
-int
-slurm_db_add_prefix_assertion(struct slurm_prefix *prefix)
+ADD_FUNCS(prefix_filter, struct slurm_prefix, al_filter_prefix,
+ &array_lists_db.filter_pfx_al, prefix_equal, true)
+ADD_FUNCS(bgpsec_filter, struct slurm_bgpsec, al_filter_bgpsec,
+ &array_lists_db.filter_bgps_al, bgpsec_equal, true)
+ADD_FUNCS(prefix_assertion, struct slurm_prefix, al_assertion_prefix,
+ &array_lists_db.assertion_pfx_al, prefix_equal, false)
+ADD_FUNCS(bgpsec_assertion, struct slurm_bgpsec, al_assertion_bgpsec,
+ &array_lists_db.assertion_bgps_al, bgpsec_equal, false)
+
+bool
+slurm_db_vrp_is_filtered(struct vrp *vrp)
{
- if (prefix_assertion_exists(&array_lists_db.assertion_pfx_al, prefix))
- return -EEXIST;
-
- return al_assertion_prefix_add(&array_lists_db.assertion_pfx_al,
- prefix);
-}
+ struct slurm_prefix slurm_prefix;
-/*
- * Try to persist the @bgpsec filter, if it already exists or is covered
- * by another filter, then the error -EEXIST is returned; otherwise, returns
- * the result of persisting the @bgpsec.
- */
-int
-slurm_db_add_bgpsec_filter(struct slurm_bgpsec *bgpsec)
-{
- if (bgpsec_filter_exists(&array_lists_db.filter_bgps_al, bgpsec))
- return -EEXIST;
+ slurm_prefix.data_flag = SLURM_COM_FLAG_ASN | SLURM_PFX_FLAG_PREFIX
+ | SLURM_PFX_FLAG_MAX_LENGTH;
+ slurm_prefix.vrp = *vrp;
+ slurm_prefix.comment = NULL;
- return al_filter_bgpsec_add(&array_lists_db.filter_bgps_al, bgpsec);
+ return prefix_filter_exists(&slurm_prefix);
}
-/*
- * Try to persist the @bgpsec assertion, if it already exists, then the error
- * -EEXIST is returned; otherwise, returns the result of persisting the
- * @bgpsec.
- */
int
-slurm_db_add_bgpsec_assertion(struct slurm_bgpsec *bgpsec)
+slurm_db_foreach_assertion_prefix(assertion_pfx_foreach_cb cb, void *arg)
{
- if (bgpsec_assertion_exists(&array_lists_db.assertion_bgps_al, bgpsec))
- return -EEXIST;
+ struct slurm_prefix *cursor;
+ int error;
- return al_assertion_bgpsec_add(&array_lists_db.assertion_bgps_al,
- bgpsec);
+ ARRAYLIST_FOREACH(&array_lists_db.assertion_pfx_al, cursor) {
+ error = cb(cursor, arg);
+ if (error)
+ return error;
+ }
+
+ return 0;
}
static void
#ifndef SRC_SLURM_SLURM_DB_H_
#define SRC_SLURM_SLURM_DB_H_
+#include <stdbool.h>
#include "slurm/slurm_parser.h"
struct slurm_prefix_list {
struct slurm_bgpsec_list bgpsec_assertions;
};
-int slurm_db_init(void);
+typedef int (*assertion_pfx_foreach_cb)(struct slurm_prefix *, void *);
+
+void slurm_db_init(void);
int slurm_db_add_prefix_filter(struct slurm_prefix *);
int slurm_db_add_prefix_assertion(struct slurm_prefix *);
int slurm_db_add_bgpsec_filter(struct slurm_bgpsec *);
int slurm_db_add_bgpsec_assertion(struct slurm_bgpsec *);
+bool slurm_db_vrp_is_filtered(struct vrp *vrp);
+int slurm_db_foreach_assertion_prefix(assertion_pfx_foreach_cb, void *);
+
void slurm_db_cleanup(void);
#endif /* SRC_SLURM_SLURM_DB_H_ */
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
+#include <stdbool.h>
#include <string.h>
#include "log.h"
return error;
}
-int
-slurm_load(void)
+static int
+slurm_load(bool *loaded)
{
DIR *dir_loc;
struct dirent *dir_ent;
int error;
/* Optional configuration */
+ *loaded = false;
slurm_dir = config_get_slurm_location();
if (slurm_dir == NULL)
return 0;
- error = slurm_db_init();
- if (error)
- return error;
+ *loaded = true;
+ slurm_db_init();
dir_loc = opendir(slurm_dir);
- if (dir_loc == NULL)
- return -pr_errno(errno, "Couldn't open dir %s", slurm_dir);
+ if (dir_loc == NULL) {
+ error = -pr_errno(errno, "Couldn't open dir %s", slurm_dir);
+ goto end;
+ }
errno = 0;
while ((dir_ent = readdir(dir_loc)) != NULL) {
if (error) {
pr_err("The error was at SLURM file %s",
dir_ent->d_name);
- goto end;
+ goto close_dir;
}
errno = 0;
}
pr_err("Error reading dir %s", slurm_dir);
error = -errno;
}
-end:
+close_dir:
closedir(dir_loc);
+end:
return error;
}
-void
+static void
slurm_cleanup(void)
{
/* Only if the SLURM was configured */
if (config_get_slurm_location() != NULL)
slurm_db_cleanup();
}
+
+static int
+slurm_pfx_filters_apply(struct vrp *vrp, void *arg)
+{
+ struct roa_table *table = arg;
+
+ if (slurm_db_vrp_is_filtered(vrp))
+ roa_table_remove_roa(table, vrp);
+
+ return 0;
+}
+
+static int
+slurm_pfx_assertions_add(struct slurm_prefix *prefix, void *arg)
+{
+ struct roa_table *table = arg;
+ struct ipv4_prefix prefix4;
+ struct ipv6_prefix prefix6;
+ struct vrp vrp;
+
+ vrp = prefix->vrp;
+ if ((prefix->data_flag & SLURM_PFX_FLAG_MAX_LENGTH) == 0)
+ vrp.max_prefix_length = vrp.prefix_length;
+
+ if (vrp.addr_fam == AF_INET) {
+ prefix4.addr = vrp.prefix.v4;
+ prefix4.len = vrp.prefix_length;
+ return rtrhandler_handle_roa_v4(table, vrp.asn, &prefix4,
+ vrp.max_prefix_length);
+ }
+ if (vrp.addr_fam == AF_INET6) {
+ prefix6.addr = vrp.prefix.v6;
+ prefix6.len = vrp.prefix_length;
+ return rtrhandler_handle_roa_v6(table, vrp.asn, &prefix6,
+ vrp.max_prefix_length);
+ }
+ return -pr_crit("Unkown addr family type");
+}
+
+static int
+slurm_pfx_assertions_apply(struct roa_table *base)
+{
+ return slurm_db_foreach_assertion_prefix(slurm_pfx_assertions_add,
+ base);
+}
+
+int
+slurm_apply(struct roa_table *base)
+{
+ bool loaded;
+ int error;
+
+ loaded = false;
+ error = slurm_load(&loaded);
+ if (error)
+ goto cleanup;
+
+ if (!loaded)
+ return 0;
+
+ error = roa_table_foreach_roa(base, slurm_pfx_filters_apply, base);
+ if (error)
+ goto cleanup;
+
+ error = slurm_pfx_assertions_apply(base);
+
+ /** TODO Apply BGPsec filters and assertions */
+
+cleanup:
+ slurm_cleanup();
+ return error;
+}
#ifndef SRC_SLURM_SLURM_LOADER_H_
#define SRC_SLURM_SLURM_LOADER_H_
-int slurm_load(void);
-void slurm_cleanup(void);
+#include "rtr/db/roa_table.h"
+
+int slurm_apply(struct roa_table *);
#endif /* SRC_SLURM_SLURM_LOADER_H_ */
return -EINVAL;
return str_to_prefix_length(text, value, max_value);
}
+
/*
* Any unknown members should be treated as errors, RFC8416 3.1:
* "JSON members that are not defined here MUST NOT be used in SLURM
error = ipv4_prefix_validate(&prefixv4);
if (error)
return error;
- result->addr_fam = AF_INET;
- result->ipv4_prefix = prefixv4.addr;
- result->prefix_length = prefixv4.len;
+ result->vrp.addr_fam = AF_INET;
+ result->vrp.prefix.v4 = prefixv4.addr;
+ result->vrp.prefix_length = prefixv4.len;
} else {
error = ipv6_prefix_validate(&prefixv6);
if (error)
return error;
- result->addr_fam = AF_INET6;
- result->ipv6_prefix = prefixv6.addr;
- result->prefix_length = prefixv6.len;
+ result->vrp.addr_fam = AF_INET6;
+ result->vrp.prefix.v6 = prefixv6.addr;
+ result->vrp.prefix_length = prefixv6.len;
}
result->data_flag |= SLURM_PFX_FLAG_PREFIX;
(*members_loaded)++;
init_slurm_prefix(struct slurm_prefix *slurm_prefix)
{
slurm_prefix->data_flag = SLURM_COM_FLAG_NONE;
- slurm_prefix->asn = 0;
- slurm_prefix->ipv6_prefix = in6addr_any;
- slurm_prefix->prefix_length = 0;
- slurm_prefix->max_prefix_length = 0;
- slurm_prefix->addr_fam = 0;
+ slurm_prefix->vrp.asn = 0;
+ slurm_prefix->vrp.prefix.v6 = in6addr_any;
+ slurm_prefix->vrp.prefix_length = 0;
+ slurm_prefix->vrp.max_prefix_length = 0;
+ slurm_prefix->vrp.addr_fam = 0;
slurm_prefix->comment = NULL;
}
init_slurm_prefix(&result);
member_count = 0;
- error = set_asn(object, is_assertion, &result.asn, &result.data_flag,
- &member_count);
+ error = set_asn(object, is_assertion, &result.vrp.asn,
+ &result.data_flag, &member_count);
if (error)
return error;
if (error)
return error;
- error = set_max_prefix_length(object, is_assertion, result.addr_fam,
- &result.max_prefix_length, &result.data_flag, &member_count);
+ error = set_max_prefix_length(object, is_assertion,
+ result.vrp.addr_fam, &result.vrp.max_prefix_length,
+ &result.data_flag, &member_count);
if (error)
return error;
*/
if ((result.data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0)
- if (result.prefix_length > result.max_prefix_length) {
+ if (result.vrp.prefix_length > result.vrp.max_prefix_length) {
pr_err(
"Prefix length is greater than max prefix length");
error = -EINVAL;
#ifndef SRC_SLURM_SLURM_PARSER_H_
#define SRC_SLURM_SLURM_PARSER_H_
-#include <netinet/in.h>
+#include "rtr/db/vrp.h"
/* Flags to get data from structs */
#define SLURM_COM_FLAG_NONE 0x00
struct slurm_prefix {
uint8_t data_flag;
- uint32_t asn;
- union {
- struct in_addr ipv4_prefix;
- struct in6_addr ipv6_prefix;
- };
- uint8_t prefix_length;
- uint8_t max_prefix_length;
- uint8_t addr_fam;
+ struct vrp vrp;
char const *comment;
};