-Remove 'comment' member from slurm structs, there's no need to store its value.
-Rename 'slurm/slurm_db.*' to 'slurm/db_slurm.*'.
-Allocate SLURM data, so that the last valid SLURM can be used if needed; so, now the SLURM lives on the heap and is 'remembered' as part of the VRPs state. Also remember the date and time when the last valid SLURM was loaded.
-Move 'slurm_bgpsec' and 'slurm_prefix' structs, and SLURM data flags to 'db_slurm.h'.
-Update 'slurm_parser' to return a specific error in case of a syntax error, so that further actions can be taken (ignore slurm, use last valid version, or store as the last valid version).
-In case a previous valid version of SLURM is utilized, log a WARNING indicating that such action is being taken, and log SLURM content at INFO level.
-Fix bug at common function 'process_file', there was an issue before releasing temporal pointers.
fort_SOURCES += rtr/db/vrp.h
fort_SOURCES += rtr/db/vrps.c rtr/db/vrps.h
-fort_SOURCES += slurm/slurm_db.c slurm/slurm_db.h
+fort_SOURCES += slurm/db_slurm.c slurm/db_slurm.h
fort_SOURCES += slurm/slurm_loader.c slurm/slurm_loader.h
fort_SOURCES += slurm/slurm_parser.c slurm/slurm_parser.h
}
error = cb(fullpath, arg);
- free(tmp);
free(fullpath);
+ free(tmp);
return error;
}
* during the current iteration.)
*/
struct db_table *base;
- /** ROA changes to @base over time. */
+ /** DB changes to @base over time. */
struct deltas_db deltas;
+ /* Last valid SLURM applied to base */
+ struct db_slurm *slurm;
+
serial_t next_serial;
uint16_t v0_session_id;
uint16_t v1_session_id;
- time_t last_modified_date;
} state;
/** Read/write lock, which protects @state and its inhabitants. */
? (state.v0_session_id - 1)
: (0xFFFFu);
+ state.slurm = NULL;
+
error = pthread_rwlock_init(&state_lock, NULL);
if (error) {
deltas_db_cleanup(&state.deltas, deltagroup_cleanup);
{
if (state.base != NULL)
db_table_destroy(state.base);
+ if (state.slurm != NULL)
+ db_slurm_destroy(state.slurm);
deltas_db_cleanup(&state.deltas, deltagroup_cleanup);
/* Nothing to do with error codes from now on */
pthread_rwlock_destroy(&state_lock);
rwlock_write_lock(&state_lock);
- /*
- * TODO (next iteration) Remember the last valid SLURM
- *
- * Currently SLURM is ignored if it has errors, the error is logged and
- * the new_base isn't altered. Instead of this, the last valid SLURM
- * should be remembered, and will be applied when a new SLURM has
- * errors; a warning should be logged to indicate which version of the
- * SLURM is being applied.
- */
- slurm_apply(&new_base);
+ error = slurm_apply(&new_base, &state.slurm);
+ if (error) {
+ rwlock_unlock(&state_lock);
+ goto revert_base;
+ }
if (state.base != NULL) {
error = compute_deltas(state.base, new_base, &deltas);
-#include "slurm_db.h"
+#include "db_slurm.h"
#include <string.h>
+#include <time.h>
+#include <arpa/inet.h>
#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include "crypto/base64.h"
#include "data_structure/array_list.h"
#include "object/router_key.h"
ARRAY_LIST(al_filter_bgpsec, struct slurm_bgpsec_ctx)
ARRAY_LIST(al_assertion_bgpsec, struct slurm_bgpsec_ctx)
-struct arraylist_db {
+struct db_slurm {
struct al_filter_prefix filter_pfx_al;
struct al_assertion_prefix assertion_pfx_al;
struct al_filter_bgpsec filter_bgps_al;
struct al_assertion_bgpsec assertion_bgps_al;
-} array_lists_db;
+ bool loaded_date_set;
+ time_t loaded_date;
+};
-void
-slurm_db_init(void)
+char addr_buf[INET6_ADDRSTRLEN];
+
+int
+db_slurm_create(struct db_slurm **result)
{
- 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);
+ struct db_slurm *db;
+
+ db = malloc(sizeof(struct db_slurm));
+ if (db == NULL)
+ return pr_enomem();
+
+ /* Not ready yet (nor required yet) for multithreading */
+ al_filter_prefix_init(&db->filter_pfx_al);
+ al_assertion_prefix_init(&db->assertion_pfx_al);
+ al_filter_bgpsec_init(&db->filter_bgps_al);
+ al_assertion_bgpsec_init(&db->assertion_bgps_al);
+ db->loaded_date_set = false;
+
+ *result = db;
+ return 0;
}
static bool
#define ADD_FUNCS(name, type, list_name, db_list, db_alt_list, equal_cb,\
cont_cb, filter) \
static type * \
- name##_locate(type *obj, bool flt, int ctx) \
+ name##_locate(struct db_slurm *db, type *obj, bool flt, int ctx)\
{ \
type##_ctx *cursor; \
array_index i; \
\
- ARRAYLIST_FOREACH(db_list, cursor, i) \
+ ARRAYLIST_FOREACH(&db->db_list, cursor, i) \
if (equal_cb(cursor, obj, ctx, filter, flt)) \
return &cursor->element; \
\
if (ctx < 0) \
return NULL; /* Avoid the next loop */ \
\
- ARRAYLIST_FOREACH(db_alt_list, cursor, i) \
+ ARRAYLIST_FOREACH(&db->db_alt_list, cursor, i) \
if (cont_cb(cursor, obj, ctx)) \
return &cursor->element; \
\
} \
\
static bool \
- name##_exists(type *obj, bool flt, int ctx) \
+ name##_exists(struct db_slurm *db, type *obj, bool flt, int ctx)\
{ \
- return name##_locate(obj, flt, ctx) != NULL; \
+ return name##_locate(db, obj, flt, ctx) != NULL; \
} \
\
int \
- slurm_db_add_##name(type *elem, int ctx) \
+ db_slurm_add_##name(struct db_slurm *db, type *elem, int ctx) \
{ \
type##_ctx new_elem; \
- if (name##_exists(elem, !filter, ctx)) \
+ if (name##_exists(db, elem, !filter, ctx)) \
return -EEXIST; \
new_elem.element = *elem; \
new_elem.ctx = ctx; \
- return list_name##_add(db_list, &new_elem); \
+ return list_name##_add(&db->db_list, &new_elem); \
}
-ADD_FUNCS(prefix_filter, struct slurm_prefix, al_filter_prefix,
- &array_lists_db.filter_pfx_al, &array_lists_db.assertion_pfx_al,
- prefix_equal, prefix_contained, true)
-ADD_FUNCS(bgpsec_filter, struct slurm_bgpsec, al_filter_bgpsec,
- &array_lists_db.filter_bgps_al, &array_lists_db.assertion_bgps_al,
- bgpsec_equal, bgpsec_contained, true)
+ADD_FUNCS(prefix_filter, struct slurm_prefix, al_filter_prefix, filter_pfx_al,
+ assertion_pfx_al, prefix_equal, prefix_contained, true)
+ADD_FUNCS(bgpsec_filter, struct slurm_bgpsec, al_filter_bgpsec, filter_bgps_al,
+ assertion_bgps_al, bgpsec_equal, bgpsec_contained, true)
ADD_FUNCS(prefix_assertion, struct slurm_prefix, al_assertion_prefix,
- &array_lists_db.assertion_pfx_al, &array_lists_db.filter_pfx_al,
- prefix_equal, prefix_contained, false)
+ assertion_pfx_al, filter_pfx_al, prefix_equal, prefix_contained, false)
ADD_FUNCS(bgpsec_assertion, struct slurm_bgpsec, al_assertion_bgpsec,
- &array_lists_db.assertion_bgps_al, &array_lists_db.filter_bgps_al,
- bgpsec_equal, bgpsec_contained, false)
+ assertion_bgps_al, filter_bgps_al, bgpsec_equal, bgpsec_contained, false)
bool
-slurm_db_vrp_is_filtered(struct vrp const *vrp)
+db_slurm_vrp_is_filtered(struct db_slurm *db, struct vrp const *vrp)
{
struct slurm_prefix slurm_prefix;
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 prefix_filter_exists(&slurm_prefix, true, -1);
+ return prefix_filter_exists(db, &slurm_prefix, true, -1);
}
-int
-slurm_db_foreach_assertion_prefix(assertion_pfx_foreach_cb cb, void *arg)
-{
- struct slurm_prefix_ctx *cursor;
- array_index i;
- int error;
-
- ARRAYLIST_FOREACH(&array_lists_db.assertion_pfx_al, cursor, i) {
- error = cb(&cursor->element, arg);
- if (error)
- return error;
+#define ITERATE_LIST_FUNC(type, object, db_list) \
+ int \
+ db_slurm_foreach_##type##_##object(struct db_slurm *db, \
+ object##_foreach_cb cb, void *arg) \
+ { \
+ struct slurm_##object##_ctx *cursor; \
+ array_index i; \
+ int error; \
+ \
+ ARRAYLIST_FOREACH(&db->db_list, cursor, i) { \
+ error = cb(&cursor->element, arg); \
+ if (error) \
+ return error; \
+ } \
+ \
+ return 0; \
}
- return 0;
-}
+ITERATE_LIST_FUNC(filter, prefix, filter_pfx_al)
+ITERATE_LIST_FUNC(filter, bgpsec, filter_bgps_al)
+ITERATE_LIST_FUNC(assertion, prefix, assertion_pfx_al)
+ITERATE_LIST_FUNC(assertion, bgpsec, assertion_bgps_al)
bool
-slurm_db_bgpsec_is_filtered(struct router_key const *key)
+db_slurm_bgpsec_is_filtered(struct db_slurm *db, struct router_key const *key)
{
struct slurm_bgpsec slurm_bgpsec;
unsigned char *tmp;
slurm_bgpsec.ski = tmp;
/* Router public key isn't used at filters */
slurm_bgpsec.router_public_key = NULL;
- slurm_bgpsec.comment = NULL;
- result = bgpsec_filter_exists(&slurm_bgpsec, true, -1);
+ result = bgpsec_filter_exists(db, &slurm_bgpsec, true, -1);
free(tmp);
return result;
}
-int
-slurm_db_foreach_assertion_bgpsec(assertion_bgpsec_foreach_cb cb, void *arg)
+static void
+clean_slurm_bgpsec(struct slurm_bgpsec_ctx *bgpsec)
{
- struct slurm_bgpsec_ctx *cursor;
- array_index i;
- int error;
+ if ((bgpsec->element.data_flag & SLURM_BGPS_FLAG_SKI) > 0)
+ free(bgpsec->element.ski);
+ if ((bgpsec->element.data_flag & SLURM_BGPS_FLAG_ROUTER_KEY) > 0)
+ free(bgpsec->element.router_public_key);
+}
- ARRAYLIST_FOREACH(&array_lists_db.assertion_bgps_al, cursor, i) {
- error = cb(&cursor->element, arg);
- if (error)
- return error;
+void
+db_slurm_update_time(struct db_slurm *db)
+{
+ db->loaded_date = time(NULL);
+ db->loaded_date_set = true;
+}
+
+static char const *
+strv4addr(struct in_addr const *addr)
+{
+ return inet_ntop(AF_INET, addr, addr_buf, INET6_ADDRSTRLEN);
+}
+
+static char const *
+strv6addr(struct in6_addr const *addr)
+{
+ return inet_ntop(AF_INET6, addr, addr_buf, INET6_ADDRSTRLEN);
+}
+
+static int
+print_prefix_data(struct slurm_prefix *prefix, void *arg)
+{
+ char *pad = " ";
+
+ pr_info(" {");
+ if (prefix->data_flag & SLURM_COM_FLAG_ASN)
+ pr_info("%s ASN: %u", pad, prefix->vrp.asn);
+
+ if (prefix->data_flag & SLURM_PFX_FLAG_PREFIX) {
+ switch(prefix->vrp.addr_fam) {
+ case AF_INET:
+ pr_info("%s Prefix: %s/%u", pad,
+ strv4addr(&prefix->vrp.prefix.v4),
+ prefix->vrp.prefix_length);
+ break;
+ case AF_INET6:
+ pr_info("%s Prefix: %s/%u", pad,
+ strv6addr(&prefix->vrp.prefix.v6),
+ prefix->vrp.prefix_length);
+ break;
+ default:
+ pr_crit("Unknown addr family type: %u",
+ prefix->vrp.addr_fam);
+ }
}
+ if (prefix->data_flag & SLURM_PFX_FLAG_MAX_LENGTH)
+ pr_info("%s Max prefix length: %u", pad,
+ prefix->vrp.max_prefix_length);
+ pr_info(" }");
+
return 0;
}
-static void
-clean_slurm_prefix(struct slurm_prefix_ctx *prefix)
+static int
+print_bgpsec_data(struct slurm_bgpsec *bgpsec, void *arg)
{
- if ((prefix->element.data_flag & SLURM_COM_FLAG_COMMENT) > 0)
- free(prefix->element.comment);
+ char *pad = " ";
+ char *buf;
+ int error;
+
+ pr_info(" {");
+ if (bgpsec->data_flag & SLURM_COM_FLAG_ASN)
+ pr_info("%s ASN: %u", pad, bgpsec->asn);
+
+ if (bgpsec->data_flag & SLURM_BGPS_FLAG_SKI) {
+ do {
+ error = base64url_encode(bgpsec->ski, RK_SKI_LEN, &buf);
+ if (error) {
+ pr_info("%s SKI: <error encoding value>", pad);
+ break;
+ }
+ pr_info("%s SKI: %s", pad, buf);
+ free(buf);
+ } while (0);
+ }
+
+ if (bgpsec->data_flag & SLURM_BGPS_FLAG_ROUTER_KEY) {
+ do {
+ error = base64url_encode(bgpsec->router_public_key,
+ RK_SPKI_LEN, &buf);
+ if (error) {
+ pr_info("%s Router public key: <error encoding value>",
+ pad);
+ break;
+ }
+ pr_info("%s Router public key: %s", pad, buf);
+ free(buf);
+ } while (0);
+ }
+ pr_info(" }");
+
+ return 0;
}
-static void
-clean_slurm_bgpsec(struct slurm_bgpsec_ctx *bgpsec)
+void
+db_slurm_log(struct db_slurm *db)
{
- if ((bgpsec->element.data_flag & SLURM_BGPS_FLAG_SKI) > 0)
- free(bgpsec->element.ski);
- if ((bgpsec->element.data_flag & SLURM_BGPS_FLAG_ROUTER_KEY) > 0)
- free(bgpsec->element.router_public_key);
- if ((bgpsec->element.data_flag & SLURM_COM_FLAG_COMMENT) > 0)
- free(bgpsec->element.comment);
+ if (db->loaded_date_set)
+ pr_info("SLURM loaded at %s",
+ asctime(localtime(&db->loaded_date)));
+ pr_info("Validation output filters {");
+ pr_info(" Prefix filters {");
+ db_slurm_foreach_filter_prefix(db, print_prefix_data, NULL);
+ pr_info(" }");
+ pr_info(" BGPsec filters {");
+ db_slurm_foreach_filter_bgpsec(db, print_bgpsec_data, NULL);
+ pr_info(" }");
+ pr_info("}");
+
+ pr_info("Locally added assertions {");
+ pr_info(" Prefix assertions {");
+ db_slurm_foreach_assertion_prefix(db, print_prefix_data, NULL);
+ pr_info(" }");
+ pr_info(" BGPsec assertions {");
+ db_slurm_foreach_assertion_bgpsec(db, print_bgpsec_data, NULL);
+ pr_info(" }");
+ pr_info("}");
}
void
-slurm_db_cleanup(void)
+db_slurm_destroy(struct db_slurm *db)
{
- al_filter_prefix_cleanup(&array_lists_db.filter_pfx_al,
- clean_slurm_prefix);
- al_filter_bgpsec_cleanup(&array_lists_db.filter_bgps_al,
+ /* No need to cleanup prefixes (filters or assertions) */
+ al_filter_prefix_cleanup(&db->filter_pfx_al, NULL);
+ al_filter_bgpsec_cleanup(&db->filter_bgps_al,
clean_slurm_bgpsec);
- al_assertion_prefix_cleanup(&array_lists_db.assertion_pfx_al,
- clean_slurm_prefix);
- al_assertion_bgpsec_cleanup(&array_lists_db.assertion_bgps_al,
+ al_assertion_prefix_cleanup(&db->assertion_pfx_al, NULL);
+ al_assertion_bgpsec_cleanup(&db->assertion_bgps_al,
clean_slurm_bgpsec);
+ free(db);
}
--- /dev/null
+#ifndef SRC_SLURM_db_slurm_H_
+#define SRC_SLURM_db_slurm_H_
+
+#include <stdbool.h>
+#include "rtr/db/vrp.h"
+
+/* Flags to get data from structs */
+#define SLURM_COM_FLAG_NONE 0x00
+#define SLURM_COM_FLAG_ASN 0x01
+#define SLURM_COM_FLAG_COMMENT 0x02
+
+#define SLURM_PFX_FLAG_PREFIX 0x04
+#define SLURM_PFX_FLAG_MAX_LENGTH 0x08
+
+#define SLURM_BGPS_FLAG_SKI 0x04
+#define SLURM_BGPS_FLAG_ROUTER_KEY 0x08
+
+struct slurm_prefix {
+ uint8_t data_flag;
+ struct vrp vrp;
+};
+
+struct slurm_bgpsec {
+ uint8_t data_flag;
+ uint32_t asn;
+ unsigned char *ski;
+ unsigned char *router_public_key;
+};
+
+struct db_slurm;
+
+typedef int (*prefix_foreach_cb)(struct slurm_prefix *, void *);
+typedef int (*bgpsec_foreach_cb)(struct slurm_bgpsec *, void *);
+
+int db_slurm_create(struct db_slurm **);
+
+int db_slurm_add_prefix_filter(struct db_slurm *, struct slurm_prefix *, int);
+int db_slurm_add_prefix_assertion(struct db_slurm *, struct slurm_prefix *,
+ int);
+int db_slurm_add_bgpsec_filter(struct db_slurm *, struct slurm_bgpsec *, int);
+int db_slurm_add_bgpsec_assertion(struct db_slurm *, struct slurm_bgpsec *,
+ int);
+
+bool db_slurm_vrp_is_filtered(struct db_slurm *, struct vrp const *);
+bool db_slurm_bgpsec_is_filtered(struct db_slurm *, struct router_key const *);
+
+int db_slurm_foreach_filter_prefix(struct db_slurm *, prefix_foreach_cb,
+ void *);
+int db_slurm_foreach_filter_bgpsec(struct db_slurm *, bgpsec_foreach_cb,
+ void *);
+int db_slurm_foreach_assertion_prefix(struct db_slurm *, prefix_foreach_cb,
+ void *);
+int db_slurm_foreach_assertion_bgpsec(struct db_slurm *, bgpsec_foreach_cb,
+ void *);
+
+/* Set the last update to current datetime */
+void db_slurm_update_time(struct db_slurm *);
+/* Log the DB in human readable form at INFO level */
+void db_slurm_log(struct db_slurm *);
+
+void db_slurm_destroy(struct db_slurm *);
+
+#endif /* SRC_SLURM_db_slurm_H_ */
+++ /dev/null
-#ifndef SRC_SLURM_SLURM_DB_H_
-#define SRC_SLURM_SLURM_DB_H_
-
-#include <stdbool.h>
-#include "slurm/slurm_parser.h"
-#include "rtr/db/vrp.h"
-
-typedef int (*assertion_pfx_foreach_cb)(struct slurm_prefix *, void *);
-typedef int (*assertion_bgpsec_foreach_cb)(struct slurm_bgpsec *, void *);
-
-void slurm_db_init(void);
-
-int slurm_db_add_prefix_filter(struct slurm_prefix *, int);
-int slurm_db_add_prefix_assertion(struct slurm_prefix *, int);
-int slurm_db_add_bgpsec_filter(struct slurm_bgpsec *, int);
-int slurm_db_add_bgpsec_assertion(struct slurm_bgpsec *, int);
-
-bool slurm_db_vrp_is_filtered(struct vrp const *);
-int slurm_db_foreach_assertion_prefix(assertion_pfx_foreach_cb, void *);
-
-bool slurm_db_bgpsec_is_filtered(struct router_key const *);
-int slurm_db_foreach_assertion_bgpsec(assertion_bgpsec_foreach_cb, void *);
-
-void slurm_db_cleanup(void);
-
-#endif /* SRC_SLURM_SLURM_DB_H_ */
#include "log.h"
#include "config.h"
#include "common.h"
-#include "slurm/slurm_db.h"
#include "slurm/slurm_parser.h"
#define SLURM_FILE_EXTENSION ".slurm"
+/*
+ * Load the SLURM file(s) from the configured path, if the path is valid but no
+ * data is loaded (specific error for a SLURM folder) return -ENOENT error.
+ *
+ * Expect an EEXIST error from slurm_parse() if there's a syntax error.
+ */
static int
-slurm_load(bool *loaded)
+slurm_load(struct slurm_parser_params *params)
{
- int ctx = 0; /* Context (file number) */
- /* Optional configuration */
- *loaded = false;
- if (config_get_slurm() == NULL)
- return 0;
+ struct db_slurm *db;
+ int error;
- *loaded = true;
- slurm_db_init();
+ error = db_slurm_create(&db);
+ if (error)
+ return error;
- return process_file_or_dir(config_get_slurm(), SLURM_FILE_EXTENSION,
- slurm_parse, &ctx);
-}
+ params->db_slurm = db;
-static void
-slurm_cleanup(void)
-{
- /* Only if the SLURM was configured */
- if (config_get_slurm() != NULL)
- slurm_db_cleanup();
+ error = process_file_or_dir(config_get_slurm(), SLURM_FILE_EXTENSION,
+ slurm_parse, params);
+ if (error)
+ goto err;
+
+ /* A unmodified context means that no SLURM was loaded */
+ if(params->cur_ctx == 0) {
+ error = -ENOENT;
+ goto err;
+ }
+
+ return 0;
+err:
+ db_slurm_destroy(db);
+ params->db_slurm = NULL;
+ return error;
}
static int
slurm_pfx_filters_apply(struct vrp const *vrp, void *arg)
{
- struct db_table *table = arg;
+ struct slurm_parser_params *params = arg;
- if (slurm_db_vrp_is_filtered(vrp))
- db_table_remove_roa(table, vrp);
+ if (db_slurm_vrp_is_filtered(params->db_slurm, vrp))
+ db_table_remove_roa(params->db_table, vrp);
return 0;
}
static int
slurm_pfx_assertions_add(struct slurm_prefix *prefix, void *arg)
{
- struct db_table *table = arg;
+ struct slurm_parser_params *params = arg;
struct ipv4_prefix prefix4;
struct ipv6_prefix prefix6;
struct vrp vrp;
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);
+ return rtrhandler_handle_roa_v4(params->db_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 rtrhandler_handle_roa_v6(params->db_table, vrp.asn,
+ &prefix6, vrp.max_prefix_length);
}
pr_crit("Unknown addr family type: %u", vrp.addr_fam);
}
static int
-slurm_pfx_assertions_apply(struct db_table *base)
+slurm_pfx_assertions_apply(struct slurm_parser_params *params)
{
- return slurm_db_foreach_assertion_prefix(slurm_pfx_assertions_add,
- base);
+ return db_slurm_foreach_assertion_prefix(params->db_slurm,
+ slurm_pfx_assertions_add, params);
}
static int
slurm_bgpsec_filters_apply(struct router_key const *key, void *arg)
{
- struct db_table *table = arg;
+ struct slurm_parser_params *params = arg;
- if (slurm_db_bgpsec_is_filtered(key))
- db_table_remove_router_key(table, key);
+ if (db_slurm_bgpsec_is_filtered(params->db_slurm, key))
+ db_table_remove_router_key(params->db_table, key);
return 0;
}
static int
slurm_bgpsec_assertions_add(struct slurm_bgpsec *bgpsec, void *arg)
{
- struct db_table *table = arg;
+ struct slurm_parser_params *params = arg;
- return rtrhandler_handle_router_key(table, bgpsec->ski,
+ return rtrhandler_handle_router_key(params->db_table, bgpsec->ski,
bgpsec->asn, bgpsec->router_public_key);
}
static int
-slurm_bgpsec_assertions_apply(struct db_table *base)
+slurm_bgpsec_assertions_apply(struct slurm_parser_params *params)
{
- return slurm_db_foreach_assertion_bgpsec(slurm_bgpsec_assertions_add,
- base);
+ return db_slurm_foreach_assertion_bgpsec(params->db_slurm,
+ slurm_bgpsec_assertions_add, params);
+}
+
+static int
+slurm_create_parser_params(struct slurm_parser_params **result)
+{
+ struct slurm_parser_params *params;
+
+ params = malloc(sizeof(struct slurm_parser_params));
+ if (params == NULL)
+ return pr_enomem();
+
+ params->db_table = NULL;
+ params->db_slurm = NULL;
+ params->cur_ctx = 0;
+
+ *result = params;
+ return 0;
}
-/*
- * Load the SLURM file/dir and try to apply it on @base.
- *
- * On any error the SLURM won't be applied to @base.
- */
int
-slurm_apply(struct db_table **base)
+slurm_apply(struct db_table **base, struct db_slurm **last_slurm)
{
- struct db_table *new_base;
- bool loaded;
+ struct slurm_parser_params *params = NULL;
int error;
- loaded = false;
- error = slurm_load(&loaded);
+ if (config_get_slurm() == NULL)
+ return 0;
+
+ error = slurm_create_parser_params(¶ms);
if (error)
- goto cleanup;
+ return error;
+
+ error = slurm_load(params);
+ switch(error) {
+ case 0:
+ /* Use as last valid slurm */
+ if (*last_slurm != NULL)
+ db_slurm_destroy(*last_slurm);
+ *last_slurm = params->db_slurm;
+ db_slurm_update_time(*last_slurm);
+ break;
+ case -EEXIST:
+ /* Syntax error, use last valid slurm, log as info */
+ if (*last_slurm != NULL) {
+ pr_warn("A previous valid version of the SLURM exists and will be applied");
+ params->db_slurm = *last_slurm;
+ db_slurm_log(params->db_slurm);
+ }
+ break;
+ default:
+ /* Some other error, discard SLURM */
+ if (*last_slurm != NULL) {
+ pr_info("Discarding previous valid SLURM");
+ db_slurm_destroy(*last_slurm);
+ }
+ goto success;
+ }
- if (!loaded)
- return 0;
+ /* If there's no SLURM, stop */
+ if (params->db_slurm == NULL)
+ goto success;
/* Deep copy of the base so that updates can be reverted */
- error = db_table_clone(&new_base, *base);
+ error = db_table_clone(¶ms->db_table, *base);
if (error)
- goto cleanup;
+ goto release_slurm;
- error = db_table_foreach_roa(new_base, slurm_pfx_filters_apply,
- new_base);
+ error = db_table_foreach_roa(params->db_table, slurm_pfx_filters_apply,
+ params);
if (error)
- goto release_new;
+ goto release_table;
- error = db_table_foreach_router_key(new_base,
- slurm_bgpsec_filters_apply, new_base);
+ error = db_table_foreach_router_key(params->db_table,
+ slurm_bgpsec_filters_apply, params);
if (error)
- goto release_new;
+ goto release_table;
- error = slurm_pfx_assertions_apply(new_base);
- if (error) {
- goto release_new;
- }
+ error = slurm_pfx_assertions_apply(params);
+ if (error)
+ goto release_table;
- error = slurm_bgpsec_assertions_apply(new_base);
- if (!error) {
- db_table_destroy(*base);
- *base = new_base;
- goto cleanup;
+ error = slurm_bgpsec_assertions_apply(params);
+ if (error) {
+ goto release_table;
}
-release_new:
- db_table_destroy(new_base);
-cleanup:
- slurm_cleanup();
+ db_table_destroy(*base);
+ *base = params->db_table;
+success:
+ free(params);
+ return 0;
+release_table:
+ db_table_destroy(params->db_table);
+release_slurm:
+ db_slurm_destroy(params->db_slurm);
+ free(params);
return error;
}
#define SRC_SLURM_SLURM_LOADER_H_
#include "rtr/db/db_table.h"
+#include "slurm/db_slurm.h"
-int slurm_apply(struct db_table **);
+/*
+ * Load the SLURM file/dir and try to apply it on @db_table, point to the SLURM
+ * applied at @db_slurm.
+ *
+ * Return error only when there's a major issue on the process (no memory,
+ * SLURM loaded but something happened applying it).
+ *
+ * Return 0 when there's no problem applying the SLURM:
+ * - There's no SLURM configured
+ * - The SLURM was successfully applied
+ * - The @last_slurm was applied due to a syntax problem with a newer SLURM
+ * - SLURM configured but couldn't be read (file doesn't exists, no permission)
+ */
+int slurm_apply(struct db_table **, struct db_slurm **);
#endif /* SRC_SLURM_SLURM_LOADER_H_ */
#include "address.h"
#include "json_parser.h"
#include "object/router_key.h"
-#include "slurm/slurm_db.h"
/* JSON members */
#define SLURM_VERSION "slurmVersion"
return pr_err("SLURM member '%s' is required", name);
/* Context value, local to avoid forwarding the parameter */
-int cur_ctx;
+struct db_slurm *db;
+unsigned int cur_ctx;
-static int handle_json(json_t *, int *);
+static int handle_json(json_t *, struct db_slurm *, unsigned int *);
+/*
+ * Try to parse the SLURM file(s), any syntax error will return an EEXIST error
+ */
int
slurm_parse(char const *location, void *arg)
{
+ struct slurm_parser_params *params;
json_t *json_root;
json_error_t json_error;
+ unsigned int ctx;
int error;
+ params = arg;
+
json_root = json_load_file(location, JSON_REJECT_DUPLICATES,
&json_error);
if (json_root == NULL) {
pr_err("SLURM JSON error on line %d, column %d: %s",
json_error.line, json_error.column, json_error.text);
+ /* File was read, but has a content error */
+ if (json_error.position > 0)
+ goto syntax_err;
return -ENOENT;
}
- error = handle_json(json_root, arg);
-
+ ctx = params->cur_ctx;
+ error = handle_json(json_root, params->db_slurm, &ctx);
json_decref(json_root);
- return error;
+ if (error)
+ goto syntax_err;
+
+ params->cur_ctx = ctx;
+ return 0;
+
+syntax_err:
+ /* File exists, but has a syntax/content error */
+ return -EEXIST;
}
static int
return 0;
}
+/* There's no need to store the comment */
static int
-set_comment(json_t *object, char **comment, uint8_t *flag,
- size_t *members_loaded)
+set_comment(json_t *object, uint8_t *flag, size_t *members_loaded)
{
char const *tmp;
int error;
else if (error)
return error;
- *comment = strdup(tmp);
*flag = *flag | SLURM_COM_FLAG_COMMENT;
(*members_loaded)++;
/* Required by assertions */
if (error && is_assertion) {
if (error == -ENOENT)
- return pr_err("SLURM assertion %s is required", ROUTER_PUBLIC_KEY);
+ return pr_err("SLURM assertion %s is required",
+ ROUTER_PUBLIC_KEY);
return error;
}
slurm_prefix->vrp.prefix_length = 0;
slurm_prefix->vrp.max_prefix_length = 0;
slurm_prefix->vrp.addr_fam = 0;
- slurm_prefix->comment = NULL;
}
static int
if (error)
return error;
- error = set_comment(object, &result.comment, &result.data_flag,
- &member_count);
+ error = set_comment(object, &result.data_flag, &member_count);
if (error)
return error;
/* A single comment isn't valid */
- if (result.data_flag == SLURM_COM_FLAG_COMMENT) {
- pr_err("Single comments aren't valid");
- error = -EINVAL;
- goto release_comment;
- }
+ if (result.data_flag == SLURM_COM_FLAG_COMMENT)
+ return pr_err("Single comments aren't valid");
/* A filter must have ASN and/or prefix */
if (!is_assertion) {
if ((result.data_flag &
- (SLURM_COM_FLAG_ASN | SLURM_PFX_FLAG_PREFIX)) == 0) {
- pr_err("Prefix filter must have an asn and/or prefix");
- error = -EINVAL;
- goto release_comment;
- }
+ (SLURM_COM_FLAG_ASN | SLURM_PFX_FLAG_PREFIX)) == 0)
+ return pr_err("Prefix filter must have an asn and/or prefix");
/* Validate expected members */
- if (!json_valid_members_count(object, member_count)) {
- pr_err("Prefix filter has unknown members (see RFC 8416 section 3.3.1)");
- error = -EINVAL;
- goto release_comment;
- }
+ if (!json_valid_members_count(object, member_count))
+ return pr_err("Prefix filter has unknown members (see RFC 8416 section 3.3.1)");
- error = slurm_db_add_prefix_filter(&result, cur_ctx);
+ error = db_slurm_add_prefix_filter(db, &result, cur_ctx);
if (error)
- goto release_comment;
+ return error;
return 0;
}
* set_asn and set_prefix
*/
- if ((result.data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0)
- if (result.vrp.prefix_length > result.vrp.max_prefix_length) {
- pr_err(
- "Prefix length is greater than max prefix length");
- error = -EINVAL;
- goto release_comment;
- }
+ if ((result.data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0 &&
+ result.vrp.prefix_length > result.vrp.max_prefix_length)
+ return pr_err("Prefix length is greater than max prefix length");
/* Validate expected members */
- if (!json_valid_members_count(object, member_count)) {
- pr_err("Prefix assertion has unknown members (see RFC 8416 section 3.4.1)");
- error = -EINVAL;
- goto release_comment;
- }
+ if (!json_valid_members_count(object, member_count))
+ return pr_err("Prefix assertion has unknown members (see RFC 8416 section 3.4.1)");
- error = slurm_db_add_prefix_assertion(&result, cur_ctx);
+ error = db_slurm_add_prefix_assertion(db, &result, cur_ctx);
if (error)
- goto release_comment;
+ return error;
return 0;
-
-release_comment:
- free(result.comment);
- return error;
}
static int
slurm_bgpsec->asn = 0;
slurm_bgpsec->ski = NULL;
slurm_bgpsec->router_public_key = NULL;
- slurm_bgpsec->comment = NULL;
}
static int
if (error)
goto release_ski;
- error = set_comment(object, &result.comment, &result.data_flag,
- &member_count);
+ error = set_comment(object, &result.data_flag, &member_count);
if (error)
goto release_router_key;
if (result.data_flag == SLURM_COM_FLAG_COMMENT) {
pr_err("Single comments aren't valid");
error = -EINVAL;
- goto release_comment;
+ goto release_router_key;
}
/* A filter must have ASN and/or SKI */
(SLURM_COM_FLAG_ASN | SLURM_BGPS_FLAG_SKI)) == 0) {
pr_err("BGPsec filter must have an asn and/or SKI");
error = -EINVAL;
- goto release_comment;
+ goto release_router_key;
}
/* Validate expected members */
if (!json_valid_members_count(object, member_count)) {
pr_err("BGPsec filter has unknown members (see RFC 8416 section 3.3.2)");
error = -EINVAL;
- goto release_comment;
+ goto release_router_key;
}
- error = slurm_db_add_bgpsec_filter(&result, cur_ctx);
+ error = db_slurm_add_bgpsec_filter(db, &result, cur_ctx);
if (error)
- goto release_comment;
+ goto release_router_key;
return 0;
}
if (!json_valid_members_count(object, member_count)) {
pr_err("BGPsec assertion has unknown members (see RFC 8416 section 3.4.2)");
error = -EINVAL;
- goto release_comment;
+ goto release_router_key;
}
- error = slurm_db_add_bgpsec_assertion(&result, cur_ctx);
+ error = db_slurm_add_bgpsec_assertion(db, &result, cur_ctx);
if (error)
- goto release_comment;
+ goto release_router_key;
return 0;
-release_comment:
- free(result.comment);
release_router_key:
free(result.router_public_key);
release_ski:
}
static int
-handle_json(json_t *root, int *ctx)
+handle_json(json_t *root, struct db_slurm *db_slurm, unsigned int *ctx)
{
size_t expected_members;
int error;
return pr_err("The root of the SLURM is not a JSON object.");
cur_ctx = *ctx;
+ db = db_slurm;
error = load_version(root);
if (error)
#ifndef SRC_SLURM_SLURM_PARSER_H_
#define SRC_SLURM_SLURM_PARSER_H_
-#include "rtr/db/vrp.h"
+#include "rtr/db/db_table.h"
+#include "slurm/db_slurm.h"
-/* Flags to get data from structs */
-#define SLURM_COM_FLAG_NONE 0x00
-#define SLURM_COM_FLAG_ASN 0x01
-#define SLURM_COM_FLAG_COMMENT 0x02
-
-#define SLURM_PFX_FLAG_PREFIX 0x04
-#define SLURM_PFX_FLAG_MAX_LENGTH 0x08
-
-#define SLURM_BGPS_FLAG_SKI 0x04
-#define SLURM_BGPS_FLAG_ROUTER_KEY 0x08
-
-struct slurm_prefix {
- uint8_t data_flag;
- struct vrp vrp;
- char *comment;
+struct slurm_parser_params {
+ struct db_table *db_table;
+ struct db_slurm *db_slurm;
+ unsigned int cur_ctx; /* Context (file number) */
};
-struct slurm_bgpsec {
- uint8_t data_flag;
- uint32_t asn;
- unsigned char *ski;
- unsigned char *router_public_key;
- char *comment;
-};
-
-
int slurm_parse(char const *, void *);
#include "rtr/db/db_table.c"
#include "rtr/db/rtr_db_impersonator.c"
#include "rtr/db/vrps.c"
-#include "slurm/slurm_db.c"
+#include "slurm/db_slurm.c"
#include "slurm/slurm_loader.c"
#include "slurm/slurm_parser.c"
#include "rtr/db/db_table.c"
#include "rtr/db/rtr_db_impersonator.c"
#include "rtr/db/vrps.c"
-#include "slurm/slurm_db.c"
+#include "slurm/db_slurm.c"
#include "slurm/slurm_loader.c"
#include "slurm/slurm_parser.c"