blob: ab7156fc5805ddd677447e4873b35a511524e1b9 [file] [log] [blame]
Harald Weltedb924d32017-10-12 20:01:54 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <time.h>
6
7#include <netinet/in.h>
8#include <sys/socket.h>
9
10#include <osmocom/core/utils.h>
11#include <osmocom/core/application.h>
12#include <osmocom/core/logging.h>
13
14#include "../../lib/in46_addr.h"
15#include "../../lib/syserr.h"
16
17static const struct in46_addr g_ia4 = {
18 .len = 4,
19 .v4.s_addr = 0x0d0c0b0a,
20};
21
22static const struct in46_addr g_ia6 = {
23 .len = 16,
24 .v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
25};
26
27static void test_in46a_to_af(void)
28{
29 struct in46_addr ia;
30
31 printf("Testing in46a_to_af()\n");
32
33 OSMO_ASSERT(in46a_to_af(&g_ia4) == AF_INET);
34 OSMO_ASSERT(in46a_to_af(&g_ia6) == AF_INET6);
35
36 ia.len = 8;
37 OSMO_ASSERT(in46a_to_af(&ia) == AF_INET6);
38}
39
40static void test_in46a_to_sas(void)
41{
42 struct sockaddr_storage ss;
43 struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
44 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
45
46 printf("Testing in46a_to_sas()\n");
47
48 memset(&ss, 0, sizeof(ss));
49 OSMO_ASSERT(in46a_to_sas(&ss, &g_ia4) == 0);
50 OSMO_ASSERT(sin->sin_family == AF_INET);
51 OSMO_ASSERT(sin->sin_addr.s_addr == g_ia4.v4.s_addr);
52
53 memset(&ss, 0, sizeof(ss));
54 OSMO_ASSERT(in46a_to_sas(&ss, &g_ia6) == 0);
55 OSMO_ASSERT(sin6->sin6_family == AF_INET6);
56 OSMO_ASSERT(!memcmp(&sin6->sin6_addr, &g_ia6.v6, sizeof(sin6->sin6_addr)));
57}
58
59static void test_in46a_ntop(void)
60{
61 struct in46_addr ia;
62 char buf[256];
63 const char *res;
64
65 printf("Testing in46a_ntop()\n");
66
67 res = in46a_ntop(NULL, buf, sizeof(buf));
68 OSMO_ASSERT(res && !strcmp(res, "UNDEFINED"));
69 printf("res = %s\n", res);
70
71 ia.len = 0;
72 res = in46a_ntop(&ia, buf, sizeof(buf));
73 printf("res = %s\n", res);
74 OSMO_ASSERT(res && !strcmp(res, "UNDEFINED"));
75
76 ia.len = 4;
77 ia.v4.s_addr = htonl(0x01020304);
78 res = in46a_ntop(&ia, buf, sizeof(buf));
79 OSMO_ASSERT(res && !strcmp(res, "1.2.3.4"));
80 printf("res = %s\n", res);
81
82 res = in46a_ntop(&g_ia6, buf, sizeof(buf));
83 OSMO_ASSERT(res && !strcmp(res, "102:304:506:708:90a:b0c:d0e:f10"));
84 printf("res = %s\n", res);
85}
86
87static void test_in46p_ntoa(void)
88{
89 const struct in46_prefix ip46 = {
90 .prefixlen = 24,
91 .addr = {
92 .len = 4,
93 .v4.s_addr = htonl(0x10203000),
94 },
95 };
96 printf("in46p_ntoa() returns %s\n", in46p_ntoa(&ip46));
97}
98
99static void test_in46a_equal(void)
100{
101 struct in46_addr b;
102
103 printf("Testing in46a_equal()\n");
104
105 memset(&b, 0xff, sizeof(b));
106 b.len = g_ia4.len;
107 b.v4.s_addr = g_ia4.v4.s_addr;
108 OSMO_ASSERT(in46a_equal(&g_ia4, &b));
109
110 memset(&b, 0xff, sizeof(b));
111 b.len = g_ia6.len;
112 b.v6 = g_ia6.v6;
113 OSMO_ASSERT(in46a_equal(&g_ia6, &b));
114
115}
116
117
118static int log_in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net,
119 size_t prefixlen)
120{
121 int rc;
122
123 printf("in46a_within_mask(%s, ", in46a_ntoa(addr));
124 printf("%s, %lu) = ", in46a_ntoa(net), prefixlen);
125
126 rc = in46a_within_mask(addr, net, prefixlen);
127 printf("%d\n", rc);
128
129 return rc;
130}
131
132static void test_in46a_within_mask(void)
133{
134 struct in46_addr addr, mask;
135
136 printf("Testing in46a_within_mask()\n");
137
138 addr = g_ia4;
139 mask = g_ia4;
140 OSMO_ASSERT(log_in46a_within_mask(&addr, &mask, 32));
141
142 mask.v4.s_addr = htonl( ntohl(mask.v4.s_addr) & 0xfffffffC );
143 OSMO_ASSERT(log_in46a_within_mask(&addr, &mask, 30));
144
145 mask.v4.s_addr = htonl( ntohl(mask.v4.s_addr) & 0xfff80000 );
146 OSMO_ASSERT(log_in46a_within_mask(&addr, &mask, 13));
147
148 addr.v4.s_addr = htonl(ntohl(addr.v4.s_addr) + 1);
149 mask = g_ia4;
150 OSMO_ASSERT(!log_in46a_within_mask(&addr, &mask, 32));
151 mask.v4.s_addr = htonl( ntohl(mask.v4.s_addr) & 0xfffffffC );
152 OSMO_ASSERT(log_in46a_within_mask(&addr, &mask, 30));
153}
154
155static void test_in46a_to_eua(void)
156{
157 const struct in46_addr ia_v6_8 = {
158 .len = 8,
159 .v6.s6_addr = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
160 };
161 struct ul66_t eua;
162
163 printf("testing in46a_to_eua()\n");
164
165#if 0 /* triggers assert in current implementation */
166 const struct in46_addr ia_invalid = { .len = 3, };
167 OSMO_ASSERT(in46a_to_eua(&ia_invalid, &eua) < 0);
168#endif
169
170 /* IPv4 address */
171 OSMO_ASSERT(in46a_to_eua(&g_ia4, &eua) == 0);
172 OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
173 OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v4);
174 OSMO_ASSERT(*(uint32_t *) &eua.v[2] == g_ia4.v4.s_addr);
175
176 /* IPv6 address */
177 OSMO_ASSERT(in46a_to_eua(&g_ia6, &eua) == 0);
178 OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
179 OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v6);
180 OSMO_ASSERT(!memcmp(&eua.v[2], &g_ia6.v6, 16));
181
182 /* IPv6 address with prefix / length 8 */
183 OSMO_ASSERT(in46a_to_eua(&ia_v6_8, &eua) == 0);
184 OSMO_ASSERT(eua.v[0] == PDP_EUA_ORG_IETF);
185 OSMO_ASSERT(eua.v[1] == PDP_EUA_TYPE_v6);
186 OSMO_ASSERT(!memcmp(&eua.v[2], &ia_v6_8.v6, 16));
187}
188
189static void test_in46a_from_eua(void)
190{
191 struct in46_addr ia;
192 struct ul66_t eua;
193 const uint8_t v4_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4 };
194 const uint8_t v4_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v4, 1,2,3,4 };
195 const uint8_t v6_unspec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6 };
196 const uint8_t v6_spec[] = { PDP_EUA_ORG_IETF, PDP_EUA_TYPE_v6,
197 1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10 };
198
199 memset(&eua, 0, sizeof(eua));
200
201 printf("Testing in46a_from_eua()\n");
202
203 /* default: v4 unspec */
204 OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
205 OSMO_ASSERT(ia.len == 4);
206 OSMO_ASSERT(ia.v4.s_addr == 0);
207
208 /* invalid */
209 eua.v[0] = 0x23;
210 eua.v[1] = PDP_EUA_TYPE_v4;
211 eua.l = 6;
212 OSMO_ASSERT(in46a_from_eua(&eua, &ia) < 0);
213
214 /* invalid */
215 eua.v[0] = PDP_EUA_ORG_IETF;
216 eua.v[1] = 0x23;
217 eua.l = 6;
218 OSMO_ASSERT(in46a_from_eua(&eua, &ia) < 0);
219
220 /* unspecified V4 */
221 memcpy(eua.v, v4_unspec, sizeof(v4_unspec));
222 eua.l = sizeof(v4_unspec);
223 OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
224 OSMO_ASSERT(ia.len == 4);
225 OSMO_ASSERT(ia.v4.s_addr == 0);
226
227 /* specified V4 */
228 memcpy(eua.v, v4_spec, sizeof(v4_spec));
229 eua.l = sizeof(v4_spec);
230 OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
231 OSMO_ASSERT(ia.len == 4);
232 OSMO_ASSERT(ia.v4.s_addr == htonl(0x01020304));
233
234 /* unspecified V6 */
235 memcpy(eua.v, v6_unspec, sizeof(v6_unspec));
236 eua.l = sizeof(v6_unspec);
237 OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
238 OSMO_ASSERT(ia.len == 16);
239 OSMO_ASSERT(IN6_IS_ADDR_UNSPECIFIED(&ia.v6));
240
241 /* specified V6 */
242 memcpy(eua.v, v6_spec, sizeof(v6_spec));
243 eua.l = sizeof(v6_spec);
244 OSMO_ASSERT(in46a_from_eua(&eua, &ia) == 0);
245 OSMO_ASSERT(ia.len == 16);
246 OSMO_ASSERT(!memcmp(&ia.v6, v6_spec+2, ia.len));
247}
248
Pau Espin Pedrol2e7b9ff2017-10-16 14:27:32 +0200249static void test_in46a_netmasklen(void)
250{
251 struct in46_addr netmask;
252 unsigned int len;
253
254 printf("Testing in46a_netmasklen() with IPv4 addresses\n");
255 netmask.len = 4;
256
257 netmask.v4.s_addr = 0xffffffff;
258 len = in46a_netmasklen(&netmask);
259 OSMO_ASSERT(len == 32);
260
261 netmask.v4.s_addr = 0x00ffffff;
262 len = in46a_netmasklen(&netmask);
263 OSMO_ASSERT(len == 24);
264
265 netmask.v4.s_addr = 0x00f0ffff;
266 len = in46a_netmasklen(&netmask);
267 OSMO_ASSERT(len == 20);
268
269 netmask.v4.s_addr = 0x000000fe;
270 len = in46a_netmasklen(&netmask);
271 OSMO_ASSERT(len == 7);
272
273 netmask.v4.s_addr = 0x00000000;
274 len = in46a_netmasklen(&netmask);
275 OSMO_ASSERT(len == 0);
276
277 printf("Testing in46a_netmasklen() with IPv6 addresses\n");
278 const struct in46_addr netmaskA = {
279 .len = 16,
280 .v6.s6_addr = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
281 };
282 len = in46a_netmasklen(&netmaskA);
283 OSMO_ASSERT(len == 128);
284
285 const struct in46_addr netmaskB = {
286 .len = 16,
287 .v6.s6_addr = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00},
288 };
289 len = in46a_netmasklen(&netmaskB);
290 OSMO_ASSERT(len == 104);
291
292 const struct in46_addr netmaskC = {
293 .len = 16,
294 .v6.s6_addr = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00},
295 };
296 len = in46a_netmasklen(&netmaskC);
297 OSMO_ASSERT(len == 103);
298
299 const struct in46_addr netmaskD = {
300 .len = 16,
301 .v6.s6_addr = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
302 };
303 len = in46a_netmasklen(&netmaskD);
304 OSMO_ASSERT(len == 0);
305}
306
Harald Weltedb924d32017-10-12 20:01:54 +0800307int main(int argc, char **argv)
308{
309 osmo_init_logging(&log_info);
310 log_set_use_color(osmo_stderr_target, 0);
311 log_set_print_filename(osmo_stderr_target, 0);
312
313 srand(time(NULL));
314
315 test_in46a_to_af();
316 test_in46a_to_sas();
317 test_in46a_ntop();
318 test_in46p_ntoa();
319 test_in46a_equal();
320 test_in46a_within_mask();
321 test_in46a_to_eua();
322 test_in46a_from_eua();
Pau Espin Pedrol2e7b9ff2017-10-16 14:27:32 +0200323 test_in46a_netmasklen();
Neels Hofmeyrdabb8b42017-10-29 01:53:50 +0200324 return 0;
Harald Weltedb924d32017-10-12 20:01:54 +0800325}