From: pcarana Date: Tue, 7 May 2019 14:47:56 +0000 (-0500) Subject: Apply SLURM prefixes before calculating the deltas X-Git-Tag: v0.0.2~35^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f2866944ee546209c0c63090123ddccc6e535ee1;p=thirdparty%2FFORT-validator.git Apply SLURM prefixes before calculating the deltas --- diff --git a/src/main.c b/src/main.c index 59c9c3a3..8ae24c91 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,6 @@ #include "rsync/rsync.h" #include "rtr/rtr.h" #include "rtr/db/vrps.h" -#include "slurm/slurm_loader.h" static int start_rtr_server(void) @@ -21,14 +20,9 @@ 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(); diff --git a/src/rtr/db/roa_table.c b/src/rtr/db/roa_table.c index 52a0b42d..9c3aae39 100644 --- a/src/rtr/db/roa_table.c +++ b/src/rtr/db/roa_table.c @@ -51,10 +51,10 @@ roa_table_destroy(struct roa_table *table) 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; @@ -100,6 +100,18 @@ add_roa(struct roa_table *table, struct hashable_roa *new) 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) diff --git a/src/rtr/db/roa_table.h b/src/rtr/db/roa_table.h index 8bd0da2d..9c18e0f5 100644 --- a/src/rtr/db/roa_table.h +++ b/src/rtr/db/roa_table.h @@ -10,6 +10,7 @@ struct roa_table *roa_table_create(void); 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, diff --git a/src/rtr/db/vrps.c b/src/rtr/db/vrps.c index 9e3e0882..182f29bd 100644 --- a/src/rtr/db/vrps.c +++ b/src/rtr/db/vrps.c @@ -9,6 +9,7 @@ #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 @@ -149,7 +150,7 @@ __perform_standalone_validation(struct roa_table **result) 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) @@ -160,6 +161,9 @@ resize_deltas_db(struct deltas_db *db, struct delta *start) 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; } @@ -204,6 +208,12 @@ vrps_update(bool *changed) 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) { diff --git a/src/slurm/slurm_db.c b/src/slurm/slurm_db.c index ea7749a2..827743b9 100644 --- a/src/slurm/slurm_db.c +++ b/src/slurm/slurm_db.c @@ -1,6 +1,5 @@ #include "slurm_db.h" -#include #include #include "data_structure/array_list.h" @@ -17,54 +16,38 @@ struct arraylist_db { 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; } @@ -73,8 +56,12 @@ static bool 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)) @@ -83,21 +70,22 @@ prefix_equal(struct slurm_prefix *left, struct slurm_prefix *right, /* 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; } @@ -149,71 +137,67 @@ bgpsec_equal(struct slurm_bgpsec *left, struct slurm_bgpsec *right, 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 diff --git a/src/slurm/slurm_db.h b/src/slurm/slurm_db.h index d35a1f4c..b6f5139f 100644 --- a/src/slurm/slurm_db.h +++ b/src/slurm/slurm_db.h @@ -1,6 +1,7 @@ #ifndef SRC_SLURM_SLURM_DB_H_ #define SRC_SLURM_SLURM_DB_H_ +#include #include "slurm/slurm_parser.h" struct slurm_prefix_list { @@ -20,13 +21,18 @@ struct slurm_db { 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_ */ diff --git a/src/slurm/slurm_loader.c b/src/slurm/slurm_loader.c index 148c5e7a..71bec6a4 100644 --- a/src/slurm/slurm_loader.c +++ b/src/slurm/slurm_loader.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "log.h" @@ -50,8 +51,8 @@ single_slurm_load(const char *dir_name, const char *file_name) return error; } -int -slurm_load(void) +static int +slurm_load(bool *loaded) { DIR *dir_loc; struct dirent *dir_ent; @@ -59,17 +60,19 @@ slurm_load(void) 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) { @@ -77,7 +80,7 @@ slurm_load(void) if (error) { pr_err("The error was at SLURM file %s", dir_ent->d_name); - goto end; + goto close_dir; } errno = 0; } @@ -85,15 +88,88 @@ slurm_load(void) 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; +} diff --git a/src/slurm/slurm_loader.h b/src/slurm/slurm_loader.h index da80bc6c..f1fcad18 100644 --- a/src/slurm/slurm_loader.h +++ b/src/slurm/slurm_loader.h @@ -1,7 +1,8 @@ #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_ */ diff --git a/src/slurm/slurm_parser.c b/src/slurm/slurm_parser.c index 2b79aad2..b1bf139f 100644 --- a/src/slurm/slurm_parser.c +++ b/src/slurm/slurm_parser.c @@ -79,6 +79,7 @@ parse_prefix_length(char *text, uint8_t *value, uint8_t max_value) 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 @@ -187,16 +188,16 @@ set_prefix(json_t *object, bool is_assertion, struct slurm_prefix *result, 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)++; @@ -354,11 +355,11 @@ static void 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; } @@ -375,8 +376,8 @@ load_single_prefix(json_t *object, bool is_assertion) 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; @@ -384,8 +385,9 @@ load_single_prefix(json_t *object, bool is_assertion) 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; @@ -430,7 +432,7 @@ load_single_prefix(json_t *object, bool is_assertion) */ 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; diff --git a/src/slurm/slurm_parser.h b/src/slurm/slurm_parser.h index 221f8a8b..6a1b0ef8 100644 --- a/src/slurm/slurm_parser.h +++ b/src/slurm/slurm_parser.h @@ -1,7 +1,7 @@ #ifndef SRC_SLURM_SLURM_PARSER_H_ #define SRC_SLURM_SLURM_PARSER_H_ -#include +#include "rtr/db/vrp.h" /* Flags to get data from structs */ #define SLURM_COM_FLAG_NONE 0x00 @@ -16,14 +16,7 @@ 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; };