/* * This file is part of RTRlib. * * This file is subject to the terms and conditions of the MIT license. * See the file LICENSE in the top level directory for more details. * * Website: http://rtrlib.realmv6.org/ */ /** * @defgroup mod_rtr_mgr_h RTR connection manager * @brief The RTR connection manager maintains multiple groups of @ref * rtr_socket "RTR sockets". * @details The RTR connection manager is initialized with one or multiple * groups of rtr_sockets. Each group is configured with a preference * value and contains a set of rtr_socket RTR sockets. It connects to all * sockets of the group with the lowest preference value.\n * In case of failures, the connection manager establishes connections to * RTR servers of another group with the next lowest preference value (see * IETF * RFC 6810 for details about error handling).\n * RTRlib also supports a Retry Interval (see * * draft-ietf-sidr-rpki-rtr-rfc6810-bis). * If a more preferred group is online again, the RTR connection manager * will switch back and close connections to the caches of the less * preferred group. * * @{ * @example rtr_mgr.c * Usage example of the RTR connection manager. */ #ifndef RTR_MGR #define RTR_MGR #include "rtrlib/pfx/pfx.h" #include "rtrlib/spki/spkitable.h" #include #include /** * @brief Status of a rtr_mgr_group. */ enum rtr_mgr_status { /** RTR sockets are disconnected */ RTR_MGR_CLOSED, /** RTR sockets trying to establish a connection. */ RTR_MGR_CONNECTING, /** All RTR sockets of the group are synchronized with rtr servers. */ RTR_MGR_ESTABLISHED, /** Error occurred on at least one RTR socket. */ RTR_MGR_ERROR, }; /** * @brief A set of RTR sockets. * @param sockets Array of rtr_socket pointer. The tr_socket element of * the rtr_socket must be associated with an initialized # * transport socket. * @param sockets_len Number of elements in the sockets array. * @param preference The preference value of this group. * Groups with lower preference values are preferred. * @param status Status of the group. */ struct rtr_mgr_group { struct rtr_socket **sockets; unsigned int sockets_len; uint8_t preference; enum rtr_mgr_status status; }; typedef void (*rtr_mgr_status_fp)(const struct rtr_mgr_group *, enum rtr_mgr_status, const struct rtr_socket *, void *); struct tommy_list_wrapper; // TODO Add refresh, expire, and retry intervals to config for easier access. struct rtr_mgr_config { struct tommy_list_wrapper *groups; unsigned int len; pthread_mutex_t mutex; rtr_mgr_status_fp status_fp; void *status_fp_data; struct pfx_table *pfx_table; struct spki_table *spki_table; }; /** * @brief Initializes a rtr_mgr_config. * @param[out] config_out The rtr_mgr_config that will be initialized by this * function. On error, *config_out will be NULL! * @param[in] groups Linked list of rtr_mgr_group. Every RTR socket in an * rtr_mgr_group must be assoziated with an initialized * transport socket. A Transport socket is only allowed to be * associated with one rtr socket. The preference values must * be unique in the linked list. More than one rtr_mgr_group * with the same preference value isn't allowed. * @param[in] groups_len Number of elements in the groups array. Must be >= 1. * @param[in] refresh_interval Interval in seconds between serial queries that * are sent to the server. Must be >= 1 and <= * 86400s (1d), recommended default is 3600s (1h). * @param[in] expire_interval Stored validation records will be deleted if * cache was unable to refresh data for this period. * The value should be twice the refresh_interval * and must be >= 600s (10min) and <= 172800s (2d). * The recommended default is 7200s (2h). * @param[in] retry_interval This parameter tells the router how long to wait * (in seconds) before retrying a failed Serial Query * or Reset Query. * The value must be >= 1s and <= 7200s (2h). * The recommended default is 600s (10min). * @param[in] update_fp Pointer to pfx_update_fp callback, that is executed for every added and removed pfx_record. * @param[in] spki_update_fp Pointer to spki_update_fp callback, that is executed for every added and removed spki_record. * @param[in] status_fp Pointer to a function that is called if the connection * status from one of the socket groups is changed. * @param[in] status_fp_data Pointer to a memory area that is passed to the * status_fp function. Memory area can be freely used * to pass user-defined data to the status_fp * callback. * @return RTR_ERROR If an error occurred * @return RTR_INVALID_PARAM If refresh_interval or expire_interval is invalid. * @return RTR_SUCCESS On success. */ int rtr_mgr_init(struct rtr_mgr_config **config_out, struct rtr_mgr_group groups[], const unsigned int groups_len, const unsigned int refresh_interval, const unsigned int expire_interval, const unsigned int retry_interval, const pfx_update_fp update_fp, const spki_update_fp spki_update_fp, const rtr_mgr_status_fp status_fp, void *status_fp_data); /** * @brief Adds a new rtr_mgr_group to the linked list of a initialized config. * @details A new group must have at least one rtr_socket associated * with it. This socket must have at least one initialized * transport socket associated with it. The new group must * have a preference value that is none of the already present * groups have. More than one rtr_mgr_group with the same * preference is not allowed. * @param config A rtr_mgr_config struct that has been initialized * previously with rtr_mgr_init * @param group A rtr_mgr_group with at least one rtr_socket and a * preference value that no existing group has. * @return RTR_INVALID_PARAM If a group with the same preference value already * exists. * @return RTR_ERROR If an error occurred while adding the group. * @return RTR_SUCCESS If the group was successfully added. * */ int rtr_mgr_add_group(struct rtr_mgr_config *config, const struct rtr_mgr_group *group); /** * @brief Removes an existing rtr_mgr_group from the linked list of config. * @details The group to be removed is identified by its preference value. * Should the group to be removed be currently active, it will be * shut down and the next best group will be spun up. * @param config A rtr_mgr_config struct that has been initialized previously * with rtr_mgr_init * @param preference The preference value of the group to be removed. * @return RTR_ERROR If no group with this preference value exists. * @return RTR_SUCCESS If group was successfully removed. * */ int rtr_mgr_remove_group(struct rtr_mgr_config *config, unsigned int preference); /** * @brief Frees all resources that were allocated from the rtr_mgr. * @details rtr_mgr_stop must be called before, to shutdown all rtr_sockets. * @param[in] config rtr_mgr_config. */ void rtr_mgr_free(struct rtr_mgr_config *config); /** * @brief Establishes rtr_socket connections * @details Establishes the connection with the rtr_sockets of the group * with the lowest preference value and handles errors as defined in the * RPKI-RTR protocol. * @param[in] config Pointer to an initialized rtr_mgr_config. * @return RTR_SUCCESS On success * @return RTR_ERROR On error */ int rtr_mgr_start(struct rtr_mgr_config *config); /** * @brief Terminates rtr_socket connections * @details Terminates all rtr_socket connections defined in the config. * All pfx_records received from these sockets will be purged. * @param[in] config The rtr_mgr_config struct */ void rtr_mgr_stop(struct rtr_mgr_config *config); /** * @brief Check if rtr_mgr_group is fully synchronized with at least one group. * @param[in] config The rtr_mgr_config. * @return true If pfx_table stores non-outdated pfx_records * @return false If pfx_table isn't fully synchronized with at least one group. */ bool rtr_mgr_conf_in_sync(struct rtr_mgr_config *config); /** * @brief Validates the origin of a BGP-Route. * @param[in] config The rtr_mgr_config * @param[in] asn Autonomous system number of the Origin-AS of the prefix * @param[in] prefix Announced network prefix * @param[in] mask_len Length of the network mask of the announced prefix * @param[out] result Outcome of the validation * @return PFX_SUCCESS On success. * @return PFX_ERROR If an error occurred. */ int rtr_mgr_validate(struct rtr_mgr_config *config, const uint32_t asn, const struct lrtr_ip_addr *prefix, const uint8_t mask_len, enum pfxv_state *result); /** * @brief Returns all SPKI records which match the given ASN and SKI. * @param[in] config * @param[in] asn Autonomous system number of the Origin-AS * @param[in] ski the SKI to search for * @param[out] result a array of all matching spki_records * @param[out] result_count number of returned spki_records * @return SPKI_SUCCESS On success * @return SPKI_ERROR If an error occurred */ int rtr_mgr_get_spki(struct rtr_mgr_config *config, const uint32_t asn, uint8_t *ski, struct spki_record **result, unsigned int *result_count); /** * @brief Converts a rtr_mgr_status to a String. * @param[in] status state to convert to a string. * @return NULL If status isn't a valid rtr_mgr_status. * @return !=NULL The rtr_rtr_mgr_status as String. */ const char *rtr_mgr_status_to_str(enum rtr_mgr_status status); /** * @brief Iterates over all IPv4 records in the pfx_table. * @details For every pfx_record the function fp is called. The pfx_record and * the data pointer is passed to the fp. * @param[in] config rtr_mgr_config * @param[in] fp Pointer to callback function with signature \c pfx_for_each_fp. * @param[in] data This parameter is forwarded to the callback function. */ void rtr_mgr_for_each_ipv4_record(struct rtr_mgr_config *config, pfx_for_each_fp fp, void *data); /** * @brief Iterates over all IPv6 records in the pfx_table. * @details For every pfx_record the function fp is called. The pfx_record and * the data pointer is passed to the fp. * @param[in] config rtr_mgr_config * @param[in] fp Pointer to callback function with signature \c pfx_for_each_fp. * @param[in] data This parameter is forwarded to the callback function. */ void rtr_mgr_for_each_ipv6_record(struct rtr_mgr_config *config, pfx_for_each_fp fp, void *data); /** * @brief Returns the first, thus active group. * @param[in] config The rtr_mgr_config * @return rtr_mgr_group The head of the linked list. */ struct rtr_mgr_group *rtr_mgr_get_first_group(struct rtr_mgr_config *config); int rtr_mgr_for_each_group(struct rtr_mgr_config *config, void (*fp)(const struct rtr_mgr_group *group, void *data), void *data); #endif /** @} */