1 #include <check.h>
2 #include <stdlib.h>
3 
4 #include "common.c"
5 #include "log.c"
6 #include "impersonator.c"
7 #include "types/address.c"
8 #include "types/delta.c"
9 #include "types/router_key.c"
10 #include "types/vrp.c"
11 #include "rtr/db/delta.c"
12 #include "rtr/db/db_table.c"
13 
14 #define ADDR1 htonl(0xC0000201) /* 192.0.2.1 */
15 #define ADDR2 htonl(0xC0000202) /* 192.0.2.2 */
16 
17 #define TOTAL_ROAS 10
18 static bool roas_found[TOTAL_ROAS];
19 static unsigned int total_found;
20 
21 static bool
vrp_equals_v4(struct vrp const * vrp,uint8_t as,uint32_t addr,uint8_t prefix_len,uint8_t max_prefix_len)22 vrp_equals_v4(struct vrp const *vrp, uint8_t as, uint32_t addr,
23     uint8_t prefix_len, uint8_t max_prefix_len)
24 {
25 	return (AF_INET == vrp->addr_fam)
26 	    && (as == vrp->asn)
27 	    && (addr == vrp->prefix.v4.s_addr)
28 	    && (prefix_len == vrp->prefix_length)
29 	    && (max_prefix_len == vrp->max_prefix_length);
30 }
31 
32 static bool
vrp_equals_v6(struct vrp const * vrp,uint8_t as,uint32_t addr,uint8_t prefix_len,uint8_t max_prefix_len)33 vrp_equals_v6(struct vrp const *vrp, uint8_t as, uint32_t addr,
34     uint8_t prefix_len, uint8_t max_prefix_len)
35 {
36 	struct in6_addr tmp;
37 	in6_addr_init(&tmp, 0x20010DB8u, 0, 0, addr);
38 
39 	return (AF_INET6 == vrp->addr_fam)
40 	    && (as == vrp->asn)
41 	    && IN6_ARE_ADDR_EQUAL(&tmp, &vrp->prefix.v6)
42 	    && (prefix_len == vrp->prefix_length)
43 	    && (max_prefix_len == vrp->max_prefix_length);
44 }
45 
46 static int
update_found(array_index index)47 update_found(array_index index)
48 {
49 	ck_assert_int_eq(false, roas_found[index]);
50 	roas_found[index] = true;
51 	total_found++;
52 	return 0;
53 }
54 
55 static int
foreach_cb(struct vrp const * vrp,void * arg)56 foreach_cb(struct vrp const *vrp, void *arg)
57 {
58 	char const *str;
59 
60 	if (vrp_equals_v4(vrp, 10, ADDR1, 24, 32))
61 		return update_found(0);
62 	if (vrp_equals_v4(vrp, 11, ADDR1, 24, 32))
63 		return update_found(1);
64 	if (vrp_equals_v4(vrp, 10, ADDR2, 24, 32))
65 		return update_found(2);
66 	if (vrp_equals_v4(vrp, 10, ADDR1, 25, 32))
67 		return update_found(3);
68 	if (vrp_equals_v4(vrp, 10, ADDR1, 24, 30))
69 		return update_found(4);
70 
71 	if (vrp_equals_v6(vrp, 10, 1, 120, 128))
72 		return update_found(5);
73 	if (vrp_equals_v6(vrp, 11, 1, 120, 128))
74 		return update_found(6);
75 	if (vrp_equals_v6(vrp, 10, 2, 120, 128))
76 		return update_found(7);
77 	if (vrp_equals_v6(vrp, 10, 1, 121, 128))
78 		return update_found(8);
79 	if (vrp_equals_v6(vrp, 10, 1, 120, 127))
80 		return update_found(9);
81 
82 	switch (vrp->addr_fam) {
83 	case AF_INET:
84 		str = v4addr2str(&vrp->prefix.v4);
85 		break;
86 	case AF_INET6:
87 		str = v6addr2str(&vrp->prefix.v6);
88 		break;
89 	default:
90 		ck_abort_msg("Unknown address family: %u", vrp->addr_fam);
91 	}
92 
93 	ck_abort_msg("Foreach is looping over unknown VRP %u/%s/%u/%u.",
94 	    vrp->asn, str, vrp->prefix_length, vrp->max_prefix_length);
95 }
96 
START_TEST(test_basic)97 START_TEST(test_basic)
98 {
99 	struct ipv4_prefix prefix4;
100 	struct ipv6_prefix prefix6;
101 	struct db_table *table;
102 	array_index i;
103 
104 	table = db_table_create();
105 	ck_assert_ptr_ne(NULL, table);
106 
107 	prefix4.addr.s_addr = ADDR1;
108 	prefix4.len = 24;
109 	in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
110 	prefix6.len = 120;
111 
112 	/* Duplicates should be transparently not re-added. */
113 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
114 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
115 
116 	/* Change the AS slightly */
117 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 11, &prefix4, 32));
118 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 11, &prefix4, 32));
119 
120 	/* Change the prefix slightly */
121 	prefix4.addr.s_addr = ADDR2;
122 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
123 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
124 
125 	prefix4.addr.s_addr = ADDR1;
126 	prefix4.len = 25;
127 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
128 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
129 
130 	/* Change the max prefix length (counts as duplicate) */
131 	prefix4.len = 24;
132 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 30));
133 	ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 30));
134 
135 	/* IPv6 */
136 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
137 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
138 
139 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 11, &prefix6, 128));
140 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 11, &prefix6, 128));
141 
142 	in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 2);
143 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
144 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
145 
146 	in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
147 	prefix6.len = 121;
148 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
149 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
150 
151 	prefix6.len = 120;
152 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 127));
153 	ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 127));
154 
155 	/* Check table contents */
156 	memset(roas_found, 0, sizeof(roas_found));
157 	total_found = 0;
158 	ck_assert_int_eq(0, db_table_foreach_roa(table, foreach_cb, NULL));
159 	ck_assert_int_eq(TOTAL_ROAS, total_found);
160 	for (i = 0; i < TOTAL_ROAS; i++)
161 		ck_assert_int_eq(true, roas_found[i]);
162 
163 	db_table_destroy(table);
164 }
165 END_TEST
166 
pdu_suite(void)167 Suite *pdu_suite(void)
168 {
169 	Suite *suite;
170 	TCase *core;
171 
172 	core = tcase_create("Core");
173 	tcase_add_test(core, test_basic);
174 
175 	suite = suite_create("DB Table");
176 	suite_add_tcase(suite, core);
177 	return suite;
178 }
179 
main(void)180 int main(void)
181 {
182 	Suite *suite;
183 	SRunner *runner;
184 	int tests_failed;
185 
186 	suite = pdu_suite();
187 
188 	runner = srunner_create(suite);
189 	srunner_run_all(runner, CK_NORMAL);
190 	tests_failed = srunner_ntests_failed(runner);
191 	srunner_free(runner);
192 
193 	return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
194 }
195