summaryrefslogtreecommitdiffstats
path: root/rtrlib/rtr_mgr.h
blob: b267723db985f33ec4a42ecc3fd88d7bef6446bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/*
 * 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
 * <a href="https://tools.ietf.org/html/rfc6810">IETF
 * RFC 6810</a> for details about error handling).\n
 * RTRlib also supports a Retry Interval (see
 * <a href="https://tools.ietf.org/html/draft-ietf-sidr-rpki-rtr-rfc6810-bis">
 * draft-ietf-sidr-rpki-rtr-rfc6810-bis</a>).
 * 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 <pthread.h>
#include <stdint.h>

/**
 * @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
/** @} */