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