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