1 #include <check.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 
5 #include "common.c"
6 #include "log.c"
7 #include "impersonator.c"
8 #include "rtr/err_pdu.c"
9 #include "rtr/pdu.c"
10 #include "rtr/primitive_reader.c"
11 #include "rtr/db/rtr_db_impersonator.c"
12 
13 /*
14  * Used to be a wrapper for `buffer2fd()`, but that's no longer necessary.
15  *
16  * Converts the @buffer buffer into PDU @obj, using the @cb function.
17  * Also takes care of the header validation.
18  */
19 #define BUFFER2FD(buffer, cb, obj) {					\
20 	struct pdu_header header;					\
21 	struct pdu_reader reader;					\
22 									\
23 	pdu_reader_init(&reader, buffer, sizeof(buffer));		\
24 	init_pdu_header(&header);					\
25 	ck_assert_int_eq(0, cb(&header, &reader, obj));			\
26 	assert_pdu_header(&(obj)->header);				\
27 }
28 
29 /* Impersonator functions */
30 
31 #define IMPERSONATE_HANDLER(name)					\
32 	int								\
33 	handle_## name ##_pdu(int fd, struct rtr_request const *req) {	\
34 		return 0;						\
35 	}
36 
37 uint16_t
get_current_session_id(uint8_t rtr_version)38 get_current_session_id(uint8_t rtr_version)
39 {
40 	return 12345;
41 }
42 
43 int
clients_set_rtr_version(int fd,uint8_t rtr_version)44 clients_set_rtr_version(int fd, uint8_t rtr_version)
45 {
46 	return 0;
47 }
48 
49 int
clients_get_rtr_version_set(int fd,bool * is_set,uint8_t * rtr_version)50 clients_get_rtr_version_set(int fd, bool *is_set, uint8_t *rtr_version)
51 {
52 	(*is_set) = true;
53 	(*rtr_version) = RTR_V0;
54 	return 0;
55 }
56 
57 IMPERSONATE_HANDLER(serial_notify)
IMPERSONATE_HANDLER(serial_query)58 IMPERSONATE_HANDLER(serial_query)
59 IMPERSONATE_HANDLER(reset_query)
60 IMPERSONATE_HANDLER(cache_response)
61 IMPERSONATE_HANDLER(ipv4_prefix)
62 IMPERSONATE_HANDLER(ipv6_prefix)
63 IMPERSONATE_HANDLER(end_of_data)
64 IMPERSONATE_HANDLER(cache_reset)
65 IMPERSONATE_HANDLER(router_key)
66 IMPERSONATE_HANDLER(error_report)
67 
68 int
69 send_error_report_pdu(int fd, uint8_t version, uint16_t code,
70     struct rtr_request const *request, char *message)
71 {
72 	pr_op_info("    Server sent Error Report %u: '%s'", code,
73 	    /* gcc is complaining about logging NULL messages. WTF */
74 	    (message != NULL) ? message : "");
75 	return 0;
76 }
77 
78 int
rtrhandler_handle_roa_v4(struct db_table * table,uint32_t asn,struct ipv4_prefix const * prefix4,uint8_t max_length)79 rtrhandler_handle_roa_v4(struct db_table *table, uint32_t asn,
80     struct ipv4_prefix const *prefix4, uint8_t max_length)
81 {
82 	return 0;
83 }
84 
85 int
rtrhandler_handle_roa_v6(struct db_table * table,uint32_t asn,struct ipv6_prefix const * prefix6,uint8_t max_length)86 rtrhandler_handle_roa_v6(struct db_table *table, uint32_t asn,
87     struct ipv6_prefix const *prefix6, uint8_t max_length)
88 {
89 	return 0;
90 }
91 
92 int
rtrhandler_handle_router_key(struct db_table * table,unsigned char const * ski,uint32_t as,unsigned char const * spk)93 rtrhandler_handle_router_key(struct db_table *table,
94     unsigned char const *ski, uint32_t as, unsigned char const *spk)
95 {
96 	return 0;
97 }
98 
99 /* End of impersonator */
100 
101 static void
init_pdu_header(struct pdu_header * header)102 init_pdu_header(struct pdu_header *header)
103 {
104 	header->protocol_version = RTR_V0;
105 	header->pdu_type = 22;
106 	header->m.reserved = get_current_session_id(RTR_V0);
107 	header->length = 0x00000020;
108 }
109 
110 static void
assert_pdu_header(struct pdu_header * header)111 assert_pdu_header(struct pdu_header *header)
112 {
113 	ck_assert_uint_eq(header->protocol_version, 0);
114 	ck_assert_uint_eq(header->pdu_type, 22);
115 	ck_assert_uint_eq(header->m.reserved, get_current_session_id(RTR_V0));
116 	ck_assert_uint_eq(header->length, 0x00000020);
117 }
118 
START_TEST(test_pdu_header_from_stream)119 START_TEST(test_pdu_header_from_stream)
120 {
121 	unsigned char input[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
122 	struct pdu_reader reader;
123 	struct pdu_header header;
124 
125 	pdu_reader_init(&reader, input, ARRAY_LEN(input));
126 	/* Read the header into its buffer. */
127 	ck_assert_int_eq(0, pdu_header_from_reader(&reader, &header));
128 
129 	ck_assert_uint_eq(header.protocol_version, 0);
130 	ck_assert_uint_eq(header.pdu_type, 1);
131 	ck_assert_uint_eq(header.m.reserved, 0x0203);
132 	ck_assert_uint_eq(header.length, 0x04050607);
133 }
134 END_TEST
135 
START_TEST(test_serial_notify_from_stream)136 START_TEST(test_serial_notify_from_stream)
137 {
138 	unsigned char input[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
139 	struct serial_notify_pdu pdu;
140 
141 	BUFFER2FD(input, serial_notify_from_stream, &pdu);
142 	ck_assert_uint_eq(pdu.serial_number, 0x010203);
143 }
144 END_TEST
145 
START_TEST(test_serial_query_from_stream)146 START_TEST(test_serial_query_from_stream)
147 {
148 	unsigned char input[] = { 13, 14, 15, 16, 17 };
149 	struct serial_query_pdu pdu;
150 
151 	BUFFER2FD(input, serial_query_from_stream, &pdu);
152 	ck_assert_uint_eq(pdu.serial_number, 0x0d0e0f10);
153 }
154 END_TEST
155 
START_TEST(test_reset_query_from_stream)156 START_TEST(test_reset_query_from_stream)
157 {
158 	unsigned char input[] = { 18, 19 };
159 	struct reset_query_pdu pdu;
160 
161 	BUFFER2FD(input, reset_query_from_stream, &pdu);
162 }
163 END_TEST
164 
START_TEST(test_cache_response_from_stream)165 START_TEST(test_cache_response_from_stream)
166 {
167 	unsigned char input[] = { 18, 19 };
168 	struct cache_response_pdu pdu;
169 
170 	BUFFER2FD(input, cache_response_from_stream, &pdu);
171 }
172 END_TEST
173 
START_TEST(test_ipv4_prefix_from_stream)174 START_TEST(test_ipv4_prefix_from_stream)
175 {
176 	unsigned char input[] = { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
177 			29, 30, 31, 32 };
178 	struct ipv4_prefix_pdu pdu;
179 
180 	BUFFER2FD(input, ipv4_prefix_from_stream, &pdu);
181 	ck_assert_uint_eq(pdu.flags, 18);
182 	ck_assert_uint_eq(pdu.prefix_length, 19);
183 	ck_assert_uint_eq(pdu.max_length, 20);
184 	ck_assert_uint_eq(pdu.zero, 21);
185 	ck_assert_uint_eq(pdu.ipv4_prefix.s_addr, 0x16171819);
186 	ck_assert_uint_eq(pdu.asn, 0x1a1b1c1d);
187 }
188 END_TEST
189 
START_TEST(test_ipv6_prefix_from_stream)190 START_TEST(test_ipv6_prefix_from_stream)
191 {
192 	unsigned char input[] = { 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
193 			44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
194 			58, 59, 60 };
195 	struct ipv6_prefix_pdu pdu;
196 	struct in6_addr tmp;
197 
198 	BUFFER2FD(input, ipv6_prefix_from_stream, &pdu);
199 	ck_assert_uint_eq(pdu.flags, 33);
200 	ck_assert_uint_eq(pdu.prefix_length, 34);
201 	ck_assert_uint_eq(pdu.max_length, 35);
202 	ck_assert_uint_eq(pdu.zero, 36);
203 	in6_addr_init(&tmp, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334);
204 	ck_assert(IN6_ARE_ADDR_EQUAL(&tmp, &pdu.ipv6_prefix));
205 	ck_assert_uint_eq(pdu.asn, 0x35363738);
206 }
207 END_TEST
208 
START_TEST(test_end_of_data_from_stream)209 START_TEST(test_end_of_data_from_stream)
210 {
211 	unsigned char input[] = { 61, 62, 63, 64 };
212 	struct end_of_data_pdu pdu;
213 
214 	BUFFER2FD(input, end_of_data_from_stream, &pdu);
215 	ck_assert_uint_eq(pdu.serial_number, 0x3d3e3f40);
216 }
217 END_TEST
218 
START_TEST(test_cache_reset_from_stream)219 START_TEST(test_cache_reset_from_stream)
220 {
221 	unsigned char input[] = { 65, 66, 67 };
222 	struct cache_reset_pdu pdu;
223 
224 	BUFFER2FD(input, cache_reset_from_stream, &pdu);
225 }
226 END_TEST
227 
START_TEST(test_error_report_from_stream)228 START_TEST(test_error_report_from_stream)
229 {
230 	unsigned char input[] = {
231 			/* Sub-pdu length */
232 			0, 0, 0, 12,
233 			/* Sub-pdu with header*/
234 			1, 0, 2, 3, 0, 0, 0, 12, 1, 2, 3, 4,
235 			/* Error msg length */
236 			0, 0, 0, 5,
237 			/* Error msg */
238 			'h', 'e', 'l', 'l', 'o',
239 			/* Garbage */
240 			1, 2, 3, 4,
241 	};
242 	struct error_report_pdu pdu;
243 	struct serial_notify_pdu sub_pdu;
244 	struct pdu_header sub_pdu_header;
245 	struct pdu_reader reader;
246 
247 	BUFFER2FD(input, error_report_from_stream, &pdu);
248 
249 	/* Get the erroneous PDU as a serial notify */
250 	pdu_reader_init(&reader, pdu.erroneous_pdu, pdu.error_pdu_length);
251 
252 	ck_assert_int_eq(0, pdu_header_from_reader(&reader, &sub_pdu_header));
253 	ck_assert_int_eq(0, serial_notify_from_stream(&sub_pdu_header, &reader,
254 	    &sub_pdu));
255 
256 	ck_assert_uint_eq(sub_pdu.header.protocol_version, 1);
257 	ck_assert_uint_eq(sub_pdu.header.pdu_type, 0);
258 	ck_assert_uint_eq(sub_pdu.header.m.reserved, 0x0203);
259 	ck_assert_uint_eq(sub_pdu.header.length, 12);
260 	ck_assert_uint_eq(sub_pdu.serial_number, 0x01020304);
261 	ck_assert_str_eq(pdu.error_message, "hello");
262 
263 	free(pdu.error_message);
264 }
265 END_TEST
266 
START_TEST(test_interrupted)267 START_TEST(test_interrupted)
268 {
269 	unsigned char input[] = { 0, 1 };
270 	struct pdu_reader reader;
271 	struct pdu_header header;
272 
273 	pdu_reader_init(&reader, input, ARRAY_LEN(input));
274 	ck_assert_int_eq(-EPIPE, pdu_header_from_reader(&reader, &header));
275 }
276 END_TEST
277 
pdu_suite(void)278 Suite *pdu_suite(void)
279 {
280 	Suite *suite;
281 	TCase *core, *errors;
282 
283 	core = tcase_create("Core");
284 	tcase_add_test(core, test_pdu_header_from_stream);
285 	tcase_add_test(core, test_serial_notify_from_stream);
286 	tcase_add_test(core, test_serial_notify_from_stream);
287 	tcase_add_test(core, test_serial_query_from_stream);
288 	tcase_add_test(core, test_reset_query_from_stream);
289 	tcase_add_test(core, test_cache_response_from_stream);
290 	tcase_add_test(core, test_ipv4_prefix_from_stream);
291 	tcase_add_test(core, test_ipv6_prefix_from_stream);
292 	tcase_add_test(core, test_end_of_data_from_stream);
293 	tcase_add_test(core, test_cache_reset_from_stream);
294 	tcase_add_test(core, test_error_report_from_stream);
295 
296 	errors = tcase_create("Errors");
297 	tcase_add_test(errors, test_interrupted);
298 
299 	suite = suite_create("PDU");
300 	suite_add_tcase(suite, core);
301 	suite_add_tcase(suite, errors);
302 	return suite;
303 }
304 
main(void)305 int main(void)
306 {
307 	Suite *suite;
308 	SRunner *runner;
309 	int tests_failed;
310 
311 	suite = pdu_suite();
312 
313 	runner = srunner_create(suite);
314 	srunner_run_all(runner, CK_NORMAL);
315 	tests_failed = srunner_ntests_failed(runner);
316 	srunner_free(runner);
317 
318 	return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
319 }
320