1 /*
2 * Project : ipv6calc
3 * File : libipv6addr.c
4 * Version : $Id: 19776250b0c1c3a7c3c1124674790d5507a99d4b $
5 * Copyright : 2001-2021 by Peter Bieringer <pb (at) bieringer.de> except the parts taken from kernel source
6 * License : GNU GPL v2
7 *
8 * Information:
9 * Function library for IPv6 address handling
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15 #include <string.h>
16 #include <math.h>
17
18 #include "config.h"
19 #include "libipv6addr.h"
20 #include "librfc1884.h"
21 #include "librfc3041.h"
22 #include "libipv6addr.h"
23 #include "libipv4addr.h"
24 #include "ipv6calctypes.h"
25 #include "libipv6calc.h"
26 #include "libipv6calcdebug.h"
27 #include "libieee.h"
28 #include "libeui64.h"
29
30 #include "../databases/lib/libipv6calc_db_wrapper.h"
31
32
33 /*
34 * function returns an octet of an IPv6 address
35 *
36 * in: ipv6addrp = pointer to IPv6 address structure
37 * in: numoctet = number of octet (0 = MSB, 15 = LSB)
38 * additional: calls exit on out of range
39 */
ipv6addr_getoctet(const ipv6calc_ipv6addr * ipv6addrp,const unsigned int numoctet)40 uint8_t ipv6addr_getoctet(const ipv6calc_ipv6addr *ipv6addrp, const unsigned int numoctet) {
41 uint8_t retval;
42
43 if ( numoctet > 15 ) {
44 ERRORPRINT_WA("given octet number '%u' is out of range!", numoctet);
45 exit(EXIT_FAILURE);
46 };
47
48 retval = ipv6addrp->in6_addr.s6_addr[numoctet];
49
50 return (retval);
51 };
52
53
54 /*
55 * function returns a word of an IPv6 address
56 *
57 * in: ipv6addrp = pointer to IPv6 address structure
58 * in: numword = number of word (0 = MSB, 7 = LSB)
59 * additional: calls exit on out of range
60 */
ipv6addr_getword(const ipv6calc_ipv6addr * ipv6addrp,const unsigned int numword)61 uint16_t ipv6addr_getword(const ipv6calc_ipv6addr *ipv6addrp, const unsigned int numword) {
62 uint16_t retval;
63
64 if ( numword > 7 ) {
65 ERRORPRINT_WA("given word number '%u' is out of range!", numword);
66 exit(EXIT_FAILURE);
67 };
68
69 retval = ( ipv6addrp->in6_addr.s6_addr[numword * 2] << 8 ) \
70 | ( ipv6addrp->in6_addr.s6_addr[numword * 2 + 1] );
71
72 return (retval);
73 };
74
75
76 /*
77 * function returns a dword of an IPv6 address
78 *
79 * in: ipv6addrp = pointer to IPv6 address structure
80 * in: numdword = number of word (0 = MSB, 3 = LSB)
81 * additional: calls exit on out of range
82 */
ipv6addr_getdword(const ipv6calc_ipv6addr * ipv6addrp,const unsigned int numdword)83 uint32_t ipv6addr_getdword(const ipv6calc_ipv6addr *ipv6addrp, const unsigned int numdword) {
84 uint32_t retval;
85
86 if ( numdword > 3 ) {
87 ERRORPRINT_WA("given dword number '%u' is out of range!", numdword);
88 exit(EXIT_FAILURE);
89 };
90
91 retval = ( ipv6addrp->in6_addr.s6_addr[numdword * 4] << 24 ) \
92 | ( ipv6addrp->in6_addr.s6_addr[numdword * 4 + 1] << 16 ) \
93 | ( ipv6addrp->in6_addr.s6_addr[numdword * 4 + 2] << 8 ) \
94 | ( ipv6addrp->in6_addr.s6_addr[numdword * 4 + 3] );
95
96 return (retval);
97 };
98
99
100 /*
101 * function sets an octet of an IPv6 address
102 *
103 * mod: ipv6addrp = pointer to IPv6 address structure
104 * in: numoctet = number of word (0 = MSB, 15 = LSB)
105 * in: value = value to set
106 * additional: calls exit on out of range
107 */
ipv6addr_setoctet(ipv6calc_ipv6addr * ipv6addrp,const unsigned int numoctet,const unsigned int value)108 void ipv6addr_setoctet(ipv6calc_ipv6addr *ipv6addrp, const unsigned int numoctet, const unsigned int value) {
109
110 if ( numoctet > 15 ) {
111 ERRORPRINT_WA("given octet number '%u' is out of range!", numoctet);
112 exit(EXIT_FAILURE);
113 };
114
115 if ( value > 0x0000000ff ) {
116 ERRORPRINT_WA("given value '%x' is out of range!", value);
117 exit(EXIT_FAILURE);
118 };
119
120 ipv6addrp->in6_addr.s6_addr[numoctet] = (uint8_t) value;
121
122 return;
123 };
124
125
126 /*
127 * function sets a word of an IPv6 address
128 *
129 * mod: ipv6addrp = pointer to IPv6 address structure
130 * in: numword = number of word (0 = MSB, 7 = LSB)
131 * in: value = value to set
132 * additional: calls exit on out of range
133 */
ipv6addr_setword(ipv6calc_ipv6addr * ipv6addrp,const unsigned int numword,const unsigned int value)134 void ipv6addr_setword(ipv6calc_ipv6addr *ipv6addrp, const unsigned int numword, const unsigned int value) {
135 if ( numword > 7 ) {
136 ERRORPRINT_WA("given word number '%u' is out of range!", numword);
137 exit(EXIT_FAILURE);
138 };
139
140 if ( value > 0x0000ffffu ) {
141 ERRORPRINT_WA("given value '%x' is out of range!", value);
142 exit(EXIT_FAILURE);
143 };
144
145 ipv6addrp->in6_addr.s6_addr[numword * 2 ] = (uint8_t) ( ( value & 0x0000ff00 ) >> 8 );
146 ipv6addrp->in6_addr.s6_addr[numword * 2 + 1] = (uint8_t) ( ( value & 0x000000ff ) );
147
148 return;
149 };
150
151
152 /*
153 * function sets a dword of an IPv6 address
154 *
155 * mod: ipv6addrp = pointer to IPv6 address structure
156 * in: numdword = number of word (0 = MSB, 3 = LSB)
157 * in: value = value to set
158 * additional: calls exit on out of range
159 */
ipv6addr_setdword(ipv6calc_ipv6addr * ipv6addrp,const unsigned int numdword,const unsigned int value)160 void ipv6addr_setdword(ipv6calc_ipv6addr *ipv6addrp, const unsigned int numdword, const unsigned int value) {
161
162 if ( numdword > 3 ) {
163 ERRORPRINT_WA("given dword number '%u' is out of range!", numdword);
164 exit(EXIT_FAILURE);
165 };
166
167 if ( value > 0xffffffffu ) {
168 ERRORPRINT_WA("given value '%x' is out of range!", value);
169 exit(EXIT_FAILURE);
170 };
171
172 ipv6addrp->in6_addr.s6_addr[numdword * 4 ] = (uint8_t) ( ( value & 0xff000000 ) >> 24 );
173 ipv6addrp->in6_addr.s6_addr[numdword * 4 + 1] = (uint8_t) ( ( value & 0x00ff0000 ) >> 16 );
174 ipv6addrp->in6_addr.s6_addr[numdword * 4 + 2] = (uint8_t) ( ( value & 0x0000ff00 ) >> 8 );
175 ipv6addrp->in6_addr.s6_addr[numdword * 4 + 3] = (uint8_t) ( ( value & 0x000000ff ) );
176
177 return;
178 };
179
180
181 /*
182 * function clears the IPv6 structure
183 *
184 * mod: ipv6addrp = pointer to IPv6 address structure
185 */
ipv6addr_clear(ipv6calc_ipv6addr * ipv6addrp)186 void ipv6addr_clear(ipv6calc_ipv6addr *ipv6addrp) {
187 int i;
188
189 for (i = 0; i < MAXENTRIES_ARRAY(ipv6addrp->in6_addr.s6_addr); i++) {
190 ipv6addrp->in6_addr.s6_addr[i] = 0;
191 };
192
193 /* Clear IPv6 address scope */
194 ipv6addrp->typeinfo = 0;
195 ipv6addrp->typeinfo2 = 0;
196 ipv6addrp->flag_typeinfo = 0;
197
198 /* Clear valid flag */
199 ipv6addrp->flag_valid = 0;
200
201 /* Clear test mode */
202 ipv6addrp->test_mode = 0;
203
204 return;
205 };
206
207
208 /*
209 * function clears the IPv6 structure
210 *
211 * mod: ipv6addrp = pointer to IPv6 address structure
212 */
ipv6addr_clearall(ipv6calc_ipv6addr * ipv6addrp)213 void ipv6addr_clearall(ipv6calc_ipv6addr *ipv6addrp) {
214 ipv6addr_clear(ipv6addrp);
215
216 /* Clear other field */
217 ipv6addrp->bit_start = 1;
218 ipv6addrp->bit_end = 128;
219 ipv6addrp->flag_startend_use = 0;
220 ipv6addrp->flag_prefixuse = 0;
221 ipv6addrp->prefixlength = 0;
222 ipv6addrp->prefix2length = 0;
223 ipv6addrp->flag_valid = 0;
224 ipv6addrp->flag_scopeid = 0;
225
226 return;
227 };
228
229
230 /*
231 * function copies the IPv6 structure
232 *
233 * in: ipv6addrp = pointer to IPv6 address structure
234 * mod: ipv6addrp2 = pointer to IPv6 address structure
235 */
ipv6addr_copy(ipv6calc_ipv6addr * ipv6addrp_dst,const ipv6calc_ipv6addr * ipv6addrp_src)236 void ipv6addr_copy(ipv6calc_ipv6addr *ipv6addrp_dst, const ipv6calc_ipv6addr *ipv6addrp_src) {
237
238 *(ipv6addrp_dst) = *(ipv6addrp_src);
239
240 return;
241 };
242
243
244 /*
245 * function compares the IPv6 structure
246 *
247 * in: ipv6addrp1 = pointer to IPv6 address structure
248 * in: ipv6addrp2 = pointer to IPv6 address structure
249 * in: compare_flags:
250 * 0=less than/equal/greater than
251 * 1=honor prefix length on addr2
252 *
253 * returns: 0: addr1 equal with addr2, 1: addr1 > addr2, -1: addr1 < addr2 (compare_flags == 0)
254 * returns: 0: addr1 equal with addr2 or covered by addr2/prefix (compare_flags == 1)
255 */
ipv6addr_compare(const ipv6calc_ipv6addr * ipv6addrp1,const ipv6calc_ipv6addr * ipv6addrp2,const uint16_t compare_flags)256 int ipv6addr_compare(const ipv6calc_ipv6addr *ipv6addrp1, const ipv6calc_ipv6addr *ipv6addrp2, const uint16_t compare_flags) {
257 int i;
258 uint32_t mask;
259
260 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare addr1 with addr2 (compare flags: %08x)", compare_flags);
261
262 if (compare_flags == 1) {
263 for (i = 0; i < 4; i++) {
264 if ((ipv6addrp2->flag_prefixuse == 0)
265 || ((ipv6addrp2->flag_prefixuse == 1) && (ipv6addrp2->prefixlength >= (i + 1) * 32))) {
266 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare dword %i (prefixuse=%d): %08x <-> %08x", i, ipv6addrp2->flag_prefixuse, ipv6addr_getdword(ipv6addrp2, i), ipv6addr_getdword(ipv6addrp1, i));
267 /* compare 32 bits */
268 if (ipv6addr_getdword(ipv6addrp2, i) != ipv6addr_getdword(ipv6addrp1, i)) {
269 return(1);
270 };
271 } else if (ipv6addrp2->flag_prefixuse == 1) {
272 mask = ~(0xffffffffu >> (ipv6addrp2->prefixlength - i * 32));
273 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare dword %i with mask 0x%08x: %08x <-> %08x", i, mask, (ipv6addr_getdword(ipv6addrp2, i) & mask), (ipv6addr_getdword(ipv6addrp1, i) & mask));
274 if ((ipv6addr_getdword(ipv6addrp2, i) & mask) != (ipv6addr_getdword(ipv6addrp1, i) & mask)) {
275 return(1);
276 } else {
277 return(0);
278 };
279 };
280 };
281 } else if (compare_flags == 0) {
282 for (i = 0; i < 4; i++) {
283 if (ipv6addr_getdword(ipv6addrp1, i) > ipv6addr_getdword(ipv6addrp2, i)) {
284 return(1);
285 } else if (ipv6addr_getdword(ipv6addrp1, i) < ipv6addr_getdword(ipv6addrp2, i)) {
286 return(-1);
287 };
288 };
289 };
290
291 return(0);
292 };
293
294
295 /*
296 * create/verify checksum for anonymized qword
297 *
298 * in: ipv6addrp = pointer to IPv6 address structure
299 * in: flag = ANON_CHECKSUM_FLAG_CREATE|ANON_CHECKSUM_FLAG_VERIFY
300 * in: qword = qword (64-bit selection)
301 * out: ANON_CHECKSUM_FLAG_CREATE: 4-bit checksum ANON_CHECKSUM_FLAG_VERIFY: 0:ok/1:not-ok
302 *
303 * using same calculation as for ISAN: ISO 7064, MOD 17,16
304 * http://www.pruefziffernberechnung.de/I/ISAN.shtml
305 */
ipv6addr_checksum_anonymized_qword(const ipv6calc_ipv6addr * ipv6addrp,const int flag,const int qword)306 uint32_t ipv6addr_checksum_anonymized_qword(const ipv6calc_ipv6addr *ipv6addrp, const int flag, const int qword) {
307 uint32_t dword[2];
308 uint32_t checksum = 0;
309 int i, n, index, i_max = 16;
310 unsigned int s;
311 uint32_t a, b, c = 0;
312
313 DEBUGPRINT_NA(DEBUG_libipv6addr, "Called");
314
315 dword[0] = ipv6addr_getdword(ipv6addrp, (qword << 1)); // 00-31 (8 nibbles)
316 dword[1] = ipv6addr_getdword(ipv6addrp, (qword << 1) + 1); // 32-63 (8 nibbles, only 7 nibbles are used for calculation)
317
318 if (flag == ANON_CHECKSUM_FLAG_CREATE) {
319 i_max = 15;
320 };
321
322 for (i = 1; i <= i_max; i++) {
323 index = (i - 1) / 8; // 0-1
324 n = (i - 1) % 8; // 0-7
325 s = (7 - n) * 4;
326
327 if (i == 1) {
328 a = 16; // init
329 } else {
330 a = c * 2;
331 };
332
333 b = (a % 17) + ((dword[index] & (0xf << s)) >> s);
334 c = b % 16;
335
336 // DEBUGPRINT_WA(DEBUG_libipv6addr, "checksum calculation of qword: %08x %08x i=%02d a=%02d b=%02d c=%02d", (unsigned int) dword[0], (unsigned int) dword[1], i, a, b, c);
337 };
338
339 if (flag == ANON_CHECKSUM_FLAG_VERIFY) {
340 // return code depending on result
341 if (c == 1) {
342 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum verification OK");
343 return(0);
344 };
345
346 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum verification FAILED");
347 return(1);
348 };
349
350 /* find checksum xdigit */
351 a = c * 2;
352
353 for (checksum = 0; checksum <= 0xf; checksum++) {
354 if ( (((a % 17) + checksum) % 16) == 1) {
355 break;
356 };
357 };
358
359 DEBUGPRINT_WA(DEBUG_libipv6addr, "checksum of 64 bits: %08x %08x = %x", (unsigned int) dword[0], (unsigned int) dword[1], checksum);
360
361 return(checksum);
362 };
363
364
365 /*
366 * set checksum for anonymized prefix
367 *
368 * mod: ipv6addrp = pointer to IPv6 address structure
369 */
ipv6addr_set_checksum_anonymized_prefix(ipv6calc_ipv6addr * ipv6addrp)370 void ipv6addr_set_checksum_anonymized_prefix(ipv6calc_ipv6addr *ipv6addrp) {
371 uint32_t checksum = ipv6addr_checksum_anonymized_qword(ipv6addrp, ANON_CHECKSUM_FLAG_CREATE, 0);
372
373 /* checksum is stored in rightmost nibble */
374 ipv6addr_setoctet(ipv6addrp, 7, (ipv6addr_getoctet(ipv6addrp, 7) & 0xf0) | checksum);
375 };
376
377
378 /*
379 * verify checksum for anonymized prefix
380 *
381 * in: ipv6addrp = pointer to IPv6 address structure
382 * out: 0=ok 1=not ok
383 */
ipv6addr_verify_checksum_anonymized_prefix(const ipv6calc_ipv6addr * ipv6addrp)384 int ipv6addr_verify_checksum_anonymized_prefix(const ipv6calc_ipv6addr *ipv6addrp) {
385 return (ipv6addr_checksum_anonymized_qword(ipv6addrp, ANON_CHECKSUM_FLAG_VERIFY, 0));
386 };
387
388
389 /*
390 * set checksum for anonymized IID
391 *
392 * mod: ipv6addrp = pointer to IPv6 address structure
393 */
ipv6addr_set_checksum_anonymized_iid(ipv6calc_ipv6addr * ipv6addrp)394 void ipv6addr_set_checksum_anonymized_iid(ipv6calc_ipv6addr *ipv6addrp) {
395 uint32_t checksum = ipv6addr_checksum_anonymized_qword(ipv6addrp, ANON_CHECKSUM_FLAG_CREATE, 1);
396
397 /* checksum is stored in rightmost nibble */
398 ipv6addr_setoctet(ipv6addrp, 15, (ipv6addr_getoctet(ipv6addrp, 15) & 0xf0) | checksum);
399 };
400
401
402 /*
403 * verify checksum for anonymized IID
404 *
405 * in: ipv6addrp = pointer to IPv6 address structure
406 * out: 0=ok 1=not ok
407 */
ipv6addr_verify_checksum_anonymized_iid(const ipv6calc_ipv6addr * ipv6addrp)408 int ipv6addr_verify_checksum_anonymized_iid(const ipv6calc_ipv6addr *ipv6addrp) {
409 return (ipv6addr_checksum_anonymized_qword(ipv6addrp, ANON_CHECKSUM_FLAG_VERIFY, 1));
410 };
411
412
413 /*
414 * fuzzy detection of IID is random generated (e.g. by privacy extension)
415 *
416 * in: ipv6addrp = pointer to IPv6 address structure
417 * out: 0=probably random generated (e.g. by privacy extension), 1=manual set, -1=global, 2=unknown
418 */
ipv6addr_iidrandomdetection(const ipv6calc_ipv6addr * ipv6addrp,s_iid_statistics * iid_statisticsp)419 int ipv6addr_iidrandomdetection(const ipv6calc_ipv6addr *ipv6addrp, s_iid_statistics *iid_statisticsp) {
420 uint32_t iid[2];
421
422 iid[0] = ipv6addr_getdword(ipv6addrp, 2); // 00-31
423 iid[1] = ipv6addr_getdword(ipv6addrp, 3); // 32-63
424
425 int result = 2;
426
427 float m, e;
428
429 int iid_digit[16]; // digit of IID
430
431 int b, i, c, v;
432
433 // debug
434 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "given IID: %08x%08x",(unsigned int) iid[0], (unsigned int) iid[1]);
435
436 // blacklists
437 if ((iid[0] & 0x02000000u) == 0x02000000u) {
438 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "universal/local bit set to: universal (no further random detection)");
439 result = -1;
440 goto END_ipv6addr_iidrandomdetection;
441 };
442
443 if (((iid[0] & 0x000000ffu) == 0x000000ffu) && ((iid[1] & 0xff000000u) == 0xfe000000u)) {
444 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "expanded EUI-48 (no further random detection)");
445 result = -1;
446 goto END_ipv6addr_iidrandomdetection;
447 };
448
449 // clear structure
450 iid_statisticsp->hexdigit = 0;
451 iid_statisticsp->lls_residual = 0;
452
453 for (c = 0; c < 16; c++) {
454 iid_statisticsp->digit_blocks[c] = 0;
455 iid_statisticsp->digit_blocks_hexdigit[c] = 0;
456 iid_statisticsp->digit_amount[c] = 0;
457 };
458
459 for (c = 0; c < 31; c++) {
460 iid_statisticsp->digit_delta[c] = 0;
461 };
462
463 iid_statisticsp->digit_delta_amount = 0;
464
465
466 /* create statistics */
467 for (b = 0; b < 16; b++) {
468 v = (iid[b/8] & (0xf << ((7 - (b % 8)) * 4))) >> ((7 - (b % 8)) * 4);
469 iid_digit[b] = v;
470
471 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "analyze nibble %2d: %x", b, v);
472
473 iid_statisticsp->digit_amount[v]++;
474 };
475
476 if ( (ipv6calc_debug & DEBUG_libipv6addr_iidrandomdetection) != 0 ) { // ipv6calc_debug usage ok
477 DEBUGPRINT_NA(DEBUG_libipv6addr, "distribution");
478
479 fprintf(stderr, "%s/%s: hex distribution: digit ", __FILE__, __func__);
480 for (b = 0; b < 16; b++) {
481 fprintf(stderr, "|%2x", b);
482 };
483 fprintf(stderr, "|\n");
484 fprintf(stderr, "%s/%s: hex distribution: count ", __FILE__, __func__);
485 for (b = 0; b < 16; b++) {
486 fprintf(stderr, "|%2d", iid_statisticsp->digit_amount[b]);
487 };
488 fprintf(stderr, "|\n");
489 };
490
491 /* calculate variances */
492 v = 0;
493
494 /* calculate variance over hexdigits */
495 c = 0;
496 float variance = 0.0;
497 for (b = 0; b < 16; b++) {
498 if (iid_statisticsp->digit_amount[b] == 0) {
499 continue;
500 };
501 c++;
502 e = iid_statisticsp->digit_amount[b];
503
504 m = 1.0;
505 /* compensate universal/local bit = 0 by shifting average */
506 if ((b & 0x02) == 0x02) {
507 m -= 0.0625;
508 } else {
509 m += 0.0625;
510 };
511
512 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "hexdigit %x: amount=%.0f exp.avg.=%.4f", b, e, m);
513
514 e = e - m; /* substract related average */
515 e = e * e; /* square */
516 variance += e;
517 };
518
519 variance = sqrt(variance / c);
520
521 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "variance for hexdigits: %0.5f", variance);
522
523 iid_statisticsp->hexdigit = variance;
524
525
526 /* calculate linear least square fit to detect sequences */
527 float xm = 0, ym = 0, x2 = 0, xy = 0, a0, a1, r, r2 = 0;
528 for (b = 0; b < 16; b++) {
529 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "linear least square calc: x=%0.5f y=%0.5f", (float) b, (float) iid_digit[b]);
530 xm += (float) b;
531 ym += (float) iid_digit[b];
532 xy += (float) b * (float) iid_digit[b];
533 x2 += (float) b * (float) b;
534 };
535 xm /= 16.0; ym /= 16.0;
536
537 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "linear least square calc: xm=%0.5f ym=%0.5f", xm, ym);
538 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "linear least square calc: x2=%0.5f xy=%0.5f", x2, xy);
539
540 a1 = (xy - 16 * xm * ym) / (x2 - 16 * xm * xm);
541 a0 = ym - a1 * xm;
542
543 for (b = 0; b < 16; b++) {
544 r = a0 + a1 * (float) b - (float) iid_digit[b];
545 r2 += r * r;
546 };
547
548 r = sqrt(r2);
549
550 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "linear least square result: a0=%0.5f a1=%0.5f r=%05f", a0, a1, r);
551
552 iid_statisticsp->lls_residual = r;
553
554
555 /* check for repeating digits (digit blocks) */
556 c = 0;
557 i = iid_digit[0];
558 for (b = 1; b < 16; b++) {
559 if (i == iid_digit[b]) {
560 c++;
561 } else {
562 if (c > 0) {
563 iid_statisticsp->digit_blocks_hexdigit[i]++;
564 };
565 iid_statisticsp->digit_blocks[c]++;
566 i = iid_digit[b];
567 c = 0;
568 };
569 };
570 iid_statisticsp->digit_blocks[c]++;
571
572
573 /* analyze delta of neighbor digits (digit delta) */
574 for (b = 1; b < 16; b++) {
575 v = iid_digit[b] - iid_digit[b-1] + 15;
576
577 if (iid_statisticsp->digit_delta[v] == 0) {
578 // count, how many different digit deltas found
579 iid_statisticsp->digit_delta_amount++;
580 };
581
582 iid_statisticsp->digit_delta[v]++;
583
584 };
585
586 if ( (ipv6calc_debug & DEBUG_libipv6addr_iidrandomdetection) != 0 ) { // ipv6calc_debug usage ok
587 fprintf(stderr, "%s/%s: digit blocks: ", __FILE__, __func__);
588 for (c = 0; c < 16; c++) {
589 fprintf(stderr, "%d:%d ", c+1, iid_statisticsp->digit_blocks[c]);
590 };
591 fprintf(stderr, "\n");
592
593 fprintf(stderr, "%s/%s: hex distribution in blocks: digit ", __FILE__, __func__);
594 for (b = 0; b < 16; b++) {
595 fprintf(stderr, "|%2x", b);
596 };
597 fprintf(stderr, "|\n");
598 fprintf(stderr, "%s/%s: hex distribution in blocks: count ", __FILE__, __func__);
599 for (b = 0; b < 16; b++) {
600 fprintf(stderr, "|%2d", iid_statisticsp->digit_blocks_hexdigit[b]);
601 };
602 fprintf(stderr, "|\n");
603 };
604
605 /* check against limits */
606 if (iid_statisticsp->hexdigit < s_iid_statistics_ok_min.hexdigit || iid_statisticsp->hexdigit > s_iid_statistics_ok_max.hexdigit) {
607 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "min/max hexdigit variance limit reached: %f min=%f max=%f", iid_statisticsp->hexdigit, s_iid_statistics_ok_min.hexdigit, s_iid_statistics_ok_max.hexdigit);
608 result = 1;
609 goto END_ipv6addr_iidrandomdetection;
610
611 } else if (iid_statisticsp->lls_residual < s_iid_statistics_ok_min.lls_residual || iid_statisticsp->lls_residual > s_iid_statistics_ok_max.lls_residual) {
612 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max lls_residual limit reached");
613 result = 1;
614 goto END_ipv6addr_iidrandomdetection;
615
616 } else if (iid_statisticsp->digit_delta_amount < s_iid_statistics_ok_min.digit_delta_amount || iid_statisticsp->digit_delta_amount > s_iid_statistics_ok_max.digit_delta_amount) {
617 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max digit_delta_amount reached");
618 result = 1;
619 goto END_ipv6addr_iidrandomdetection;
620
621 } else {
622 for (c = 0; c < 16; c++) {
623 // digit blocks
624 if (iid_statisticsp->digit_blocks[c] < s_iid_statistics_ok_min.digit_blocks[c] || iid_statisticsp->digit_blocks[c] > s_iid_statistics_ok_max.digit_blocks[c]) {
625 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max digit_blocks reached");
626 result = 1;
627 goto END_ipv6addr_iidrandomdetection;
628 };
629
630 // digit blocks hexdigits
631 if (iid_statisticsp->digit_blocks_hexdigit[c] < s_iid_statistics_ok_min.digit_blocks_hexdigit[c] || iid_statisticsp->digit_blocks_hexdigit[c] > s_iid_statistics_ok_max.digit_blocks_hexdigit[c]) {
632 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max digit_blocks_hexdigit reached");
633 result = 1;
634 goto END_ipv6addr_iidrandomdetection;
635 };
636
637 // digit amount
638 if (iid_statisticsp->digit_amount[c] < s_iid_statistics_ok_min.digit_amount[c] || iid_statisticsp->digit_amount[c] > s_iid_statistics_ok_max.digit_amount[c]) {
639 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max digit_amount reached");
640 result = 1;
641 goto END_ipv6addr_iidrandomdetection;
642 };
643 };
644 for (c = 0; c < 31; c++) {
645 // digit delta
646 if (iid_statisticsp->digit_delta[c] < s_iid_statistics_ok_min.digit_delta[c] || iid_statisticsp->digit_delta[c] > s_iid_statistics_ok_max.digit_delta[c]) {
647 DEBUGPRINT_NA(DEBUG_libipv6addr_iidrandomdetection, "min/max digit_delta reached");
648 result = 1;
649 goto END_ipv6addr_iidrandomdetection;
650 };
651 };
652
653 };
654
655 result = 0;
656
657 END_ipv6addr_iidrandomdetection:
658 DEBUGPRINT_WA(DEBUG_libipv6addr_iidrandomdetection, "result=%d", result);
659 return (result);
660 };
661
662
663 /*
664 * Set type of an IPv6 address
665 *
666 * with credits to kernel and USAGI developer team
667 * basic code was taken from "kernel/net/ipv6/addrconf.c"
668 *
669 * in : ipv6addrp = pointer to IPv6 address structure
670 * mod: typeinfo, typeinfo2, prefix2length
671 */
ipv6addr_settype(ipv6calc_ipv6addr * ipv6addrp)672 void ipv6addr_settype(ipv6calc_ipv6addr *ipv6addrp) {
673 uint32_t type = 0, r, type2 = 0;
674 uint32_t st, st1, st2, st3;
675 s_iid_statistics variances;
676 int p;
677 uint32_t mask_0_15, mask_16_31;
678
679 uint32_t as_num32, cc_index, geonameid, geonameid_type;
680 int r1, r2, f;
681
682 ipv6calc_ipv4addr ipv4addr;
683 ipv6calc_ipv6addr ipv6addr;
684
685 st = ipv6addr_getdword(ipv6addrp, 0); /* 32 MSB */
686 st1 = ipv6addr_getdword(ipv6addrp, 1);
687 st2 = ipv6addr_getdword(ipv6addrp, 2);
688 st3 = ipv6addr_getdword(ipv6addrp, 3); /* 32 LSB */
689
690 DEBUGPRINT_NA(DEBUG_libipv6addr, "Called");
691
692 /* unspecified address */
693 if ( (st == 0) && (st1 == 0) && (st2 == 0) && (st3 == 0) ) {
694 type |= IPV6_NEW_ADDR_UNSPECIFIED;
695 goto END_ipv6addr_gettype;
696 };
697
698 /* address space information */
699 if ((st & 0xFE000000u) == 0xFC000000u) {
700 /* FC00::/7 -> Unique Local IPv6 Unicast Address */
701 type |= IPV6_ADDR_ULUA;
702 };
703
704 if (st == 0x261000d0) {
705 /* 2610:00d0::/32 -> LISP (RFC 6830) */
706 type2 |= IPV6_ADDR_TYPE2_LISP;
707 };
708
709 if ((st == 0x2001067c) && ((st1 & 0xffff0000u) == 0x01980000u)) {
710 /* 2001:67c:198::/48 -> LISP PETR (RFC 6830) */
711 type2 |= IPV6_ADDR_TYPE2_LISP | IPV6_ADDR_TYPE2_LISP_PETR;
712 type |= IPV6_ADDR_ANYCAST;
713 };
714
715 if ((st == 0x2001067c) && ((st1 & 0xffff0000u) == 0x00280000u)) {
716 /* 2001:67c:28::/48 -> LISP Map Resolver (RFC 6830) */
717 type2 |= IPV6_ADDR_TYPE2_LISP | IPV6_ADDR_TYPE2_LISP_MAP_RESOLVER;
718 type |= IPV6_ADDR_ANYCAST;
719 };
720
721 if (st == 0x20010db8) {
722 /* 2001:db8::/32 -> prefix for documentation (RFC 3849) */
723 type |= IPV6_ADDR_RESERVED;
724 };
725
726 if (UNPACK_XMS(st, ANON_PREFIX_TOKEN_XOR, ANON_PREFIX_TOKEN_MASK, ANON_PREFIX_TOKEN_SHIFT) == ANON_PREFIX_TOKEN_VALUE) {
727 // anonymized prefix ?
728 DEBUGPRINT_WA(DEBUG_libipv6addr, " probably anonymized prefix found: %04x:%04x:%04x:%04x", U32_MSB16(st), U32_LSB16(st), U32_MSB16(st1), U32_LSB16(st1));
729
730 /* verify now checksum */
731 if (ipv6addr_verify_checksum_anonymized_prefix(ipv6addrp) == 0) {
732 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum ok - anonymized prefix found");
733
734 /* extract flag */
735 uint32_t flags;
736 f = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_FLAGS, &flags);
737 if (f != 0) {
738 ERRORPRINT_NA("'flags' payload can't be retrieved, FIX CODE");
739 exit(EXIT_FAILURE);
740 };
741
742 if (flags == 0x0) {
743 DEBUGPRINT_NA(DEBUG_libipv6addr, "found anonymized IPv6 address with method: kp");
744 // anon method=kp
745 type |= IPV6_NEW_ADDR_AGU | IPV6_ADDR_UNICAST | IPV6_ADDR_ANONYMIZED_PREFIX;
746
747 r1 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_CCINDEX, &cc_index);
748 r2 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_ASN32, &as_num32);
749
750 if ((r1 == 0) && (r2 == 0) && (cc_index == COUNTRYCODE_INDEX_UNKNOWN_REGISTRY_MAP_MIN + REGISTRY_6BONE)) {
751 type |= IPV6_NEW_ADDR_6BONE;
752 } else if ((r1 == 0) && (r2 == 0) && (cc_index == COUNTRYCODE_INDEX_LISP)) {
753 type |= IPV6_NEW_ADDR_PRODUCTIVE;
754 type2 |= IPV6_ADDR_TYPE2_LISP;
755 } else {
756 type |= IPV6_NEW_ADDR_PRODUCTIVE;
757 };
758 } else if (flags == 0x1) {
759 DEBUGPRINT_NA(DEBUG_libipv6addr, "found anonymized IPv6 address with method: kg");
760 // anon method=kg
761 type |= IPV6_NEW_ADDR_AGU | IPV6_ADDR_UNICAST | IPV6_ADDR_ANONYMIZED_PREFIX;
762 type2 |= IPV6_ADDR_TYPE2_ANONYMIZED_GEONAMEID;
763
764 r1 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_GEONAMEID, &geonameid);
765 r2 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_GEONAMEID_TYPE, &geonameid_type);
766
767 if ((r1 == 0) && (r2 == 0) && (((geonameid_type & 0xf) == 0) && ((geonameid_type & 0xf0) >> 4) == REGISTRY_6BONE)) {
768 type |= IPV6_NEW_ADDR_6BONE;
769 DEBUGPRINT_NA(DEBUG_libipv6addr, "found anonymized 6bone IPv6 address with method: kg");
770 } else if ((r1 == 0) && (r2 == 0) && (geonameid == 0x11800) && ((geonameid_type & 0xf)== 7)) {
771 DEBUGPRINT_NA(DEBUG_libipv6addr, "found anonymized LISP IPv6 address with method: kg");
772 type |= IPV6_NEW_ADDR_PRODUCTIVE;
773 type2 |= IPV6_ADDR_TYPE2_LISP;
774 } else {
775 type |= IPV6_NEW_ADDR_PRODUCTIVE;
776 };
777 } else {
778 };
779 } else {
780 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum NOT ok - no anonymized prefix found");
781 };
782 };
783
784 /* address space information */
785 if ((st & 0xE0000000u) == 0x20000000u) {
786 /* 2000::/3 -> global unicast */
787 type |= IPV6_NEW_ADDR_AGU;
788 };
789
790 /* address space information */
791 if ((st & 0xFFFF0000u) == 0x3FFE0000u) {
792 /* 3ffe::/16 -> experimental 6bone */
793 type |= IPV6_NEW_ADDR_6BONE;
794 };
795
796 if ((st & 0xFFFF0000u) == 0x20020000u) {
797 /* 2002::/16 -> 6to4 tunneling */
798 type |= IPV6_NEW_ADDR_6TO4;
799
800 if ( (ipv6addr_getword(ipv6addrp, 3) == 0) &&
801 (ipv6addr_getword(ipv6addrp, 4) == 0) &&
802 (ipv6addr_getword(ipv6addrp, 5) == 0) &&
803 (ipv6addr_getword(ipv6addrp, 6) == ipv6addr_getword(ipv6addrp, 1)) &&
804 (ipv6addr_getword(ipv6addrp, 7) == ipv6addr_getword(ipv6addrp, 2)) ) {
805 /* 2002:<ipv4addr>::<ipv4addr> -> usually Microsoft does this */
806 type |= IPV6_NEW_ADDR_6TO4_MICROSOFT;
807 type |= IPV6_ADDR_IID_32_63_HAS_IPV4;
808 };
809 };
810
811 if (st == (uint32_t) 0x3FFE831Fu || st == (uint32_t) 0x20010000u) {
812 /* 3ffe:831f::/32 -> Teredo (6bone, older draft) */
813 /* 2001:0000::/32 -> Teredo (RFC 4380) */
814 type |= IPV6_NEW_ADDR_TEREDO;
815 if (ipv6addr_getword(ipv6addrp, 5) == 0xffffu) {
816 // port=0, done by anonymization
817 type |= IPV6_ADDR_ANONYMIZED_IID;
818 };
819 };
820
821 if (((st & 0xFFFFFFF0u) == 0x20010010u) || ((st & 0xFFFFFFF0u) == 0x20010020u)) {
822 /* 2001:0010::/28 -> ORCHID (RFC 4843) */
823 /* 2001:0020::/28 -> ORCHIDv2 (RFC 7343) */
824 type |= IPV6_NEW_ADDR_ORCHID;
825 /* ORCHID has no IID, only a 100 bit encoded hash */
826
827 /* check for anonymized hash */
828 if ((st2 & ANON_TOKEN_MASK_00_31) == (ANON_TOKEN_VALUE_00_31 & ANON_TOKEN_MASK_00_31)) {
829 DEBUGPRINT_NA(DEBUG_libipv6addr, "probably anonymized ORCHID found");
830
831 /* verify now checksum */
832 if (ipv6addr_verify_checksum_anonymized_iid(ipv6addrp) == 0) {
833 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum ok - anonymized ORCHID found");
834
835 type |= IPV6_ADDR_ANONYMIZED_IID;
836
837 } else {
838 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum NOT ok - no anonymized ORCHID found");
839 };
840 };
841 goto END_ipv6addr_gettype;
842 };
843
844 if ((st == 0x0064ff9bu) && (st1 == 0) && (st2 == 0)) {
845 /* 64:ff9b::/96 -> NAT64 (RFC 6052) */
846 type |= IPV6_NEW_ADDR_NAT64;
847 };
848
849 if (((type & (IPV6_NEW_ADDR_6BONE | IPV6_NEW_ADDR_6TO4)) == 0) && ((st & 0xE0000000u) == 0x20000000u)) {
850 /* 2000::/3 -> productive IPv6 address space */
851 /* except 3ffe::/16 (6BONE) and 2002::/16 (6TO4) */
852 type |= IPV6_NEW_ADDR_PRODUCTIVE;
853 };
854
855 if ((st2 == (uint32_t) 0x00000001u) && (st3 & 0xFF000000u) == 0xFF000000u) {
856 /* ..:0000:0001:ffxx:xxxx solicited node suffix */
857 type |= IPV6_NEW_ADDR_SOLICITED_NODE;
858 };
859
860 if (((st2 & 0xFDFFFF00u) == (uint32_t) 0x00005E00u) && ((type & IPV6_NEW_ADDR_TEREDO) == 0)) {
861 /* ISATAP (RFC 4214/5214), but not if TEREDO */
862 /* ..:0x00:5EFE:xx.xx.xx.xx ISATAP IID with private IPv4 address */
863 /* ..:0x00:5EFE:xx.xx.xx.xx ISATAP IID with public IPv4 address */
864 /* ..:0x00:5EFF:FExx:xxxx ISATAP IID with vendor ID */
865 /* ..:0x00:5Exx:xxxx:xxxx ISATAP IID with extension ID */
866 /* x & 0x2 == 0x2:global, x & 0x02 == 0:local */
867 type |= IPV6_NEW_ADDR_IID_ISATAP;
868
869 if ((st2 & 0x02000000u) == 0x02000000u) {
870 type |= IPV6_NEW_ADDR_IID_GLOBAL;
871 } else {
872 type |= IPV6_NEW_ADDR_IID_LOCAL;
873 };
874
875 if ((st2 & 0x000000ffu) == 0x000000feu) {
876 type |= IPV6_ADDR_IID_32_63_HAS_IPV4;
877 };
878 };
879
880 /* multicast */
881 if ((st & 0xFF000000u) == 0xFF000000u) {
882 type |= IPV6_ADDR_MULTICAST;
883
884 switch((st & 0x00FF0000u)) {
885 case (0x00010000u):
886 type |= IPV6_ADDR_LOOPBACK;
887 break;
888
889 case (0x00020000u):
890 type |= IPV6_ADDR_LINKLOCAL;
891 break;
892
893 case (0x00050000u):
894 type |= IPV6_ADDR_SITELOCAL;
895 break;
896 };
897 goto END_ipv6addr_gettype;
898 };
899
900 /* special */
901 if ((st | st1) == 0) {
902 if (st2 == 0) {
903 if (st3 == 0) {
904 type |= IPV6_ADDR_ANY;
905 goto END_ipv6addr_gettype;
906 };
907
908 if (st3 == (uint32_t) 0x00000001u) {
909 type |= IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST;
910 goto END_ipv6addr_gettype;
911 };
912
913 type |= IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST;
914 }
915
916 if (st2 == (uint32_t) 0x0000ffffu)
917 type |= IPV6_ADDR_MAPPED;
918 };
919
920 // check for included anonymized IPv4 address
921 if ((type & (IPV6_ADDR_COMPATv4| IPV6_ADDR_MAPPED | IPV6_NEW_ADDR_NAT64 | IPV6_NEW_ADDR_6TO4)) != 0) {
922 ipv6addr_copy(&ipv6addr, ipv6addrp);
923 ipv6addr.typeinfo = type; // store what we already have
924
925 r = libipv6addr_get_included_ipv4addr(&ipv6addr, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
926 if (r == 0) {
927 if ((ipv4addr.typeinfo & IPV4_ADDR_ANONYMIZED) != 0) {
928 if ((type & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) != 0) {
929 type |= IPV6_ADDR_ANONYMIZED_PREFIX;
930 };
931 if ((type & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0) {
932 type |= IPV6_ADDR_ANONYMIZED_IID;
933 };
934 };
935 if ((ipv4addr.typeinfo & IPV4_ADDR_ANONYMIZED_GEONAMEID) != 0) {
936 type2 |= IPV6_ADDR_TYPE2_ANONYMIZED_GEONAMEID;
937 };
938 };
939 } else if ((type & (IPV6_NEW_ADDR_TEREDO)) != 0) {
940 // check client IP
941 ipv6addr_copy(&ipv6addr, ipv6addrp);
942 ipv6addr.typeinfo = type; // store what we already have
943
944 r = libipv6addr_get_included_ipv4addr(&ipv6addr, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
945 if (r == 0) {
946 if ((ipv4addr.typeinfo & IPV4_ADDR_ANONYMIZED) != 0) {
947 type |= IPV6_ADDR_ANONYMIZED_IID;
948 };
949 if ((ipv4addr.typeinfo & IPV4_ADDR_ANONYMIZED_GEONAMEID) != 0) {
950 type2 |= IPV6_ADDR_TYPE2_ANONYMIZED_GEONAMEID;
951 };
952 };
953
954 // check server IP
955 ipv6addr_copy(&ipv6addr, ipv6addrp);
956 ipv6addr.typeinfo = type; // store what we already have
957
958 r = libipv6addr_get_included_ipv4addr(&ipv6addr, &ipv4addr, IPV6_ADDR_SELECT_IPV4_TEREDO_SERVER);
959 if (r == 0) {
960 if ((ipv4addr.typeinfo & IPV4_ADDR_ANONYMIZED) != 0) {
961 type |= IPV6_ADDR_ANONYMIZED_PREFIX;
962 };
963 };
964 };
965
966
967 /* Consider all addresses with the first three bits different of
968 000 and 111 as unicasts.
969 also link-local,site-local,ULULA
970 except LISP anycast
971 */
972 if ((((st & 0xE0000000u) != 0x00000000u) && ((st & 0xE0000000u) != 0xE0000000u)) || ((st & 0xFC000000u) == 0xFC000000u)) {
973 if ((type2 & (IPV6_ADDR_TYPE2_LISP_PETR | IPV6_ADDR_TYPE2_LISP_MAP_RESOLVER)) == 0) {
974 type |= IPV6_ADDR_UNICAST;
975 };
976
977 if ((type & IPV6_NEW_ADDR_TEREDO) != 0) {
978 /* teredo has no IID */
979 goto END_ipv6addr_gettype;
980 };
981
982 type |= IPV6_NEW_ADDR_IID;
983
984 if ((st & 0xFFC00000u) == 0xFE800000u) {
985 type |= IPV6_ADDR_LINKLOCAL;
986 if ( ((st2 == 0x80005445u) && (st3 ==0x5245444fu)) \
987 || ((st2 == 0x0000FFFFu) && (st3 ==0xFFFFFFFDu)) \
988 ) {
989 /* fe80::8000:5445:5245:444F : LSB string: "TEREDO" */
990 /* fe80::ffff:ffff:fffd */
991 type |= IPV6_NEW_ADDR_LINKLOCAL_TEREDO | IPV6_NEW_ADDR_IID_TEREDO;
992 };
993 } else if ((st & 0xFFC00000u) == 0xFEC00000u) {
994 type |= IPV6_ADDR_SITELOCAL;
995 };
996
997 if ((type & IPV6_NEW_ADDR_IID) != 0) {
998 /* check IID */
999 if ((st2 & 0x02000000u) == 0x02000000u) {
1000 type |= IPV6_NEW_ADDR_IID_GLOBAL;
1001
1002 if ((type & IPV6_NEW_ADDR_IID_ISATAP) != 0) {
1003 /* ISATAP is handled above */
1004 } else {
1005 if (((st2 & (uint32_t) 0x000000FFu) == (uint32_t) 0x000000FFu) && ((st3 & (uint32_t) 0xFE000000u) == (uint32_t) 0xFE000000u)) {
1006 type |= IPV6_NEW_ADDR_IID_EUI48;
1007 } else {
1008 type |= IPV6_NEW_ADDR_IID_EUI64;
1009 };
1010 };
1011 } else {
1012 if ((type & IPV6_NEW_ADDR_IID_ISATAP) != 0) {
1013 /* ISATAP is handled above */
1014 } else if (((st2 & (uint32_t) 0x000000FFu) == (uint32_t) 0x000000FFu) && ((st3 & (uint32_t) 0xFE000000u) == (uint32_t) 0xFE000000u)) {
1015 /* EUI-48 local scope based */
1016 type |= IPV6_NEW_ADDR_IID_EUI48 | IPV6_NEW_ADDR_IID_LOCAL;
1017 };
1018
1019 DEBUGPRINT_WA(DEBUG_libipv6addr, "check for anonymized IID: %04x:%04x:%04x:%04x", U32_MSB16(st2), U32_LSB16(st2), U32_MSB16(st3), U32_LSB16(st3));
1020
1021 /* check for anonymized IID */
1022 if ((st2 & ANON_TOKEN_MASK_00_31) == (ANON_TOKEN_VALUE_00_31 & ANON_TOKEN_MASK_00_31)) {
1023 DEBUGPRINT_NA(DEBUG_libipv6addr, "perhaps anonymized IID found (ANON token match)");
1024
1025 /* verify now checksum */
1026 if (ipv6addr_verify_checksum_anonymized_iid(ipv6addrp) == 0) {
1027 p = UNPACK_XMS(st2, 0, ANON_IID_PREFIX_NIBBLES_MASK, ANON_IID_PREFIX_NIBBLES_SHIFT);
1028
1029 DEBUGPRINT_WA(DEBUG_libipv6addr, "checksum ok - probably anonymized IID found, p=%d", p);
1030
1031 if (p == 0) {
1032 // no additional check
1033 } else if (p == 0xf) {
1034 if ((type & IPV6_ADDR_ANONYMIZED_PREFIX) == 0) {
1035 DEBUGPRINT_NA(DEBUG_libipv6addr, "no anonymized prefix found, but p=f -> no anonymized IID");
1036 goto END_ANON_IID;
1037 };
1038 } else {
1039 // check anonymized nibbles in prefix
1040 DEBUGPRINT_WA(DEBUG_libipv6addr, "check now for %d anonymized nibbles in prefix: %04x:%04x:%04x:%04x", p, U32_MSB16(st), U32_LSB16(st), U32_MSB16(st1), U32_LSB16(st1));
1041
1042 if (p >= 8) {
1043 mask_0_15 = 0xffffffff >> ((16 - p) * 4);
1044 mask_16_31 = 0xffffffff;
1045 } else {
1046 mask_0_15 = 0x0;
1047 mask_16_31 = 0xffffffff >> ((8 - p) * 4);
1048 };
1049
1050 // check 1st 32-bit block
1051 if ((st & mask_0_15) != ((ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16)) & mask_0_15)) {
1052 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized parts of prefix doesn't match amount of given nibbles: 0-15=%08x mask=%08x", st, mask_0_15);
1053 goto END_ANON_IID;
1054 };
1055
1056 // check 2nd 32-bit block
1057 if ((st1 & mask_16_31) != ((ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16)) & mask_16_31)) {
1058 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized parts of prefix doesn't match amount of given nibbles: 16-31=%08x mask=%08x", st1, mask_16_31);
1059 goto END_ANON_IID;
1060 };
1061
1062 type2 |= IPV6_ADDR_TYPE2_ANON_MASKED_PREFIX;
1063 ipv6addrp->prefix2length = 64 - 4 * p;
1064 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized masked prefix verified, usable prefix length is %u", ipv6addrp->prefix2length);
1065 };
1066
1067 if (((st2 & ANON_IID_RANDOM_MASK_00_31) == ANON_IID_RANDOM_VALUE_00_31) && ((st3 & ANON_IID_RANDOM_MASK_32_63) == ANON_IID_RANDOM_VALUE_32_63)) {
1068 type |= IPV6_NEW_ADDR_IID_RANDOM | IPV6_ADDR_ANONYMIZED_IID | IPV6_NEW_ADDR_IID_LOCAL;
1069 goto END_ipv6addr_gettype;
1070
1071 } else if (((st2 & ANON_IID_STATIC_MASK_00_31) == ANON_IID_STATIC_VALUE_00_31) && ((st3 & ANON_IID_STATIC_MASK_32_63) == ANON_IID_STATIC_VALUE_32_63)) {
1072 type |= IPV6_NEW_ADDR_IID_LOCAL | IPV6_ADDR_ANONYMIZED_IID;
1073 goto END_ipv6addr_gettype;
1074
1075 } else if (((st2 & ANON_IID_EUI48_MASK_00_31) == ANON_IID_EUI48_VALUE_00_31) && ((st3 & ANON_IID_EUI48_MASK_32_63) == ANON_IID_EUI48_VALUE_32_63)) {
1076 type |= IPV6_NEW_ADDR_IID_EUI48 | IPV6_ADDR_ANONYMIZED_IID;
1077
1078 /* retrieve inverted local/global bit */
1079 if ( (st3 & ANON_IID_EUIxx_SCOPE_MASK) == ANON_IID_EUIxx_SCOPE_GLOBAL) {
1080 type |= IPV6_NEW_ADDR_IID_GLOBAL;
1081 } else {
1082 type |= IPV6_NEW_ADDR_IID_LOCAL;
1083 };
1084 goto END_ipv6addr_gettype;
1085
1086 } else if (((st2 & ANON_IID_EUI64_MASK_00_31) == ANON_IID_EUI64_VALUE_00_31) && ((st3 & ANON_IID_EUI64_MASK_32_63) == ANON_IID_EUI64_VALUE_32_63)) {
1087 type |= IPV6_NEW_ADDR_IID_EUI64 | IPV6_ADDR_ANONYMIZED_IID;
1088
1089 /* retrieve local/global bit */
1090 if ( (st3 & ANON_IID_EUIxx_SCOPE_MASK) == ANON_IID_EUIxx_SCOPE_GLOBAL) {
1091 type |= IPV6_NEW_ADDR_IID_GLOBAL;
1092 } else {
1093 type |= IPV6_NEW_ADDR_IID_LOCAL;
1094 };
1095 goto END_ipv6addr_gettype;
1096
1097 } else if (((st2 & ANON_IID_IPV4_MASK_00_31) == ANON_IID_IPV4_VALUE_00_31) && ((st3 & ANON_IID_IPV4_MASK_32_63) == ANON_IID_IPV4_VALUE_32_63)) {
1098 type |= IPV6_ADDR_IID_32_63_HAS_IPV4 | IPV6_ADDR_ANONYMIZED_IID;
1099 if ((type & IPV6_NEW_ADDR_6TO4) != 0) {
1100 // anonymized 6to4 microsoft address
1101 type |= IPV6_NEW_ADDR_6TO4_MICROSOFT | IPV6_NEW_ADDR_IID_LOCAL;
1102 };
1103 goto END_ipv6addr_gettype;
1104
1105 } else if (((st2 & ANON_IID_ISATAP_MASK_00_31) == ANON_IID_ISATAP_VALUE_00_31)) {
1106 type |= IPV6_NEW_ADDR_IID_ISATAP | IPV6_ADDR_ANONYMIZED_IID;
1107
1108 if ((st3 & ANON_IID_ISATAP_TYPE_MASK_32_63) == ANON_IID_ISATAP_TYPE_IPV4_VALUE_32_63) {
1109 type |= IPV6_ADDR_IID_32_63_HAS_IPV4;
1110 };
1111
1112 if (((st3 & ANON_IID_ISATAP_SCOPE_MASK) == ANON_IID_ISATAP_SCOPE_GLOBAL)) {
1113 type |= IPV6_NEW_ADDR_IID_GLOBAL;
1114 } else {
1115 type |= IPV6_NEW_ADDR_IID_LOCAL;
1116 };
1117 goto END_ipv6addr_gettype;
1118 };
1119
1120
1121 if ((ipv6calc_debug & DEBUG_libipv6addr_anonymization_unknown_break) != 0) { // ipv6calc_debug usage ok
1122 DEBUGPRINT_WA(DEBUG_libipv6addr_anonymization_unknown_break, "unhandled probably anonymized IID found, STOP because of debug level: %08x %08x", st2, st3);
1123 exit(1);
1124 } else {
1125 DEBUGPRINT_NA(DEBUG_libipv6addr, "unhandled probably anonymized IID found (this can really happen), proceed further on");
1126 };;
1127 } else {
1128 DEBUGPRINT_NA(DEBUG_libipv6addr, "checksum WRONG - no anonymized IID found, proceed further on");
1129 };
1130 };
1131
1132 END_ANON_IID:
1133 type |= IPV6_NEW_ADDR_IID_LOCAL;
1134
1135 if ((type & (IPV6_ADDR_IID_32_63_HAS_IPV4 | IPV6_NEW_ADDR_LINKLOCAL_TEREDO | IPV6_NEW_ADDR_IID_ISATAP | IPV6_NEW_ADDR_TEREDO | IPV6_NEW_ADDR_SOLICITED_NODE)) == 0) {
1136 DEBUGPRINT_WA(DEBUG_libipv6addr, "call IID random detection, typeinfo=%08x", type);
1137
1138 /* fuzzy detection of random IID (e.g. privacy extension) */
1139 r = ipv6addr_iidrandomdetection(ipv6addrp, &variances);
1140 if (r == 0) {
1141 type |= IPV6_NEW_ADDR_IID_RANDOM;
1142 } else if (r == 2) {
1143 type |= IPV6_NEW_ADDR_IID_RANDOM | IPV6_ADDR_ANONYMIZED_IID;
1144 } else if (r == 3) {
1145 type |= IPV6_NEW_ADDR_IID_LOCAL | IPV6_ADDR_ANONYMIZED_IID;
1146 };
1147 };
1148 };
1149 };
1150 } else {
1151 type |= IPV6_ADDR_RESERVED;
1152 };
1153
1154 END_ipv6addr_gettype:
1155 ipv6addrp->typeinfo = type;
1156 ipv6addrp->typeinfo2 = type2;
1157 ipv6addrp->flag_typeinfo = 1;
1158 };
1159
1160
1161 /*
1162 * function stores an IPv6 literal address string into a structure
1163 *
1164 * in : *addrstring = IPv6 address
1165 * out: *resultstring = error message
1166 * out: ipv6addrp = changed IPv6 address structure
1167 * ret: ==0: ok, !=0: error
1168 */
addrliteral_to_ipv6addrstruct(const char * addrstring,char * resultstring,const size_t resultstring_length,ipv6calc_ipv6addr * ipv6addrp)1169 int addrliteral_to_ipv6addrstruct(const char *addrstring, char *resultstring, const size_t resultstring_length, ipv6calc_ipv6addr *ipv6addrp) {
1170 int retval = 1;
1171 unsigned int s;
1172 char tempstring[IPV6CALC_STRING_MAX], tempstring2[IPV6CALC_STRING_MAX], *cptr;
1173 const char *literalstring = ".ipv6-literal.net";
1174
1175 resultstring[0] = '\0'; /* clear result string */
1176
1177 DEBUGPRINT_WA(DEBUG_libipv6addr, "Got input '%s'", addrstring);
1178
1179 /* lowercase string */
1180 for (s = 0; s <= strlen(addrstring); s++) {
1181 /* including trailing \0 */
1182 tempstring2[s] = tolower(addrstring[s]);
1183 }
1184
1185 /* search for literal string */
1186 cptr = strstr(tempstring2, literalstring);
1187
1188 DEBUGPRINT_WA(DEBUG_libipv6addr, "String lengths addrstring=%d strstr=%d literal=%d", (unsigned int) strlen(addrstring), (unsigned int) strlen(cptr), (unsigned int) strlen(literalstring));
1189
1190 if (cptr == NULL) {
1191 snprintf(resultstring, resultstring_length, "Error in given IPv6 literal address, has no 'ipv6-literal.net' included!");
1192 return (1);
1193 };
1194
1195 if (strlen(cptr) != strlen(literalstring)) {
1196 snprintf(resultstring, resultstring_length, "Error in given IPv6 literal address, ends not with 'ipv6-literal.net'!");
1197 return (1);
1198 };
1199
1200 /* copy without literal */
1201 snprintf(tempstring, strlen(addrstring) - strlen(literalstring) + 1, "%s", addrstring);
1202
1203 DEBUGPRINT_WA(DEBUG_libipv6addr, "String without literal suffix: %s", tempstring);
1204
1205 /* replace - with : */
1206 for (s = 0; s < strlen(tempstring); s++) {
1207 if (tempstring[s] == '-') {
1208 tempstring[s] = ':';
1209 } else if (tempstring[s] == 's') {
1210 tempstring[s] = '%';
1211 };
1212 };
1213
1214 DEBUGPRINT_WA(DEBUG_libipv6addr, "String converted to non-literal format: %s", tempstring);
1215
1216 /* call normal IPv6 parsing function */
1217 retval = addr_to_ipv6addrstruct(tempstring, resultstring, resultstring_length, ipv6addrp);
1218
1219 return (retval);
1220 };
1221
1222 /*
1223 * function stores an IPv6 address string into a structure
1224 *
1225 * in : *addrstring = IPv6 address
1226 * out: *resultstring = error message
1227 * out: ipv6addrp = changed IPv6 address structure
1228 * ret: ==0: ok, !=0: error
1229 */
addr_to_ipv6addrstruct(const char * addrstring,char * resultstring,const size_t resultstring_length,ipv6calc_ipv6addr * ipv6addrp)1230 int addr_to_ipv6addrstruct(const char *addrstring, char *resultstring, const size_t resultstring_length, ipv6calc_ipv6addr *ipv6addrp) {
1231 int retval = 1, result, i, cpoints = 0, ccolons = 0, cxdigits = 0;
1232 char *addronlystring, *cp, tempstring[IPV6CALC_STRING_MAX], tempstring2[IPV6CALC_STRING_MAX], *cptr, **ptrptr;
1233 int expecteditems = 0;
1234 int temp[8];
1235 unsigned int compat[4];
1236
1237 ptrptr = &cptr;
1238
1239 resultstring[0] = '\0'; /* clear result string */
1240
1241 DEBUGPRINT_WA(DEBUG_libipv6addr, "Got input '%s' (resultstring_length=%u)", addrstring, (unsigned int) resultstring_length);
1242
1243 if (strlen(addrstring) < 2) {
1244 fprintf(stderr, "Error in given IPv6 address, has less than 2 chars!\n");
1245 return (1);
1246 };
1247
1248 if (strlen(addrstring) >= sizeof(tempstring)) {
1249 fprintf(stderr, "Error in given IPv6 address, has too much chars: %s\n", addrstring);
1250 return (1);
1251 };
1252
1253 ipv6addr_clearall(ipv6addrp);
1254
1255 snprintf(tempstring, sizeof(tempstring), "%s", addrstring);
1256
1257 /* save prefix length first, if available */
1258 DEBUGPRINT_WA(DEBUG_libipv6addr, "Call strtok_r, searching for / in %s", tempstring);
1259
1260 addronlystring = strtok_r(tempstring, "/", ptrptr);
1261
1262 if ( addronlystring == NULL ) {
1263 fprintf(stderr, "Strange input (extracting prefix length): %s\n", addrstring);
1264 return (1);
1265 };
1266
1267 DEBUGPRINT_WA(DEBUG_libipv6addr, "Got address only string: %s", addronlystring);
1268
1269 cp = strtok_r (NULL, "/", ptrptr);
1270 if ( cp != NULL ) {
1271 i = atoi(cp);
1272 if (i < 0 || i > 128 ) {
1273 snprintf(resultstring, resultstring_length, "Illegal prefix length: '%s'", cp);
1274 retval = 1;
1275 return (retval);
1276 };
1277 ipv6addrp->flag_prefixuse = 1;
1278 ipv6addrp->prefixlength = (uint8_t) i;
1279
1280 DEBUGPRINT_WA(DEBUG_libipv6addr, "prefix length %u", (unsigned int) ipv6addrp->prefixlength);
1281 DEBUGPRINT_WA(DEBUG_libipv6addr, "flag_prefixuse %d", ipv6addrp->flag_prefixuse);
1282 };
1283
1284 snprintf(tempstring2, sizeof(tempstring2), "%s", addronlystring);
1285
1286 /* save scope ID, if available */
1287 DEBUGPRINT_WA(DEBUG_libipv6addr, "Call strtok_r, searching for %% in %s", tempstring2);
1288
1289 addronlystring = strtok_r(tempstring2, "%%", ptrptr);
1290
1291 if ( addronlystring == NULL ) {
1292 fprintf(stderr, "Strange input (extracting scope ID): %s\n", addrstring);
1293 return (1);
1294 };
1295
1296 DEBUGPRINT_WA(DEBUG_libipv6addr, "Got address only string: %s", addronlystring);
1297
1298 cp = strtok_r (NULL, "%", ptrptr);
1299 if ( cp != NULL ) {
1300 ipv6addrp->flag_scopeid = 1;
1301 snprintf(ipv6addrp->scopeid, sizeof(ipv6addrp->scopeid), "%s", cp);
1302
1303 DEBUGPRINT_WA(DEBUG_libipv6addr, "scope ID : %s", ipv6addrp->scopeid);
1304 DEBUGPRINT_WA(DEBUG_libipv6addr, "flag_scopeid: %d", ipv6addrp->flag_scopeid);
1305 };
1306
1307 if ((strlen(addronlystring) < 2) || (strlen(addronlystring) > 45)) {
1308 /* min: :: */
1309 /* max: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128 */
1310 /* max: ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123 */
1311 snprintf(resultstring, resultstring_length, "Error in given IPv6 address, has not 2 to 45 chars!");
1312 return (1);
1313 };
1314
1315 /* uncompress string, if necessary */
1316 if (strstr(addronlystring, "::") != NULL) {
1317 result = compaddr_to_uncompaddr(addronlystring, tempstring, sizeof(tempstring));
1318 DEBUGPRINT_WA(DEBUG_libipv6addr, "Result of uncompressed string: '%s'", tempstring);
1319 if ( result != 0 ) {
1320 snprintf(resultstring, resultstring_length, "%s", tempstring);
1321 retval = 1;
1322 return (retval);
1323 };
1324 } else {
1325 DEBUGPRINT_WA(DEBUG_libipv6addr, "Copy string: '%s'", addronlystring);
1326 snprintf(tempstring, sizeof(tempstring), "%s", addronlystring);
1327 };
1328
1329 DEBUGPRINT_WA(DEBUG_libipv6addr, "Check string: '%s'", tempstring);
1330
1331 /* count ":", "." and xdigits */
1332 for (i = 0; i < (int) strlen(tempstring); i++) {
1333 if (tempstring[i] == ':') {
1334 ccolons++;
1335 };
1336 if (tempstring[i] == '.') {
1337 cpoints++;
1338 };
1339 if (isxdigit(tempstring[i])) {
1340 cxdigits++;
1341 };
1342 };
1343
1344 /* check amount of ":", must be 6 (compat) or 7 (other) */
1345 if ( ! ( ( ( ccolons == 7 ) && ( cpoints == 0 ) ) || ( ( ccolons == 6 ) && ( cpoints == 3 ) ) ) ) {
1346 if (strstr(addronlystring, "::")) {
1347 snprintf(resultstring, resultstring_length, "Error in given address expanded to '%s' is not valid!", tempstring);
1348 } else {
1349 snprintf(resultstring, resultstring_length, "Error in given address '%s' is not valid!", addrstring);
1350 };
1351 retval = 1;
1352 return (retval);
1353 };
1354
1355 /* amount of ":" + "." + xdigits must be length */
1356 if (ccolons + cpoints + cxdigits != (int) strlen(tempstring)) {
1357 snprintf(resultstring, resultstring_length, "Error in given address '%s' is not valid!", tempstring);
1358 retval = 1;
1359 return (retval);
1360 };
1361
1362 /* clear variables */
1363 for ( i = 0; i <= 3; i++ ) {
1364 compat[i] = 0;
1365 };
1366
1367 ipv6addr_clear(ipv6addrp);
1368
1369 if ( ccolons == 6 ) {
1370 /* compatv4/mapped format */
1371 expecteditems = 10;
1372 result = sscanf(tempstring, "%x:%x:%x:%x:%x:%x:%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5], &compat[0], &compat[1], &compat[2], &compat[3]);
1373 /* check compat */
1374 for ( i = 0; i <= 3; i++ ) {
1375 if ( compat[i] > 255 ) {
1376 snprintf(resultstring, resultstring_length, "Error in given compatv4/mapped IPv6 address, '%s' is not valid on position %d!", addrstring, i);
1377 retval = 1;
1378 return (retval);
1379 };
1380 };
1381 temp[6] = (int) (( compat[0] << 8 ) | compat[1]);
1382 temp[7] = (int) (( compat[2] << 8 ) | compat[3]);
1383 } else {
1384 /* normal format */
1385 expecteditems = 8;
1386 result = sscanf(tempstring, "%x:%x:%x:%x:%x:%x:%x:%x", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5], &temp[6], &temp[7]);
1387 };
1388
1389 DEBUGPRINT_WA(DEBUG_libipv6addr, "reading into array, got items: %d", result);
1390
1391 if ( result != expecteditems ) {
1392 snprintf(resultstring, resultstring_length, "Error in given IPv6 address, splitting of '%s' returns %d items instead of %d!", addronlystring, result, expecteditems);
1393 retval = 1;
1394 return (retval);
1395 };
1396
1397 /* check address words range */
1398 for ( i = 0; i <= 7; i++ ) {
1399 if ( (temp[i] < 0) || (temp[i] > 0xffff) ) {
1400 snprintf(resultstring, resultstring_length, "Error in given IPv6 address, '%s' is not valid on position %d!", addronlystring, i);
1401 retval = 1;
1402 return (retval);
1403 };
1404 };
1405
1406 /* copy into structure */
1407 for ( i = 0; i <= 7; i++ ) {
1408 DEBUGPRINT_WA(DEBUG_libipv6addr, "Push word %u: %04x", (unsigned int) i, (unsigned int) temp[i]);
1409 ipv6addr_setword(ipv6addrp, (unsigned int) i, (unsigned int) temp[i]);
1410 };
1411
1412 DEBUGPRINT_WA(DEBUG_libipv6addr, "In structure %08x %08x %08x %08x", (unsigned int) ipv6addr_getdword(ipv6addrp, 0), (unsigned int) ipv6addr_getdword(ipv6addrp, 1), (unsigned int) ipv6addr_getdword(ipv6addrp, 2), (unsigned int) ipv6addr_getdword(ipv6addrp, 3));
1413 DEBUGPRINT_WA(DEBUG_libipv6addr, "In structure %04x %04x %04x %04x %04x %04x %04x %04x", (unsigned int) ipv6addr_getword(ipv6addrp, 0), (unsigned int) ipv6addr_getword(ipv6addrp, 1), (unsigned int) ipv6addr_getword(ipv6addrp, 2), (unsigned int) ipv6addr_getword(ipv6addrp, 3), (unsigned int) ipv6addr_getword(ipv6addrp, 4), (unsigned int) ipv6addr_getword(ipv6addrp, 5), (unsigned int) ipv6addr_getword(ipv6addrp, 6), (unsigned int) ipv6addr_getword(ipv6addrp, 7));
1414
1415 ipv6addr_settype(ipv6addrp);
1416
1417 DEBUGPRINT_WA(DEBUG_libipv6addr, "flag_prefixuse %d", ipv6addrp->flag_prefixuse);
1418
1419 ipv6addrp->flag_valid = 1;
1420 retval = 0;
1421 return (retval);
1422 };
1423
1424
1425 /*
1426 * stores the ipv6addr structure in an uncompressed IPv6 format string
1427 *
1428 * in: ipv6addr = IPv6 address structure
1429 * out: *resultstring = IPv6 address (modified)
1430 * ret: ==0: ok, !=0: error
1431 */
ipv6addrstruct_to_uncompaddr(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1432 static int ipv6addrstruct_to_uncompaddr(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1433 int retval = 1;
1434 unsigned int s;
1435 char tempstring[IPV6CALC_STRING_MAX], temp2string[IPV6CALC_STRING_MAX];
1436
1437 /* print array */
1438 if ( ((ipv6addrp->typeinfo & (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED | IPV6_ADDR_IID_32_63_HAS_IPV4)) != 0) && ((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_IID) == 0)) {
1439 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1440 snprintf(tempstring, sizeof(tempstring), "%04x:%04x:%04x:%04x:%04x:%04x:%u.%u.%u.%u", \
1441 (unsigned int) ipv6addr_getword(ipv6addrp, 0), \
1442 (unsigned int) ipv6addr_getword(ipv6addrp, 1), \
1443 (unsigned int) ipv6addr_getword(ipv6addrp, 2), \
1444 (unsigned int) ipv6addr_getword(ipv6addrp, 3), \
1445 (unsigned int) ipv6addr_getword(ipv6addrp, 4), \
1446 (unsigned int) ipv6addr_getword(ipv6addrp, 5), \
1447 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1448 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1449 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1450 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1451 );
1452 } else {
1453 snprintf(tempstring, sizeof(tempstring), "%x:%x:%x:%x:%x:%x:%u.%u.%u.%u", \
1454 (unsigned int) ipv6addr_getword(ipv6addrp, 0), \
1455 (unsigned int) ipv6addr_getword(ipv6addrp, 1), \
1456 (unsigned int) ipv6addr_getword(ipv6addrp, 2), \
1457 (unsigned int) ipv6addr_getword(ipv6addrp, 3), \
1458 (unsigned int) ipv6addr_getword(ipv6addrp, 4), \
1459 (unsigned int) ipv6addr_getword(ipv6addrp, 5), \
1460 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1461 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1462 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1463 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1464 );
1465 };
1466 } else {
1467 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1468 snprintf(tempstring, sizeof(tempstring), "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", \
1469 (unsigned int) ipv6addr_getword(ipv6addrp, 0), \
1470 (unsigned int) ipv6addr_getword(ipv6addrp, 1), \
1471 (unsigned int) ipv6addr_getword(ipv6addrp, 2), \
1472 (unsigned int) ipv6addr_getword(ipv6addrp, 3), \
1473 (unsigned int) ipv6addr_getword(ipv6addrp, 4), \
1474 (unsigned int) ipv6addr_getword(ipv6addrp, 5), \
1475 (unsigned int) ipv6addr_getword(ipv6addrp, 6), \
1476 (unsigned int) ipv6addr_getword(ipv6addrp, 7) \
1477 );
1478 } else {
1479 snprintf(tempstring, sizeof(tempstring), "%x:%x:%x:%x:%x:%x:%x:%x", \
1480 (unsigned int) ipv6addr_getword(ipv6addrp, 0), \
1481 (unsigned int) ipv6addr_getword(ipv6addrp, 1), \
1482 (unsigned int) ipv6addr_getword(ipv6addrp, 2), \
1483 (unsigned int) ipv6addr_getword(ipv6addrp, 3), \
1484 (unsigned int) ipv6addr_getword(ipv6addrp, 4), \
1485 (unsigned int) ipv6addr_getword(ipv6addrp, 5), \
1486 (unsigned int) ipv6addr_getword(ipv6addrp, 6), \
1487 (unsigned int) ipv6addr_getword(ipv6addrp, 7) \
1488 );
1489 };
1490 };
1491
1492 if ((ipv6addrp->flag_prefixuse == 1) && ((formatoptions & (FORMATOPTION_literal | FORMATOPTION_no_prefixlength)) == 0)) {
1493 /* append prefix length */
1494 snprintf(resultstring, resultstring_length, "%s/%u", tempstring, (unsigned int) ipv6addrp->prefixlength);
1495 } else {
1496 if ((formatoptions & FORMATOPTION_literal) != 0) {
1497 /* replace : by - */
1498 for (s = 0; s < strlen(tempstring); s++) {
1499 if (tempstring[s] == ':') {
1500 tempstring[s] = '-';
1501 };
1502 };
1503
1504 if (ipv6addrp->flag_scopeid) {
1505 snprintf(resultstring, resultstring_length, "%ss%s.ipv6-literal.net", tempstring, ipv6addrp->scopeid);
1506 } else {
1507 snprintf(resultstring, resultstring_length, "%s.ipv6-literal.net", tempstring);
1508 }
1509 } else {
1510 if (ipv6addrp->flag_scopeid) {
1511 snprintf(resultstring, resultstring_length, "%s%%%s", tempstring, ipv6addrp->scopeid);
1512 } else {
1513 snprintf(resultstring, resultstring_length, "%s", tempstring);
1514 };
1515 };
1516 };
1517
1518 if ( (formatoptions & FORMATOPTION_machinereadable) != 0 ) {
1519 snprintf(temp2string, sizeof(temp2string), "IPV6=%s", resultstring);
1520 snprintf(resultstring, resultstring_length, "%s", temp2string);
1521 };
1522
1523 retval = 0;
1524 return (retval);
1525 };
1526
1527
1528 /*
1529 * stores the prefix of an ipv6addr structure in an uncompressed IPv6 format string
1530 *
1531 * in: ipv6addr = IPv6 address structure, formatoptions
1532 * out: *resultstring = IPv6 address (modified)
1533 * ret: ==0: ok, !=0: error
1534 */
ipv6addrstruct_to_uncompaddrprefix(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1535 static int ipv6addrstruct_to_uncompaddrprefix(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1536 int retval = 1;
1537 unsigned int max, i;
1538 char tempstring1[IPV6CALC_STRING_MAX], tempstring2[IPV6CALC_STRING_MAX];
1539
1540 DEBUGPRINT_NA(DEBUG_libipv6addr, "called");
1541
1542 /* test for misuse */
1543 if ( ((ipv6addrp->typeinfo & (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED)) != 0 ) && (ipv6addrp->prefixlength > 96) ) {
1544 snprintf(resultstring, resultstring_length, "Error, cannot print prefix of a compatv4/mapped address with prefix length bigger than 96!");
1545 retval = 1;
1546 return (retval);
1547 };
1548 if ( ipv6addrp->prefixlength == 0 ) {
1549 snprintf(resultstring, resultstring_length, "Error, cannot print prefix of a address with prefix length 0!");
1550 retval = 1;
1551 return (retval);
1552 };
1553
1554 max = ( (unsigned int) ipv6addrp->prefixlength - 1 ) / 16u;
1555 i = 0;
1556 tempstring1[0] = '\0';
1557 while (i <= max ) {
1558 if ( i < max ) {
1559 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1560 snprintf(tempstring2, sizeof(tempstring2), "%s%04x:", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1561 } else {
1562 snprintf(tempstring2, sizeof(tempstring2), "%s%x:", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1563 };
1564 } else {
1565 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1566 snprintf(tempstring2, sizeof(tempstring2), "%s%04x", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1567 } else {
1568 snprintf(tempstring2, sizeof(tempstring2), "%s%x", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1569 };
1570 };
1571 i++;
1572 snprintf(tempstring1, sizeof(tempstring1), "%s", tempstring2);
1573 };
1574 snprintf(resultstring, resultstring_length, "%s", tempstring1);
1575
1576 DEBUGPRINT_WA(DEBUG_libipv6addr, "result string: %s", resultstring);
1577
1578 retval = 0;
1579 return (retval);
1580 };
1581
1582
1583 /*
1584 * function stores the suffix of an ipv6addr structure in an uncompressed IPv6 format string
1585 *
1586 * in: ipv6addr = IPv6 address structure
1587 * out: *resultstring = IPv6 address (modified)
1588 * ret: ==0: ok, !=0: error
1589 */
ipv6addrstruct_to_uncompaddrsuffix(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1590 static int ipv6addrstruct_to_uncompaddrsuffix(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1591 int retval = 1;
1592 unsigned int max, i;
1593 char tempstring1[IPV6CALC_STRING_MAX], tempstring2[IPV6CALC_STRING_MAX];
1594
1595 DEBUGPRINT_NA(DEBUG_libipv6addr, "called");
1596
1597 /* test for misuse */
1598 if ( ( (ipv6addrp->typeinfo & (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED)) != 0) && ( ipv6addrp->prefixlength > 96 ) ) {
1599 snprintf(resultstring, resultstring_length, "Error, cannot print suffix of a compatv4/mapped address with prefix length bigger than 96!");
1600 retval = 1;
1601 return (retval);
1602 };
1603 if ( ipv6addrp->prefixlength == 128 ) {
1604 snprintf(resultstring, resultstring_length, "Error, cannot print suffix of a address with prefix length 128!");
1605 retval = 1;
1606 return (retval);
1607 };
1608
1609 max = 7;
1610 i = (unsigned int) ipv6addrp->prefixlength / 16u;
1611 tempstring1[0] = '\0';
1612 while (i <= max ) {
1613 if ( ( ( ipv6addrp->typeinfo & (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED)) != 0 ) && ( i == 6 ) ) {
1614 snprintf(tempstring2, sizeof(tempstring2), "%s%u.%u.%u.%u", tempstring1, \
1615 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1616 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1617 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1618 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1619 );
1620 i = max;
1621 } else if ( i < max ) {
1622 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1623 snprintf(tempstring2, sizeof(tempstring2), "%s%04x:", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1624 } else {
1625 snprintf(tempstring2, sizeof(tempstring2), "%s%x:", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1626 };
1627 } else {
1628 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1629 snprintf(tempstring2, sizeof(tempstring2), "%s%04x", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1630 } else {
1631 snprintf(tempstring2, sizeof(tempstring2), "%s%x", tempstring1, (unsigned int) ipv6addr_getword(ipv6addrp, i));
1632 };
1633 };
1634 i++;
1635 snprintf(tempstring1, sizeof(tempstring1), "%s", tempstring2);
1636 };
1637 snprintf(resultstring, resultstring_length, "%s", tempstring1);
1638
1639 DEBUGPRINT_WA(DEBUG_libipv6addr, "result string: %s", resultstring);
1640
1641 retval = 0;
1642 return (retval);
1643 };
1644
1645
libipv6addr_ipv6addrstruct_to_uncompaddr(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1646 int libipv6addr_ipv6addrstruct_to_uncompaddr(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1647 int retval = 1;
1648
1649 DEBUGPRINT_WA(DEBUG_libipv6addr, "get format option: %08x", (unsigned int) formatoptions);
1650
1651 if ( (formatoptions & FORMATOPTION_printprefix) != 0 ) {
1652 retval = ipv6addrstruct_to_uncompaddrprefix(ipv6addrp, resultstring, resultstring_length, formatoptions);
1653 } else if ( (formatoptions & FORMATOPTION_printsuffix) != 0 ) {
1654 retval = ipv6addrstruct_to_uncompaddrsuffix(ipv6addrp, resultstring, resultstring_length, formatoptions);
1655 } else {
1656 retval = ipv6addrstruct_to_uncompaddr(ipv6addrp, resultstring, resultstring_length, formatoptions);
1657 };
1658
1659 if (retval == 0) {
1660 /* don't modify case on error messages */
1661 if ( (formatoptions & FORMATOPTION_printlowercase) != 0 ) {
1662 /* nothing to do */
1663 } else if ( (formatoptions & FORMATOPTION_printuppercase) != 0 ) {
1664 string_to_upcase(resultstring);
1665 };
1666 };
1667
1668 DEBUGPRINT_WA(DEBUG_libipv6addr, "result string: %s", resultstring);
1669
1670 retval = 0;
1671 return (retval);
1672 };
1673
1674
1675 /*
1676 * mask prefix bits (set suffix bits to 0)
1677 *
1678 * in: structure via reference
1679 * out: modified structure
1680 */
ipv6addrstruct_maskprefix(ipv6calc_ipv6addr * ipv6addrp)1681 void ipv6addrstruct_maskprefix(ipv6calc_ipv6addr *ipv6addrp) {
1682 unsigned int nbit, nword;
1683 uint16_t mask, newword;
1684 int i;
1685
1686 DEBUGPRINT_NA(DEBUG_libipv6addr, "called");
1687
1688 if (ipv6addrp->flag_prefixuse != 1) {
1689 /* hmm, no prefix specified. skip */
1690 return;
1691 };
1692
1693 for (i = 127; i >= 0; i--) {
1694 nbit = (unsigned int) i;
1695 if (nbit >= (unsigned int) ipv6addrp->prefixlength) {
1696 /* set bit to zero */
1697
1698 /* calculate word (16 bit) - matches with addr6p[]*/
1699 nword = (nbit & 0x70) >> 4;
1700
1701 /* calculate mask */
1702 mask = ((uint16_t) 0x8000u) >> (( ((uint16_t) nbit) & ((uint16_t) 0x0fu)));
1703 newword = ipv6addr_getword(ipv6addrp, nword) & (~ mask );
1704
1705 DEBUGPRINT_WA(DEBUG_libipv6addr, "bit: %u = nword: %u, mask: %04x, word: %04x newword: %04x", nbit, nword, (unsigned int) mask, (unsigned int) ipv6addr_getword(ipv6addrp, nword), (unsigned int) newword);
1706
1707 ipv6addr_setword(ipv6addrp, nword, (unsigned int) newword);
1708 };
1709 };
1710 };
1711
1712
1713 /*
1714 * mask suffix bits (set prefix bits to 0)
1715 *
1716 * in: structure via reference
1717 * out: modified structure
1718 */
ipv6addrstruct_masksuffix(ipv6calc_ipv6addr * ipv6addrp)1719 void ipv6addrstruct_masksuffix(ipv6calc_ipv6addr *ipv6addrp) {
1720 unsigned int nbit, nword;
1721 uint16_t mask, newword;
1722 int i;
1723
1724 DEBUGPRINT_NA(DEBUG_libipv6addr, "called");
1725
1726 if (ipv6addrp->flag_prefixuse != 1) {
1727 /* hmm, no prefix specified. skip */
1728 return;
1729 };
1730
1731 for (i = 127; i >= 0; i--) {
1732 nbit = (unsigned int) i;
1733
1734 if (nbit < (unsigned int) ipv6addrp->prefixlength) {
1735 /* set bit to zero */
1736
1737 /* calculate word (16 bit) - matches with addr6p[]*/
1738 nword = (nbit & 0x70) >> 4;
1739
1740 /* calculate mask */
1741 mask = ((uint32_t) 0x8000u) >> (((uint32_t) nbit) & ((uint32_t) 0x0fu ));
1742 newword = ipv6addr_getword(ipv6addrp, nword) & (~ mask );
1743
1744 DEBUGPRINT_WA(DEBUG_libipv6addr, "%u = nword: %u, mask: %04x, word: %04x newword: %04x", nbit, nword, (unsigned int) mask, (unsigned int) ipv6addr_getword(ipv6addrp, nword), (unsigned int) newword);
1745
1746 ipv6addr_setword(ipv6addrp, nword, (unsigned int) newword);
1747 };
1748 };
1749 };
1750
1751
1752 /*
1753 * function stores an 16 char token into a structure
1754 *
1755 * in : *addrstring = 16 char token
1756 * out: *resultstring = error message
1757 * out: ipv6addr = IPv6 address structure
1758 * ret: ==0: ok, !=0: error
1759 */
tokenlsb64_to_ipv6addrstruct(const char * addrstring,char * resultstring,const size_t resultstring_length,ipv6calc_ipv6addr * ipv6addrp)1760 int tokenlsb64_to_ipv6addrstruct(const char *addrstring, char *resultstring, const size_t resultstring_length, ipv6calc_ipv6addr *ipv6addrp) {
1761 int retval = 1, result;
1762 int temp[4];
1763 char tempstring[IPV6CALC_STRING_MAX];
1764
1765 resultstring[0] = '\0'; /* clear result string */
1766
1767 DEBUGPRINT_WA(DEBUG_libipv6addr, "got input '%s'", addrstring);
1768
1769 if ( strlen(addrstring) != 16 ) {
1770 snprintf(resultstring, resultstring_length, "Error in given token '%s' is not valid (length != 16)!", addrstring);
1771 retval = 1;
1772 return (retval);
1773 };
1774
1775 /* scan address into array */
1776 result = sscanf(addrstring, "%04x%04x%04x%04x", &temp[0], &temp[1], &temp[2], &temp[3]);
1777 if ( result != 4 ) {
1778 snprintf(resultstring, resultstring_length, "Error splitting address '%s', got %d items instead of 4!", addrstring, result);
1779 retval = 1;
1780 return (retval);
1781 };
1782
1783 /* set prefix */
1784 snprintf(tempstring, sizeof(tempstring), "0:0:0:0:%04x:%04x:%04x:%04x", \
1785 (unsigned int) temp[0] ,\
1786 (unsigned int) temp[1], \
1787 (unsigned int) temp[2], \
1788 (unsigned int) temp[3] \
1789 );
1790
1791 /* store into structure */
1792 retval = addr_to_ipv6addrstruct(tempstring, resultstring, sizeof(resultstring), ipv6addrp);
1793
1794 return (retval);
1795 };
1796
1797 /*
1798 * function stores an interface identifier into a structure
1799 *
1800 * in : *addrstring = interface identifier
1801 * out: *resultstring = error message
1802 * out: ipv6addr = IPv6 address structure
1803 * ret: ==0: ok, !=0: error
1804 */
identifier_to_ipv6addrstruct(const char * addrstring,char * resultstring,const size_t resultstring_length,ipv6calc_ipv6addr * ipv6addrp)1805 int identifier_to_ipv6addrstruct(const char *addrstring, char *resultstring, const size_t resultstring_length, ipv6calc_ipv6addr *ipv6addrp) {
1806 int retval = 1, i, ccolons = 0;
1807 char tempstring[IPV6CALC_STRING_MAX];
1808
1809 resultstring[0] = '\0'; /* clear result string */
1810
1811 DEBUGPRINT_WA(DEBUG_libipv6addr, "Got input '%s'", addrstring);
1812
1813 if ((strlen(addrstring) < 2) || (strlen(addrstring) > 19)) {
1814 /* min: :: */
1815 /* max: ffff:ffff:ffff:ffff */
1816 snprintf(resultstring, resultstring_length, "Error in given identifier identifier, has not 2 to 19 chars!");
1817 retval = 1;
1818 return (retval);
1819 };
1820
1821 /* count ":", must be 2 to 3 */
1822 for (i = 0; i < (int) strlen(addrstring); i++) {
1823 if (addrstring[i] == ':') {
1824 ccolons++;
1825 };
1826 };
1827 if ((ccolons < 2) || (ccolons > 3)) {
1828 snprintf(resultstring, resultstring_length, "Error in given identifier '%s' is not valid!", addrstring);
1829 retval = 1;
1830 return (retval);
1831 };
1832
1833 /* set prefix */
1834 snprintf(tempstring, sizeof(tempstring), "0:0:0:0:%s", addrstring);
1835
1836 /* store into structure */
1837 retval = addr_to_ipv6addrstruct(tempstring, resultstring, sizeof(resultstring), ipv6addrp);
1838
1839 DEBUGPRINT_WA(DEBUG_libipv6addr, "result string '%s'", resultstring);
1840
1841 return (retval);
1842 };
1843
1844 /*
1845 * function stores the ipv6addr structure in an uncompressed IPv6 format string
1846 *
1847 * in: ipv6addr = IPv6 address structure
1848 * out: *resultstring = IPv6 address (modified)
1849 * ret: ==0: ok, !=0: error
1850 */
libipv6addr_ipv6addrstruct_to_tokenlsb64(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,uint32_t formatoptions)1851 int libipv6addr_ipv6addrstruct_to_tokenlsb64(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, uint32_t formatoptions) {
1852 int retval = 1;
1853
1854 /* print array */
1855 snprintf(resultstring, resultstring_length, "%04x%04x%04x%04x", \
1856 (unsigned int) ipv6addr_getword(ipv6addrp, 4), \
1857 (unsigned int) ipv6addr_getword(ipv6addrp, 5), \
1858 (unsigned int) ipv6addr_getword(ipv6addrp, 6), \
1859 (unsigned int) ipv6addr_getword(ipv6addrp, 7) \
1860 );
1861
1862 if ( (formatoptions & FORMATOPTION_printlowercase) != 0 ) {
1863 /* nothing to do */
1864 } else if ( (formatoptions & FORMATOPTION_printuppercase) != 0 ) {
1865 string_to_upcase(resultstring);
1866 };
1867
1868 DEBUGPRINT_WA(DEBUG_libipv6addr, "result string '%s'", resultstring);
1869
1870 retval = 0;
1871 return (retval);
1872 };
1873
1874
1875 /*
1876 * function prints an IPv6 address in native octal format
1877 *
1878 * in: ipv6addr = IPv6 address structure
1879 * formatoptions
1880 * out: *resultstring = IPv6 address (modified)
1881 * ret: ==0: ok, !=0: error
1882 */
libipv6addr_to_octal(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1883 int libipv6addr_to_octal(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1884 int retval = 1;
1885 char tempstring[IPV6CALC_STRING_MAX];
1886
1887 if ( (formatoptions & FORMATOPTION_printfulluncompressed) != 0 ) {
1888 snprintf(tempstring, sizeof(tempstring), "\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o\\0%03o",
1889 (unsigned int) ipv6addrp->in6_addr.s6_addr[0], \
1890 (unsigned int) ipv6addrp->in6_addr.s6_addr[1], \
1891 (unsigned int) ipv6addrp->in6_addr.s6_addr[2], \
1892 (unsigned int) ipv6addrp->in6_addr.s6_addr[3], \
1893 (unsigned int) ipv6addrp->in6_addr.s6_addr[4], \
1894 (unsigned int) ipv6addrp->in6_addr.s6_addr[5], \
1895 (unsigned int) ipv6addrp->in6_addr.s6_addr[6], \
1896 (unsigned int) ipv6addrp->in6_addr.s6_addr[7], \
1897 (unsigned int) ipv6addrp->in6_addr.s6_addr[8], \
1898 (unsigned int) ipv6addrp->in6_addr.s6_addr[9], \
1899 (unsigned int) ipv6addrp->in6_addr.s6_addr[10], \
1900 (unsigned int) ipv6addrp->in6_addr.s6_addr[11], \
1901 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1902 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1903 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1904 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1905 );
1906 } else {
1907 snprintf(tempstring, sizeof(tempstring), "\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o\\0%o",
1908 (unsigned int) ipv6addrp->in6_addr.s6_addr[0], \
1909 (unsigned int) ipv6addrp->in6_addr.s6_addr[1], \
1910 (unsigned int) ipv6addrp->in6_addr.s6_addr[2], \
1911 (unsigned int) ipv6addrp->in6_addr.s6_addr[3], \
1912 (unsigned int) ipv6addrp->in6_addr.s6_addr[4], \
1913 (unsigned int) ipv6addrp->in6_addr.s6_addr[5], \
1914 (unsigned int) ipv6addrp->in6_addr.s6_addr[6], \
1915 (unsigned int) ipv6addrp->in6_addr.s6_addr[7], \
1916 (unsigned int) ipv6addrp->in6_addr.s6_addr[8], \
1917 (unsigned int) ipv6addrp->in6_addr.s6_addr[9], \
1918 (unsigned int) ipv6addrp->in6_addr.s6_addr[10], \
1919 (unsigned int) ipv6addrp->in6_addr.s6_addr[11], \
1920 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1921 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1922 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1923 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1924 );
1925 };
1926
1927 snprintf(resultstring, resultstring_length, "%s", tempstring);
1928 retval = 0;
1929 return (retval);
1930 };
1931
1932
1933 /*
1934 * function prints an IPv6 address in native hex format
1935 *
1936 * in: ipv6addr = IPv6 address structure
1937 * formatoptions
1938 * out: *resultstring = IPv6 address (modified)
1939 * ret: ==0: ok, !=0: error
1940 */
libipv6addr_to_hex(const ipv6calc_ipv6addr * ipv6addrp,char * resultstring,const size_t resultstring_length,const uint32_t formatoptions)1941 int libipv6addr_to_hex(const ipv6calc_ipv6addr *ipv6addrp, char *resultstring, const size_t resultstring_length, const uint32_t formatoptions) {
1942 int retval = 1;
1943 int i;
1944 unsigned int s;
1945 char tempstring[IPV6CALC_STRING_MAX];
1946
1947 snprintf(tempstring, sizeof(tempstring), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
1948 (unsigned int) ipv6addrp->in6_addr.s6_addr[0], \
1949 (unsigned int) ipv6addrp->in6_addr.s6_addr[1], \
1950 (unsigned int) ipv6addrp->in6_addr.s6_addr[2], \
1951 (unsigned int) ipv6addrp->in6_addr.s6_addr[3], \
1952 (unsigned int) ipv6addrp->in6_addr.s6_addr[4], \
1953 (unsigned int) ipv6addrp->in6_addr.s6_addr[5], \
1954 (unsigned int) ipv6addrp->in6_addr.s6_addr[6], \
1955 (unsigned int) ipv6addrp->in6_addr.s6_addr[7], \
1956 (unsigned int) ipv6addrp->in6_addr.s6_addr[8], \
1957 (unsigned int) ipv6addrp->in6_addr.s6_addr[9], \
1958 (unsigned int) ipv6addrp->in6_addr.s6_addr[10], \
1959 (unsigned int) ipv6addrp->in6_addr.s6_addr[11], \
1960 (unsigned int) ipv6addrp->in6_addr.s6_addr[12], \
1961 (unsigned int) ipv6addrp->in6_addr.s6_addr[13], \
1962 (unsigned int) ipv6addrp->in6_addr.s6_addr[14], \
1963 (unsigned int) ipv6addrp->in6_addr.s6_addr[15] \
1964 );
1965
1966 snprintf(resultstring, resultstring_length, "%s", tempstring);
1967
1968 if ((formatoptions & FORMATOPTION_printprefix) && (ipv6addrp->flag_prefixuse == 1)) {
1969 // shorten string
1970 resultstring[ipv6addrp->prefixlength / 4] = '\0';
1971 } else if ((formatoptions & FORMATOPTION_printsuffix) && (ipv6addrp->flag_prefixuse == 1)) {
1972 // move string
1973 for (i = 0; i < 32 - (ipv6addrp->prefixlength / 4); i++) {
1974 resultstring[i] = resultstring[i + (ipv6addrp->prefixlength / 4)];
1975 };
1976 resultstring[32 - (ipv6addrp->prefixlength / 4)] = '\0';
1977 };
1978
1979 if (formatoptions & FORMATOPTION_printuppercase) {
1980 for (s = 0; s < strlen(resultstring); s++) {
1981 resultstring[s] = toupper(resultstring[s]);
1982 };
1983 };
1984
1985 retval = 0;
1986 return (retval);
1987 };
1988
1989
1990 /*
1991 * retrieve payload of anonymized prefix
1992 *
1993 * in: ipv6addrp = pointer to IPv6 address structure
1994 * payload_selector: payload which should be retrieved
1995 * result_ptr = pointer to a 32-bit result
1996 * out: 0 = OK, !=0: not ok
1997 */
ipv6addr_get_payload_anonymized_prefix(const ipv6calc_ipv6addr * ipv6addrp,const int payload_selector,uint32_t * result_ptr)1998 int ipv6addr_get_payload_anonymized_prefix(const ipv6calc_ipv6addr *ipv6addrp, const int payload_selector, uint32_t *result_ptr) {
1999 uint32_t prefix[2], flags;
2000
2001 prefix[0] = ipv6addr_getdword(ipv6addrp, 0);
2002 prefix[1] = ipv6addr_getdword(ipv6addrp, 1);
2003
2004 // retrieve flags
2005 flags = UNPACK_XMS(prefix[ANON_PREFIX_FLAGS_DWORD], ANON_PREFIX_FLAGS_XOR, ANON_PREFIX_FLAGS_MASK, ANON_PREFIX_FLAGS_SHIFT);
2006
2007 DEBUGPRINT_WA(DEBUG_libipv6addr, "Get payload %d from %08x%08x (flags=%x)", payload_selector, prefix[0], prefix[1], flags);
2008
2009 if (payload_selector == ANON_PREFIX_PAYLOAD_FLAGS) {
2010 *result_ptr = flags;
2011 } else {
2012 if ((flags != 0) && (flags != 1)) {
2013 // currently only flags=0| is supported
2014 return(1);
2015 };
2016
2017 if (payload_selector == ANON_PREFIX_PAYLOAD_CCINDEX) {
2018 *result_ptr = UNPACK_XMS(prefix[ANON_PREFIX_CCINDEX_DWORD], ANON_PREFIX_CCINDEX_XOR, ANON_PREFIX_CCINDEX_MASK, ANON_PREFIX_CCINDEX_SHIFT);
2019 } else if (payload_selector == ANON_PREFIX_PAYLOAD_ASN32) {
2020 *result_ptr = (UNPACK_XMS(prefix[ANON_PREFIX_ASN32_MSB_DWORD], ANON_PREFIX_ASN32_MSB_XOR, ANON_PREFIX_ASN32_MSB_MASK, ANON_PREFIX_ASN32_MSB_SHIFT) << ANON_PREFIX_ASN32_LSB_AMOUNT)| (UNPACK_XMS(prefix[ANON_PREFIX_ASN32_LSB_DWORD], ANON_PREFIX_ASN32_LSB_XOR, ANON_PREFIX_ASN32_LSB_MASK, ANON_PREFIX_ASN32_LSB_SHIFT));
2021 } else if (payload_selector == ANON_PREFIX_PAYLOAD_GEONAMEID) {
2022 *result_ptr = (UNPACK_XMS(prefix[ANON_PREFIX_GEONAMEID_MSB_DWORD], ANON_PREFIX_GEONAMEID_MSB_XOR, ANON_PREFIX_GEONAMEID_MSB_MASK, ANON_PREFIX_GEONAMEID_MSB_SHIFT) << ANON_PREFIX_GEONAMEID_LSB_AMOUNT)| (UNPACK_XMS(prefix[ANON_PREFIX_GEONAMEID_LSB_DWORD], ANON_PREFIX_GEONAMEID_LSB_XOR, ANON_PREFIX_GEONAMEID_LSB_MASK, ANON_PREFIX_GEONAMEID_LSB_SHIFT));
2023 } else if (payload_selector == ANON_PREFIX_PAYLOAD_GEONAMEID_TYPE) {
2024 *result_ptr = UNPACK_XMS(prefix[ANON_PREFIX_GEONAMEID_TYPE_DWORD], ANON_PREFIX_GEONAMEID_TYPE_XOR, ANON_PREFIX_GEONAMEID_TYPE_MASK, ANON_PREFIX_GEONAMEID_TYPE_SHIFT);
2025 } else {
2026 ERRORPRINT_WA("payload_selector out of range, FIX CODE: %d", payload_selector);
2027 exit(EXIT_FAILURE);
2028 };
2029 };
2030
2031 DEBUGPRINT_WA(DEBUG_libipv6addr, "Extracted payload %d from %08x%08x: %08x", payload_selector, prefix[0], prefix[1], *result_ptr);
2032
2033 return(0);
2034 };
2035
2036
2037 /*
2038 * retrieve payload of anonymized IID
2039 *
2040 * in: ipv6addrp = pointer to IPv6 address structure
2041 * out: payload (max. 32 bit)
2042 */
ipv6addr_get_payload_anonymized_iid(const ipv6calc_ipv6addr * ipv6addrp,const uint32_t typeinfo)2043 uint32_t ipv6addr_get_payload_anonymized_iid(const ipv6calc_ipv6addr *ipv6addrp, const uint32_t typeinfo) {
2044 uint32_t iid[2];
2045 uint32_t payload = 0;
2046
2047 iid[0] = ipv6addr_getdword(ipv6addrp, 2);
2048 iid[1] = ipv6addr_getdword(ipv6addrp, 3);
2049
2050 DEBUGPRINT_WA(DEBUG_libipv6addr, "typeinfo=%08x iid[0]=%08x iid[1]=%08x", typeinfo, iid[0], iid[1]);
2051
2052 if ((typeinfo & IPV6_NEW_ADDR_IID_EUI48) != 0) {
2053 payload = (iid[1] >> ANON_IID_EUI48_PAYLOAD_SHIFT) & ((2 << ANON_IID_EUI48_PAYLOAD_LENGTH) - 1);
2054 } else if ((typeinfo & IPV6_NEW_ADDR_IID_EUI64) != 0) {
2055 payload = (iid[1] >> ANON_IID_EUI64_PAYLOAD_SHIFT) & ((2 << ANON_IID_EUI64_PAYLOAD_LENGTH) - 1);
2056 } else if ((typeinfo & (IPV6_NEW_ADDR_IID_ISATAP|IPV6_ADDR_IID_32_63_HAS_IPV4)) != 0) {
2057 payload = (iid[1] >> ANON_IID_ISATAP_PAYLOAD_SHIFT) & ((2 << ANON_IID_ISATAP_PAYLOAD_LENGTH) - 1);
2058 } else if ((typeinfo & IPV6_ADDR_IID_32_63_HAS_IPV4) != 0) {
2059 payload = (iid[1] >> ANON_IID_IPV4_PAYLOAD_SHIFT) & ((2 << ANON_IID_IPV4_PAYLOAD_LENGTH) - 1);
2060 };
2061
2062 DEBUGPRINT_WA(DEBUG_libipv6addr, "payload=%08x", payload);
2063
2064 return(payload);
2065 };
2066
2067
2068 /*
2069 * anonymize IPv6 address
2070 *
2071 * in : *ipv6addrp = IPv6 address structure
2072 * *ipv6calc_anon_set = anonymization set structure
2073 * ret: 0:anonymization ok
2074 * 1:anonymization method not supported
2075 */
libipv6addr_anonymize(ipv6calc_ipv6addr * ipv6addrp,const s_ipv6calc_anon_set * ipv6calc_anon_set)2076 int libipv6addr_anonymize(ipv6calc_ipv6addr *ipv6addrp, const s_ipv6calc_anon_set *ipv6calc_anon_set) {
2077 /* anonymize IPv4 address according to settings */
2078 uint32_t iid[2];
2079 char tempstring[IPV6CALC_STRING_MAX];
2080 char helpstring[IPV6CALC_STRING_MAX];
2081 int i, r;
2082 int calculate_checksum = 0;
2083 int calculate_checksum_prefix = 0;
2084 int zeroize_prefix = 0;
2085 int zeroize_iid = 0;
2086 int anonymized_prefix_nibbles = 0;
2087
2088 ipv6calc_macaddr macaddr;
2089 ipv6calc_eui64addr eui64addr;
2090 ipv6calc_ipv4addr ipv4addr;
2091 ipv6calc_ipaddr ipaddr;
2092 uint32_t map_value;
2093
2094 uint16_t cc_index, flags = 0;
2095 uint32_t as_num32, ipv6_prefix[2];
2096
2097 int mask_eui64 = ipv6calc_anon_set->mask_eui64;
2098 // int mask_mac = ipv6calc_anon_set->mask_mac; // currently not used
2099 int mask_ipv6 = ipv6calc_anon_set->mask_ipv6;
2100 int mask_ipv4 = ipv6calc_anon_set->mask_ipv4;
2101 int method = ipv6calc_anon_set->method;
2102
2103 uint8_t bit_ul = 0;
2104
2105 DEBUGPRINT_WA(DEBUG_libipv6addr, "Called: addr=%08x %08x %08x %08x", ipv6addr_getdword(ipv6addrp, 0), ipv6addr_getdword(ipv6addrp, 1), ipv6addr_getdword(ipv6addrp, 2), ipv6addr_getdword(ipv6addrp, 3));
2106
2107 ipv6addr_settype(ipv6addrp);
2108
2109 if (method == ANON_METHOD_ZEROIZE) {
2110 zeroize_prefix = 1;
2111 };
2112
2113 if ( (ipv6calc_debug & DEBUG_libipv6addr) != 0 ) { // ipv6calc_debug usage ok
2114 libipv6calc_anon_infostring(tempstring, sizeof(tempstring), ipv6calc_anon_set);
2115 DEBUGPRINT_WA(DEBUG_libipv6addr, "Anonymize IPv6 address flags: %s", tempstring);
2116 };
2117
2118 if ((ipv6addrp->typeinfo & (IPV6_ADDR_ANONYMIZED_IID | IPV6_ADDR_ANONYMIZED_PREFIX)) != 0) {
2119 DEBUGPRINT_NA(DEBUG_libipv6addr, "Already anonymized IPv6 address - skip");
2120 return(0);
2121 };
2122
2123 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6TO4) != 0) {
2124 DEBUGPRINT_NA(DEBUG_libipv6addr, "Embedded IPv4 address, anonymize and store back");
2125 ipv4addr_clearall(&ipv4addr);
2126 /* extract IPv4 address */
2127 for (i = 0; i <= 3; i++) {
2128 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) 2 + i));
2129 };
2130
2131 ipv4addr_settype(&ipv4addr, 1); /* Set typeinfo */
2132 ipv4addr.flag_valid = 1;
2133 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2134
2135 /* store back */
2136 for (i = 0; i <= 3; i++) {
2137 ipv6addr_setoctet(ipv6addrp, (unsigned int) 2 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i));
2138 };
2139
2140 };
2141
2142 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_TEREDO) != 0) {
2143 /* extract Teredo client IPv4 address */
2144 ipv4addr_clearall(&ipv4addr);
2145 for (i = 0; i <= 3; i++) {
2146 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) 12 + i) ^ 0xff);
2147 };
2148
2149 ipv4addr_settype(&ipv4addr, 1);
2150 ipv4addr.flag_valid = 1;
2151 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2152
2153 /* store back */
2154 for (i = 0; i <= 3; i++) {
2155 ipv6addr_setoctet(ipv6addrp, (unsigned int) 12 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i) ^ 0xff);
2156 };
2157
2158 /* clear client port */
2159 ipv6addr_setword(ipv6addrp, 5, 0 ^ 0xffff);
2160 };
2161
2162 if ((ipv6addrp->typeinfo & (IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_NEW_ADDR_NAT64)) != 0) {
2163 /* extract IPv4 address */
2164 ipv4addr_clearall(&ipv4addr);
2165 for (i = 0; i <= 3; i++) {
2166 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) 12 + i));
2167 };
2168
2169 ipv4addr_settype(&ipv4addr, 1);
2170 ipv4addr.flag_valid = 1;
2171 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2172
2173 /* store back */
2174 for (i = 0; i <= 3; i++) {
2175 ipv6addr_setoctet(ipv6addrp, (unsigned int) 12 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i));
2176 };
2177 };
2178
2179 /* prefix handling */
2180 if ( ((ipv6addrp->typeinfo & (IPV6_ADDR_SITELOCAL | IPV6_ADDR_ULUA | IPV6_NEW_ADDR_AGU)) != 0) && ((ipv6addrp->typeinfo & (IPV6_NEW_ADDR_TEREDO | IPV6_NEW_ADDR_ORCHID)) == 0) ) {
2181 /* prefix included */
2182 DEBUGPRINT_WA(DEBUG_libipv6addr, "Prefix: pref=%08x %08x", ipv6addr_getdword(ipv6addrp, 0), ipv6addr_getdword(ipv6addrp, 1));
2183
2184 if (((ipv6addrp->typeinfo & IPV6_NEW_ADDR_AGU) != 0) && ((ipv6addrp->typeinfo & (IPV6_NEW_ADDR_6TO4)) == 0) \
2185 && ((method == ANON_METHOD_KEEPTYPEASNCC) || (method == ANON_METHOD_KEEPTYPEGEONAMEID))) {
2186 uint32_t GeonameID_type = IPV6CALC_DB_GEO_GEONAMEID_TYPE_UNKNOWN;
2187 uint32_t GeonameID = IPV6CALC_DB_GEO_GEONAMEID_UNKNOWN;
2188
2189 // check whether IPv6 address is anycast
2190 if (((ipv6addrp->typeinfo & IPV6_ADDR_ANYCAST) != 0) && ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0)) {
2191 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 is LISP anycast, skip prefix anonymization");
2192 goto InterfaceIdentifier;
2193 };
2194
2195 // check whether IPv6 address is reserved
2196 r = libipv6calc_db_wrapper_registry_string_by_ipv6addr(ipv6addrp, helpstring, sizeof(helpstring));
2197 if (r == 2) {
2198 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 registry of prefix contains reserved, skip anonymization");
2199 goto InterfaceIdentifier;
2200 };
2201
2202 if (method == ANON_METHOD_KEEPTYPEASNCC) {
2203 if (libipv6calc_db_wrapper_has_features(ANON_METHOD_KEEPTYPEASNCC_IPV6_REQ_DB) == 0) {
2204 DEBUGPRINT_NA(DEBUG_libipv6addr, "anonymization method not supported, db_wrapper reports too less features");
2205 return(1);
2206 };
2207
2208 // switch to prefix anonymization
2209 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6BONE) != 0) {
2210 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 is 6bone unicast, special prefix anonymization");
2211 cc_index = COUNTRYCODE_INDEX_UNKNOWN_REGISTRY_MAP_MIN + IPV6_ADDR_REGISTRY_6BONE;
2212
2213 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
2214 as_num32 = libipv6calc_db_wrapper_as_num32_by_addr(&ipaddr, NULL);
2215 } else if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0) {
2216 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 is LISP unicast, special prefix anonymization");
2217 cc_index = COUNTRYCODE_INDEX_LISP;
2218
2219 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
2220 as_num32 = libipv6calc_db_wrapper_as_num32_by_addr(&ipaddr, NULL);
2221 } else {
2222 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
2223
2224 cc_index = libipv6calc_db_wrapper_cc_index_by_addr(&ipaddr, NULL);
2225 as_num32 = libipv6calc_db_wrapper_as_num32_by_addr(&ipaddr, NULL);
2226
2227 if (cc_index == COUNTRYCODE_INDEX_UNKNOWN) {
2228 // on unknown country, map registry value
2229 cc_index = COUNTRYCODE_INDEX_UNKNOWN_REGISTRY_MAP_MIN + libipv6calc_db_wrapper_registry_num_by_ipv6addr(ipv6addrp);
2230 };
2231 };
2232
2233 DEBUGPRINT_WA(DEBUG_libipv6addr, "cc_index=%d (0x%03x) as_num32=%d (0x%08x)", cc_index, cc_index, as_num32, as_num32);
2234 } else if (method == ANON_METHOD_KEEPTYPEGEONAMEID) {
2235 if (libipv6calc_db_wrapper_has_features(ANON_METHOD_KEEPTYPEGEONAMEID_IPV6_REQ_DB) == 0) {
2236 DEBUGPRINT_NA(DEBUG_libipv6addr, "anonymization method not supported, db_wrapper reports too less features");
2237 return(1);
2238 };
2239
2240 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
2241
2242 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6BONE) != 0) {
2243 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 is 6bone unicast, special prefix anonymization");
2244 GeonameID_type = 0x0;
2245 GeonameID_type |= REGISTRY_6BONE << 4;
2246 } else if (((ipv6addrp->typeinfo & IPV6_ADDR_UNICAST) != 0) && ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0)) {
2247 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 is LISP unicast, special prefix anonymization");
2248 GeonameID_type = 0x7;
2249 GeonameID = 0x11800;
2250 GeonameID_type |= (libipv6calc_db_wrapper_registry_num_by_ipv6addr(ipv6addrp) & 0x7) << 4;
2251 GeonameID |= 0x000; // TODO: map LISP information into 11 LSB
2252 } else {
2253 // get GeonameID
2254 GeonameID = libipv6calc_db_wrapper_GeonameID_by_addr(&ipaddr, NULL, &GeonameID_type);
2255
2256 // get registry
2257 int registry = libipv6addr_registry_num_by_addr(ipv6addrp);
2258
2259 DEBUGPRINT_WA(DEBUG_libipv6addr, "result of GeonameID retrievement: %d (0x%08x) (source: %d) (registry: %d)", GeonameID, GeonameID, GeonameID_type, registry);
2260
2261 if (registry > 0) {
2262 // store registry
2263 GeonameID_type |= registry << 4;
2264 };
2265 };
2266 };
2267
2268 ipv6_prefix[0] = 0; ipv6_prefix[1] = 0;
2269
2270 // store prefix
2271 ipv6_prefix[ANON_PREFIX_TOKEN_DWORD] |= PACK_XMS(ANON_PREFIX_TOKEN_VALUE, ANON_PREFIX_TOKEN_XOR, ANON_PREFIX_TOKEN_MASK, ANON_PREFIX_TOKEN_SHIFT);
2272
2273 if (method == ANON_METHOD_KEEPTYPEASNCC) {
2274 flags = 0x0;
2275
2276 // store cc_index
2277 ipv6_prefix[ANON_PREFIX_CCINDEX_DWORD] |= PACK_XMS(cc_index, ANON_PREFIX_CCINDEX_XOR, ANON_PREFIX_CCINDEX_MASK, ANON_PREFIX_CCINDEX_SHIFT);
2278
2279 // store as_num32
2280 ipv6_prefix[ANON_PREFIX_ASN32_MSB_DWORD] |= PACK_XMS(as_num32 >> ANON_PREFIX_ASN32_LSB_AMOUNT, ANON_PREFIX_ASN32_MSB_XOR, ANON_PREFIX_ASN32_MSB_MASK, ANON_PREFIX_ASN32_MSB_SHIFT);
2281 ipv6_prefix[ANON_PREFIX_ASN32_LSB_DWORD] |= PACK_XMS(as_num32 & ANON_PREFIX_ASN32_LSB_MASK, ANON_PREFIX_ASN32_LSB_XOR, ANON_PREFIX_ASN32_LSB_MASK, ANON_PREFIX_ASN32_LSB_SHIFT);
2282
2283 } else if (method == ANON_METHOD_KEEPTYPEGEONAMEID) {
2284 flags = 0x1;
2285
2286 // store type
2287 ipv6_prefix[ANON_PREFIX_GEONAMEID_TYPE_DWORD] |= PACK_XMS(GeonameID_type, ANON_PREFIX_GEONAMEID_TYPE_XOR, ANON_PREFIX_GEONAMEID_TYPE_MASK, ANON_PREFIX_GEONAMEID_TYPE_SHIFT);
2288
2289 // store GeonameID
2290 ipv6_prefix[ANON_PREFIX_GEONAMEID_MSB_DWORD] |= PACK_XMS(GeonameID >> ANON_PREFIX_GEONAMEID_LSB_AMOUNT, ANON_PREFIX_GEONAMEID_MSB_XOR, ANON_PREFIX_GEONAMEID_MSB_MASK, ANON_PREFIX_GEONAMEID_MSB_SHIFT);
2291 ipv6_prefix[ANON_PREFIX_GEONAMEID_LSB_DWORD] |= PACK_XMS(GeonameID & ANON_PREFIX_GEONAMEID_LSB_MASK, ANON_PREFIX_GEONAMEID_LSB_XOR, ANON_PREFIX_GEONAMEID_LSB_MASK, ANON_PREFIX_GEONAMEID_LSB_SHIFT);
2292 };
2293
2294 // store flags
2295 ipv6_prefix[ANON_PREFIX_FLAGS_DWORD] |= PACK_XMS(flags, ANON_PREFIX_FLAGS_XOR, ANON_PREFIX_FLAGS_MASK, ANON_PREFIX_FLAGS_SHIFT);
2296
2297 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonmized prefix for method=%d: %08x%08x", method, ipv6_prefix[0], ipv6_prefix[1]);
2298
2299 anonymized_prefix_nibbles = 0;
2300
2301 ipv6addr_setdword(ipv6addrp, 0, ipv6_prefix[0]);
2302 ipv6addr_setdword(ipv6addrp, 1, ipv6_prefix[1]);
2303 calculate_checksum_prefix = 1;
2304
2305 } else if (mask_ipv6 == 64) {
2306 /* nothing to do */
2307 } else if (mask_ipv6 < 16 || mask_ipv6 > 64) {
2308 /* should not happen here */
2309 fprintf(stderr, "%s/%s: 'mask_ipv6' has an unexpected illegal value: %d\n", __FILE__, __func__, mask_ipv6);
2310 exit(EXIT_FAILURE);
2311 } else {
2312 if (((ipv6addrp->typeinfo & IPV6_ADDR_ANYCAST) != 0) && ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0)) {
2313 if (mask_ipv6 < 48) {
2314 mask_ipv6 = 48; // keeping address type
2315 };
2316 DEBUGPRINT_WA(DEBUG_libipv6addr, "Mask adjusted to: %d", mask_ipv6);
2317 };
2318
2319 DEBUGPRINT_WA(DEBUG_libipv6addr, "Mask prefix with mask: %d", mask_ipv6);
2320
2321 if (mask_ipv6 < 64 && mask_ipv6 > 32) {
2322 if (zeroize_prefix != 0) {
2323 ipv6addr_setdword(ipv6addrp, 1, ipv6addr_getdword(ipv6addrp, 1) & (0xffffffffu << ((unsigned int) 64 - mask_ipv6)));
2324 } else {
2325 ipv6addr_setdword(ipv6addrp, 1, (ipv6addr_getdword(ipv6addrp, 1) & (0xffffffffu << ((unsigned int) 64 - mask_ipv6))) | ((ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16)) & ((0xffffffffu >> ((unsigned int) mask_ipv6 - 32)))));
2326 anonymized_prefix_nibbles = (64 - mask_ipv6) / 4;
2327 };
2328 } else if (mask_ipv6 == 32) {
2329 if (zeroize_prefix != 0) {
2330 ipv6addr_setdword(ipv6addrp, 1, 0u);
2331 } else {
2332 ipv6addr_setdword(ipv6addrp, 1, ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16));
2333 anonymized_prefix_nibbles = 8;
2334 };
2335 } else if (mask_ipv6 < 32 && mask_ipv6 >= 16) {
2336 if (zeroize_prefix != 0) {
2337 ipv6addr_setdword(ipv6addrp, 1, 0u);
2338 ipv6addr_setdword(ipv6addrp, 0, ipv6addr_getdword(ipv6addrp, 0) & (0xffffffffu << ((unsigned int) 32 - mask_ipv6)));
2339 } else {
2340 ipv6addr_setdword(ipv6addrp, 1, ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16));
2341 ipv6addr_setdword(ipv6addrp, 0, (ipv6addr_getdword(ipv6addrp, 0) & (0xffffffffu << ((unsigned int) 32 - mask_ipv6))) | ((ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16)) & ((0xffffffffu >> ((unsigned int) mask_ipv6)))));
2342 anonymized_prefix_nibbles = (64 - mask_ipv6) / 4;
2343 };
2344 };
2345 };
2346
2347 /* restore prefix in special cases */
2348 if ( ((ipv6addrp->typeinfo & IPV6_ADDR_SITELOCAL) != 0) && (mask_ipv6 < 10) ) {
2349 ipv6addr_setword(ipv6addrp, 0, ipv6addr_getword(ipv6addrp, 1) | 0xfec0u);
2350 } else if ( ((ipv6addrp->typeinfo & IPV6_ADDR_ULUA) != 0) && (mask_ipv6 < 7) ) {
2351 ipv6addr_setoctet(ipv6addrp, 0, ipv6addr_getoctet(ipv6addrp, 0) | 0xfdu);
2352 };
2353
2354 DEBUGPRINT_WA(DEBUG_libipv6addr, "Prefix: pref=%08x %08x (anonymized)", ipv6addr_getdword(ipv6addrp, 0), ipv6addr_getdword(ipv6addrp, 1));
2355 };
2356
2357 InterfaceIdentifier:
2358 /* interface identifier handling */
2359 if ( ( ((ipv6addrp->typeinfo & (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_SITELOCAL | IPV6_NEW_ADDR_AGU | IPV6_ADDR_ULUA )) != 0) || ((ipv6addrp->typeinfo & (IPV6_ADDR_LOOPBACK | IPV6_NEW_ADDR_SOLICITED_NODE)) == (IPV6_ADDR_LOOPBACK | IPV6_NEW_ADDR_SOLICITED_NODE)) ) && ((ipv6addrp->typeinfo & (IPV6_NEW_ADDR_TEREDO | IPV6_NEW_ADDR_ORCHID)) == 0) ) {
2360 /* Interface identifier included */
2361 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_EUI48) != 0) {
2362 /* EUI-48 */
2363
2364 DEBUGPRINT_NA(DEBUG_libipv6addr, "EUI-48 identifier found");
2365
2366 if (method == ANON_METHOD_ZEROIZE) {
2367 zeroize_iid = 1;
2368 } else {
2369 /* set anon interface ID, include shifted OUI bytes */
2370 DEBUGPRINT_WA(DEBUG_libipv6addr, "Anonymize IPv6 address: OUI=%02x:%02x:%02x", ipv6addr_getoctet(ipv6addrp, 8) & 0xfc, ipv6addr_getoctet(ipv6addrp, 9), ipv6addr_getoctet(ipv6addrp, 10));
2371
2372 mac_clearall(&macaddr);
2373 macaddr.addr[0] = ipv6addr_getoctet(ipv6addrp, 8) ^ 0x2;
2374 macaddr.addr[1] = ipv6addr_getoctet(ipv6addrp, 9);
2375 macaddr.addr[2] = ipv6addr_getoctet(ipv6addrp, 10);
2376 macaddr.addr[3] = ipv6addr_getoctet(ipv6addrp, 13);
2377 macaddr.addr[4] = ipv6addr_getoctet(ipv6addrp, 14);
2378 macaddr.addr[5] = ipv6addr_getoctet(ipv6addrp, 15);
2379 macaddr.flag_valid = 1;
2380
2381 map_value = libieee_map_oui_macaddr(&macaddr) ^ 0x00020000;
2382
2383 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_EUI48_VALUE_00_31;
2384 iid[1] = ANON_IID_EUI48_VALUE_32_63 | ((map_value & 0x1ffffff) << ANON_IID_EUI48_PAYLOAD_SHIFT);
2385
2386 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2387 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2388 calculate_checksum = 1;
2389 };
2390 } else {
2391 if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_RANDOM) != 0 ) {
2392 if (method == ANON_METHOD_ZEROIZE) {
2393 /* mask ID according to mask_eui64 */
2394 zeroize_iid = 1;
2395 } else {
2396 /* replace IID with special value */
2397 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_RANDOM_VALUE_00_31;
2398 iid[1] = ANON_IID_RANDOM_VALUE_32_63;
2399
2400 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2401 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2402 calculate_checksum = 1;
2403 };
2404 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_EUI64) == IPV6_NEW_ADDR_IID_EUI64) {
2405 /* Check for global EUI-64 */
2406 if (method == ANON_METHOD_ZEROIZE) {
2407 /* mask ID according to mask_eui64 */
2408 zeroize_iid = 1;
2409 } else {
2410 libeui64_clearall(&eui64addr);
2411 eui64addr.addr[0] = ipv6addr_getoctet(ipv6addrp, 8) ^ 0x2;
2412 eui64addr.addr[1] = ipv6addr_getoctet(ipv6addrp, 9);
2413 eui64addr.addr[2] = ipv6addr_getoctet(ipv6addrp, 10);
2414 eui64addr.addr[3] = ipv6addr_getoctet(ipv6addrp, 11);
2415 eui64addr.addr[4] = ipv6addr_getoctet(ipv6addrp, 12);
2416 eui64addr.addr[5] = ipv6addr_getoctet(ipv6addrp, 13);
2417 eui64addr.addr[6] = ipv6addr_getoctet(ipv6addrp, 14);
2418 eui64addr.addr[7] = ipv6addr_getoctet(ipv6addrp, 15);
2419 eui64addr.flag_valid = 1;
2420
2421 map_value = libieee_map_oui_eui64addr(&eui64addr) ^ 0x00020000;
2422
2423 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_EUI64_VALUE_00_31;
2424 iid[1] = ANON_IID_EUI64_VALUE_32_63 | ((map_value & 0x1ffffff) << ANON_IID_EUI64_PAYLOAD_SHIFT);
2425
2426 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2427 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2428 calculate_checksum = 1;
2429 };
2430 } else {
2431 if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_SOLICITED_NODE) != 0 ) {
2432 /* zero'ise unique ID */
2433 ipv6addr_setoctet(ipv6addrp, 13, 0x0u);
2434 ipv6addr_setoctet(ipv6addrp, 14, 0x0u);
2435 ipv6addr_setoctet(ipv6addrp, 15, 0x0u);
2436 } else if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_ISATAP) != 0 ) {
2437 /* ISATAP address */
2438 if ( (ipv6addrp->typeinfo & IPV6_ADDR_IID_32_63_HAS_IPV4) != 0 ) {
2439 /* IPv4 address included */
2440
2441 for (i = 0; i <= 3; i++) {
2442 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) (i + 12)));
2443 };
2444 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2445
2446 DEBUGPRINT_WA(DEBUG_libipv6addr, "ISATAP includes IPv4 address: IPv4=%d.%d.%d.%d, anonymized: %d.%d.%d.%d", ipv6addr_getoctet(ipv6addrp, 12), ipv6addr_getoctet(ipv6addrp, 13), ipv6addr_getoctet(ipv6addrp, 14), ipv6addr_getoctet(ipv6addrp, 15), ipv4addr_getoctet(&ipv4addr, 0), ipv4addr_getoctet(&ipv4addr, 1), ipv4addr_getoctet(&ipv4addr, 2), ipv4addr_getoctet(&ipv4addr, 3));
2447
2448 /* store back */
2449 for (i = 0; i <= 3; i++) {
2450 ipv6addr_setoctet(ipv6addrp, (unsigned int) 12 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i));
2451 };
2452
2453 if (method == ANON_METHOD_ZEROIZE) {
2454 // nothing to do, IPv4 address already anonymized
2455 } else {
2456 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_ISATAP_VALUE_00_31;
2457 iid[1] = (ipv6addr_getoctet(ipv6addrp, 12) << (ANON_IID_ISATAP_PAYLOAD_SHIFT + 16)) | (ipv6addr_getoctet(ipv6addrp, 13) << (ANON_IID_ISATAP_PAYLOAD_SHIFT + 8)) | (ipv6addr_getoctet(ipv6addrp, 14) << (ANON_IID_ISATAP_PAYLOAD_SHIFT));
2458 iid[1] |= ANON_IID_ISATAP_TYPE_IPV4_VALUE_32_63;
2459 calculate_checksum = 1;
2460 };
2461 } else if ((ipv6addr_getoctet(ipv6addrp, 11) == 0xff) && (ipv6addr_getoctet(ipv6addrp, 12) == 0xfe)) {
2462 /* vendor ID included */
2463 if (method == ANON_METHOD_ZEROIZE) {
2464 /* zero'ise unique ID */
2465 /* TODO: honor mask_eui64 */
2466 ipv6addr_setoctet(ipv6addrp, 13, 0x0u);
2467 ipv6addr_setoctet(ipv6addrp, 14, 0x0u);
2468 ipv6addr_setoctet(ipv6addrp, 15, 0x0u);
2469 } else {
2470 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_ISATAP_VALUE_00_31;
2471 iid[1] = (ipv6addr_getoctet(ipv6addrp, 13) << (ANON_IID_ISATAP_PAYLOAD_SHIFT + 16));
2472 iid[1] |= ANON_IID_ISATAP_TYPE_VENDOR_VALUE_32_63;
2473 calculate_checksum = 1;
2474 };
2475 } else {
2476 /* extension ID included */
2477 if (method == ANON_METHOD_ZEROIZE) {
2478 /* mask ID according to mask_eui64 */
2479 zeroize_iid = 1;
2480 } else {
2481 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_ISATAP_VALUE_00_31;
2482 iid[1] = (ipv6addr_getoctet(ipv6addrp, 11) << (ANON_IID_ISATAP_PAYLOAD_SHIFT + 16)) | (ipv6addr_getoctet(ipv6addrp, 12) << (ANON_IID_ISATAP_PAYLOAD_SHIFT + 8)) | (ipv6addr_getoctet(ipv6addrp, 13) << (ANON_IID_ISATAP_PAYLOAD_SHIFT));
2483 iid[1] |= ANON_IID_ISATAP_TYPE_EXTID_VALUE_32_63;
2484 calculate_checksum = 1;
2485 };
2486 };
2487
2488 if (calculate_checksum == 1) {
2489 /* store local/global bit */
2490 DEBUGPRINT_NA(DEBUG_libipv6addr, "ISATAP: store local/global bit");
2491 if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_GLOBAL) != 0 ) {
2492 DEBUGPRINT_NA(DEBUG_libipv6addr, "ISATAP: store global bit");
2493 iid[1] |= ANON_IID_ISATAP_SCOPE_GLOBAL;
2494 } else if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_IID_LOCAL) != 0 ) {
2495 DEBUGPRINT_NA(DEBUG_libipv6addr, "ISATAP: store local bit");
2496 iid[1] |= ANON_IID_ISATAP_SCOPE_LOCAL;
2497 };
2498 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2499 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2500 };
2501
2502 } else if ( ( ( (ipv6addrp->typeinfo & IPV6_ADDR_LINKLOCAL) != 0) && (ipv6addr_getdword(ipv6addrp, 2) == 0 && ipv6addr_getword(ipv6addrp, 6) != 0)) ) {
2503 /* fe80:: must have 0000:0000:xxxx:yyyy where xxxx > 0 */
2504 for (i = 0; i <= 3; i++) {
2505 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) (i + 12)));
2506 };
2507
2508 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2509
2510 /* store back */
2511 for (i = 0; i <= 3; i++) {
2512 ipv6addr_setoctet(ipv6addrp, (unsigned int) 12 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i));
2513 };
2514 } else {
2515 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6TO4_MICROSOFT) != 0) {
2516 /* extract IPv4 address */
2517 for (i = 0; i <= 3; i++) {
2518 ipv4addr_setoctet(&ipv4addr, (unsigned int) i, (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) (i + 12)));
2519 };
2520
2521 libipv4addr_anonymize(&ipv4addr, mask_ipv4, method);
2522
2523 if (method == ANON_METHOD_ZEROIZE) {
2524 /* store back */
2525 for (i = 0; i <= 3; i++) {
2526 ipv6addr_setoctet(ipv6addrp, (unsigned int) 12 + i, (unsigned int) ipv4addr_getoctet(&ipv4addr, (unsigned int) i));
2527 };
2528 } else {
2529 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_IPV4_VALUE_00_31;
2530 iid[1] = ANON_IID_IPV4_VALUE_32_63 | (ipv4addr_getoctet(&ipv4addr, 0) << (ANON_IID_IPV4_PAYLOAD_SHIFT + 16)) | (ipv4addr_getoctet(&ipv4addr, 1) << (ANON_IID_IPV4_PAYLOAD_SHIFT + 8)) | (ipv4addr_getoctet(&ipv4addr, 2) << (ANON_IID_IPV4_PAYLOAD_SHIFT));
2531
2532 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2533 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2534 calculate_checksum = 1;
2535 };
2536 } else {
2537 /* Identifier has local scope */
2538 if (method == ANON_METHOD_ZEROIZE) {
2539 /* mask ID according to mask_eui64 */
2540 zeroize_iid = 1;
2541 } else {
2542 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_IID_STATIC_VALUE_00_31;
2543 iid[1] = ANON_IID_STATIC_VALUE_32_63;
2544
2545 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2546 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2547 calculate_checksum = 1;
2548 };
2549 };
2550 };
2551 };
2552 };
2553 };
2554
2555 /* ORCHID hash */
2556 if ( (ipv6addrp->typeinfo & IPV6_NEW_ADDR_ORCHID) != 0 ) {
2557 DEBUGPRINT_NA(DEBUG_libipv6addr, "ORCHID address found");
2558
2559 if (method == ANON_METHOD_ZEROIZE) {
2560 /* mask 100 LSBs */
2561 ipv6addr_setword(ipv6addrp, 7, 0x0u);
2562 ipv6addr_setword(ipv6addrp, 6, 0x0u);
2563 ipv6addr_setword(ipv6addrp, 5, 0x0u);
2564 ipv6addr_setword(ipv6addrp, 4, 0x0u);
2565 } else {
2566 iid[0] = ANON_TOKEN_VALUE_00_31 | ANON_ORCHID_VALUE_00_31;
2567 iid[1] = ANON_ORCHID_VALUE_32_63;
2568 ipv6addr_setdword(ipv6addrp, 2, iid[0]);
2569 ipv6addr_setdword(ipv6addrp, 3, iid[1]);
2570 calculate_checksum = 1;
2571 };
2572
2573 if (zeroize_prefix != 0) {
2574 ipv6addr_setword(ipv6addrp, 3, 0x0u);
2575 ipv6addr_setword(ipv6addrp, 2, 0x0u);
2576 ipv6addr_setword(ipv6addrp, 1, ipv6addr_getword(ipv6addrp, 1) & 0xFFF0);
2577 } else {
2578 ipv6addr_setdword(ipv6addrp, 1, (ANON_TOKEN_VALUE_00_31 | (ANON_TOKEN_VALUE_00_31 >> 16)));
2579 ipv6addr_setword(ipv6addrp, 1, (ipv6addr_getword(ipv6addrp, 1) & 0xFFF0) | ((ANON_TOKEN_VALUE_00_31 >> 16) & 0xF));
2580 anonymized_prefix_nibbles = (64 - 28) / 4;
2581 };
2582 };
2583
2584 /* switch prefix anonymization if IID is not anonymizied in reliable way */
2585 if (calculate_checksum == 0) {
2586 zeroize_prefix = 1;
2587 } else {
2588 ipv6addrp->typeinfo |= IPV6_ADDR_ANONYMIZED_IID;
2589 };
2590
2591 if (zeroize_iid == 1) {
2592 DEBUGPRINT_WA(DEBUG_libipv6addr, "Zeroize IID with mask: %d", mask_eui64);
2593
2594 libeui64_clearall(&eui64addr);
2595
2596 eui64addr.addr[0] = ipv6addr_getoctet(ipv6addrp, 8) ^ 0x2;
2597 eui64addr.addr[1] = ipv6addr_getoctet(ipv6addrp, 9);
2598 eui64addr.addr[2] = ipv6addr_getoctet(ipv6addrp, 10);
2599 eui64addr.addr[3] = ipv6addr_getoctet(ipv6addrp, 11);
2600 eui64addr.addr[4] = ipv6addr_getoctet(ipv6addrp, 12);
2601 eui64addr.addr[5] = ipv6addr_getoctet(ipv6addrp, 13);
2602 eui64addr.addr[6] = ipv6addr_getoctet(ipv6addrp, 14);
2603 eui64addr.addr[7] = ipv6addr_getoctet(ipv6addrp, 15);
2604 eui64addr.flag_valid = 1;
2605
2606 bit_ul = eui64addr.addr[0] & 0x02;
2607
2608 libeui64_anonymize(&eui64addr, ipv6calc_anon_set); // covers also EUI-48
2609
2610 if ((mask_eui64 < 7) && (ipv6calc_anon_set->mask_autoadjust == 0) && (bit_ul == 0x0)) {
2611 DEBUGPRINT_WA(DEBUG_libipv6addr, "mask_eui64 < 7 AND EUI-64 was %s AND mask_autoadjust not set, do not invert universal/local bit for IID (for backwards compatibility reason", (bit_ul == 2) ? "local" : "universal");
2612
2613 eui64addr.addr[0] |= 0x02; // will be inverted and therefore cleared next
2614 };
2615
2616 ipv6addr_setoctet(ipv6addrp, 8, eui64addr.addr[0] ^ 0x2);
2617 ipv6addr_setoctet(ipv6addrp, 9, eui64addr.addr[1]);
2618 ipv6addr_setoctet(ipv6addrp, 10, eui64addr.addr[2]);
2619 ipv6addr_setoctet(ipv6addrp, 11, eui64addr.addr[3]);
2620 ipv6addr_setoctet(ipv6addrp, 12, eui64addr.addr[4]);
2621 ipv6addr_setoctet(ipv6addrp, 13, eui64addr.addr[5]);
2622 ipv6addr_setoctet(ipv6addrp, 14, eui64addr.addr[6]);
2623 ipv6addr_setoctet(ipv6addrp, 15, eui64addr.addr[7]);
2624 };
2625
2626 // checksumming
2627 if (calculate_checksum == 1) {
2628 if (anonymized_prefix_nibbles > 0) {
2629 /* fill amount of nibbles into IID lead token */
2630 DEBUGPRINT_WA(DEBUG_libipv6addr, "Store amount of anonymized nibbles to IID lead token: %d", anonymized_prefix_nibbles);
2631
2632 ipv6addr_setoctet(ipv6addrp, 9, ipv6addr_getoctet(ipv6addrp, 9) | (anonymized_prefix_nibbles << 4));
2633 };
2634
2635 ipv6addr_set_checksum_anonymized_iid(ipv6addrp);
2636 };
2637
2638 if (calculate_checksum_prefix == 1) {
2639 ipv6addr_set_checksum_anonymized_prefix(ipv6addrp);
2640 ipv6addrp->typeinfo |= IPV6_ADDR_ANONYMIZED_PREFIX;
2641 };
2642
2643 DEBUGPRINT_WA(DEBUG_libipv6addr, "Result: addr=%08x %08x %08x %08x (anonymized)", ipv6addr_getdword(ipv6addrp, 0), ipv6addr_getdword(ipv6addrp, 1), ipv6addr_getdword(ipv6addrp, 2), ipv6addr_getdword(ipv6addrp, 3));
2644
2645 return(0);
2646 };
2647
2648
2649 /*
2650 * clear filter IPv6 address
2651 *
2652 * in : *filter = filter structure
2653 */
ipv6addr_filter_clear(s_ipv6calc_filter_ipv6addr * filter)2654 void ipv6addr_filter_clear(s_ipv6calc_filter_ipv6addr *filter) {
2655 filter->active = 0;
2656
2657 filter->filter_typeinfo.active = 0;
2658 filter->filter_typeinfo.typeinfo_must_have = 0;
2659 filter->filter_typeinfo.typeinfo_may_not_have = 0;
2660 filter->filter_typeinfo2.typeinfo_must_have = 0;
2661 filter->filter_typeinfo2.typeinfo_may_not_have = 0;
2662
2663 libipv6calc_filter_clear_db_cc(&filter->filter_db_cc);
2664 libipv6calc_filter_clear_db_asn(&filter->filter_db_asn);
2665 libipv6calc_filter_clear_db_registry(&filter->filter_db_registry);
2666
2667 filter->filter_addr.active = 0;
2668 filter->filter_addr.addr_must_have_max = 0;
2669 filter->filter_addr.addr_may_not_have_max = 0;
2670
2671 return;
2672 };
2673
2674
2675 /*
2676 * parse filter IPv6
2677 *
2678 * in : *filter = filter structure
2679 * ret: 0:found 1:skip 2:problem
2680 */
ipv6addr_filter_parse(s_ipv6calc_filter_ipv6addr * filter,const char * token)2681 int ipv6addr_filter_parse(s_ipv6calc_filter_ipv6addr *filter, const char *token) {
2682 int i, result = 1, negate = 0, offset = 0, r;
2683 const char *prefix = "ipv6";
2684 const char *prefixdot = "ipv6.";
2685 const char *prefixdbdot = "db.";
2686 const char *prefixaddreq = "addr=";
2687 const char *prefixaddreq_le = "addr<=";
2688 const char *prefixaddreq_lt = "addr<";
2689 const char *prefixaddreq_ge = "addr>=";
2690 const char *prefixaddreq_gt = "addr>";
2691 const char *prefixaddreq_le2 = "addr=le=";
2692 const char *prefixaddreq_lt2 = "addr=lt=";
2693 const char *prefixaddreq_ge2 = "addr=ge=";
2694 const char *prefixaddreq_gt2 = "addr=gt=";
2695 ipv6calc_ipv6addr ipv6addr;
2696 char resultstring[IPV6CALC_STRING_MAX];
2697 int db = 0;
2698 int addr_test_method = IPV6CALC_TEST_NONE;
2699
2700 if (token == NULL) {
2701 return (result);
2702 };
2703
2704 DEBUGPRINT_WA(DEBUG_libipv6addr, "input: %s", token);
2705
2706 if (token[0] == '^') {
2707 DEBUGPRINT_WA(DEBUG_libipv6addr, "found negate prefix in token: %s", token);
2708
2709 negate = 1;
2710 offset += 1;
2711 };
2712
2713 // typeinfo
2714 if (strcmp(token + offset, prefix) == 0) {
2715 /* any */
2716 if (negate == 1) {
2717 filter->filter_typeinfo.typeinfo_may_not_have = ~IPV6_ADDR_ANY;
2718 } else {
2719 filter->filter_typeinfo.typeinfo_must_have = IPV6_ADDR_ANY;
2720 };
2721 filter->filter_typeinfo.active = 1;
2722 filter->active = 1;
2723 result = 0;
2724 goto END_ipv6addr_filter_parse;
2725
2726 } else if (strncmp(token + offset, prefixdot, strlen(prefixdot)) == 0) {
2727 /* prefix with dot found */
2728 offset += strlen(prefixdot);
2729 result = 2; /* token with prefix, result into problem if not found */
2730
2731 DEBUGPRINT_WA(DEBUG_libipv6addr, "token with prefix, suffix: %s", token + offset);
2732 };
2733
2734 if (strncmp(token + offset, prefixaddreq_le, strlen(prefixaddreq_le)) == 0) {
2735 /* prefixaddr with = found */
2736 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr<=' prefix in token: %s", token);
2737 offset += strlen(prefixaddreq_le);
2738 addr_test_method = IPV6CALC_TEST_LE;
2739
2740 } else if (strncmp(token + offset, prefixaddreq_lt, strlen(prefixaddreq_lt)) == 0) {
2741 /* prefixaddr with = found */
2742 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr<' prefix in token: %s", token);
2743 offset += strlen(prefixaddreq_lt);
2744 addr_test_method = IPV6CALC_TEST_LT;
2745
2746 } else if (strncmp(token + offset, prefixaddreq_ge, strlen(prefixaddreq_ge)) == 0) {
2747 /* prefixaddr with = found */
2748 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr>=' prefix in token: %s", token);
2749 offset += strlen(prefixaddreq_ge);
2750 addr_test_method = IPV6CALC_TEST_GE;
2751
2752 } else if (strncmp(token + offset, prefixaddreq_gt, strlen(prefixaddreq_gt)) == 0) {
2753 /* prefixaddr with = found */
2754 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr>' prefix in token: %s", token);
2755 offset += strlen(prefixaddreq_gt);
2756 addr_test_method = IPV6CALC_TEST_GT;
2757
2758 } else if (strncmp(token + offset, prefixaddreq_le2, strlen(prefixaddreq_le2)) == 0) {
2759 /* prefixaddr with = found */
2760 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr=le=' prefix in token: %s", token);
2761 offset += strlen(prefixaddreq_le2);
2762 addr_test_method = IPV6CALC_TEST_LE;
2763
2764 } else if (strncmp(token + offset, prefixaddreq_lt2, strlen(prefixaddreq_lt2)) == 0) {
2765 /* prefixaddr with = found */
2766 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr=lt=' prefix in token: %s", token);
2767 offset += strlen(prefixaddreq_lt2);
2768 addr_test_method = IPV6CALC_TEST_LT;
2769
2770 } else if (strncmp(token + offset, prefixaddreq_ge2, strlen(prefixaddreq_ge2)) == 0) {
2771 /* prefixaddr with = found */
2772 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr=ge=' prefix in token: %s", token);
2773 offset += strlen(prefixaddreq_ge2);
2774 addr_test_method = IPV6CALC_TEST_GE;
2775
2776 } else if (strncmp(token + offset, prefixaddreq_gt2, strlen(prefixaddreq_gt2)) == 0) {
2777 /* prefixaddr with = found */
2778 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr=gt=' prefix in token: %s", token);
2779 offset += strlen(prefixaddreq_gt2);
2780 addr_test_method = IPV6CALC_TEST_GT;
2781
2782 } else if (strncmp(token + offset, prefixaddreq, strlen(prefixaddreq)) == 0) {
2783 /* prefixaddr with = found */
2784 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'addr=' prefix in token: %s", token);
2785 offset += strlen(prefixaddreq);
2786 addr_test_method = IPV6CALC_TEST_PREFIX;
2787
2788
2789 } else if (strncmp(token + offset, prefixdbdot, strlen(prefixdbdot)) == 0) {
2790 /* prefixdb with dot found */
2791 DEBUGPRINT_WA(DEBUG_libipv6addr, "found 'db.' prefix in token: %s", token);
2792 db = 1;
2793
2794 } else if (strstr(token, ".") != NULL) {
2795 /* other prefix */
2796 DEBUGPRINT_WA(DEBUG_libipv6addr, "prefix did not match: %s", token + offset);
2797 return(1);
2798 };
2799
2800
2801 if ((db == 0) && (addr_test_method == IPV6CALC_TEST_NONE)) {
2802 // typeinfo token
2803 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_ipv6addrtypestrings); i++ ) {
2804 DEBUGPRINT_WA(DEBUG_libipv6addr, "check token against: %s", ipv6calc_ipv6addrtypestrings[i].token);
2805
2806 if (strcmp(ipv6calc_ipv6addrtypestrings[i].token, token + offset) == 0) {
2807 DEBUGPRINT_WA(DEBUG_libipv6addr, "token match: %s", ipv6calc_ipv6addrtypestrings[i].token);
2808
2809 if (negate == 1) {
2810 filter->filter_typeinfo.typeinfo_may_not_have |= ipv6calc_ipv6addrtypestrings[i].number;
2811 } else {
2812 filter->filter_typeinfo.typeinfo_must_have |= ipv6calc_ipv6addrtypestrings[i].number;
2813 };
2814 filter->filter_typeinfo.active = 1;
2815 filter->active = 1;
2816 result = 0;
2817 break;
2818 };
2819 };
2820
2821 // typeinfo2 token
2822 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_ipv6addr_type2_strings); i++ ) {
2823 DEBUGPRINT_WA(DEBUG_libipv6addr, "check token against: %s", ipv6calc_ipv6addr_type2_strings[i].token);
2824
2825 if (strcmp(ipv6calc_ipv6addr_type2_strings[i].token, token + offset) == 0) {
2826 DEBUGPRINT_WA(DEBUG_libipv6addr, "token match: %s", ipv6calc_ipv6addr_type2_strings[i].token);
2827
2828 if (negate == 1) {
2829 filter->filter_typeinfo2.typeinfo_may_not_have |= ipv6calc_ipv6addr_type2_strings[i].number;
2830 } else {
2831 filter->filter_typeinfo2.typeinfo_must_have |= ipv6calc_ipv6addr_type2_strings[i].number;
2832 };
2833 filter->filter_typeinfo2.active = 1;
2834 filter->active = 1;
2835 result = 0;
2836 break;
2837 };
2838 };
2839 };
2840
2841 if (db == 1) {
2842 // DB CC filter
2843 r = libipv6calc_db_cc_filter_parse(&filter->filter_db_cc, token + offset, negate);
2844 if (r == 0) {
2845 result = 0;
2846 filter->active = 1;
2847 };
2848
2849 // DB ASN filter
2850 r = libipv6calc_db_asn_filter_parse(&filter->filter_db_asn, token + offset, negate);
2851 if (r == 0) {
2852 result = 0;
2853 filter->active = 1;
2854 };
2855
2856 // DB registry filter
2857 r = libipv6calc_db_registry_filter_parse(&filter->filter_db_registry, token + offset, negate);
2858 if (r == 0) {
2859 result = 0;
2860 filter->active = 1;
2861 };
2862 };
2863
2864
2865 if (addr_test_method != IPV6CALC_TEST_NONE) {
2866 DEBUGPRINT_WA(DEBUG_libipv6addr, "try to parse IPv6 address: %s", token + offset);
2867 r = addr_to_ipv6addrstruct(token + offset, resultstring, sizeof(resultstring), &ipv6addr);
2868
2869 if (r == 0) {
2870 DEBUGPRINT_WA(DEBUG_libipv6addr, "successfully parsed IPv6 address: %s", token + offset);
2871
2872 // store address test method in 'flag_startend_use'
2873 ipv6addr.test_mode = addr_test_method;
2874
2875 if (negate == 1) {
2876 if (filter->filter_addr.addr_may_not_have_max < IPV6CALC_FILTER_IPV6ADDR) {
2877 ipv6addr_copy(&filter->filter_addr.ipv6addr_may_not_have[filter->filter_addr.addr_may_not_have_max], &ipv6addr);
2878 filter->filter_addr.addr_may_not_have_max++;
2879 filter->filter_addr.active = 1;
2880 filter->active = 1;
2881 result = 0;
2882 } else {
2883 ERRORPRINT_WA("filter token 'addr=' maxmimum reached for 'may not have': %d", filter->filter_addr.addr_may_not_have_max);
2884 };
2885 } else {
2886 if (filter->filter_addr.addr_must_have_max < IPV6CALC_FILTER_IPV6ADDR) {
2887 ipv6addr_copy(&filter->filter_addr.ipv6addr_must_have[filter->filter_addr.addr_must_have_max], &ipv6addr);
2888 filter->filter_addr.addr_must_have_max++;
2889 filter->filter_addr.active = 1;
2890 filter->active = 1;
2891 result = 0;
2892 } else {
2893 ERRORPRINT_WA("filter token 'addr=' maxmimum reached for 'must have': %d", filter->filter_addr.addr_must_have_max);
2894 };
2895 };
2896 };
2897 };
2898
2899 if (result != 0) {
2900 DEBUGPRINT_WA(DEBUG_libipv6addr, "token not supported: %s", token);
2901 return (result);
2902 };
2903
2904 END_ipv6addr_filter_parse:
2905 return (result);
2906 };
2907
2908
2909 /*
2910 * check filter IPv6
2911 *
2912 * in : *filter = filter structure
2913 * ret: 0:ok 1:problem
2914 */
ipv6addr_filter_check(const s_ipv6calc_filter_ipv6addr * filter)2915 int ipv6addr_filter_check(const s_ipv6calc_filter_ipv6addr *filter) {
2916 int result = 0, r, i;
2917 char resultstring[IPV6CALC_STRING_MAX];
2918
2919 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter general active : %d", filter->active);
2920
2921 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo' active : %d", filter->filter_typeinfo.active);
2922 if (filter->filter_typeinfo.active > 0) {
2923 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo/must_have' : 0x%08x", filter->filter_typeinfo.typeinfo_must_have);
2924 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo/may_not_have' : 0x%08x", filter->filter_typeinfo.typeinfo_may_not_have);
2925 };
2926
2927 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo2' active : %d", filter->filter_typeinfo2.active);
2928 if (filter->filter_typeinfo2.active > 0) {
2929 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo2/must_have' : 0x%08x", filter->filter_typeinfo2.typeinfo_must_have);
2930 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'typeinfo2/may_not_have': 0x%08x", filter->filter_typeinfo2.typeinfo_may_not_have);
2931 };
2932
2933 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'addr' active : %d", filter->filter_addr.active);
2934 if (filter->filter_addr.active > 0) {
2935 if (filter->filter_addr.addr_must_have_max > 0) {
2936 for (i = 0; i < filter->filter_addr.addr_must_have_max; i++) {
2937 ipv6addrstruct_to_compaddr(&filter->filter_addr.ipv6addr_must_have[i], resultstring, sizeof(resultstring));
2938 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'addr/must_have' : %s", resultstring);
2939 };
2940 };
2941 if (filter->filter_addr.addr_may_not_have_max > 0) {
2942 for (i = 0; i < filter->filter_addr.addr_may_not_have_max; i++) {
2943 ipv6addrstruct_to_compaddr(&filter->filter_addr.ipv6addr_may_not_have[i], resultstring, sizeof(resultstring));
2944 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'addr/may_not_have' : %s", resultstring);
2945 };
2946 };
2947 };
2948
2949 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'db.cc' active : %d", filter->filter_db_cc.active);
2950 if (filter->filter_db_cc.active > 0) {
2951 r = libipv6calc_db_cc_filter_check(&filter->filter_db_cc, IPV6CALC_PROTO_IPV6);
2952 if (r > 0) { result = 1; };
2953 };
2954
2955 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'db.asn' active : %d", filter->filter_db_asn.active);
2956 if (filter->filter_db_asn.active > 0) {
2957 r = libipv6calc_db_asn_filter_check(&filter->filter_db_asn, IPV6CALC_PROTO_IPV6);
2958 if (r > 0) { result = 1; };
2959 };
2960
2961 DEBUGPRINT_WA(DEBUG_libipv6addr, "ipv6 filter 'db.registry' active : %d", filter->filter_db_registry.active);
2962 if (filter->filter_db_registry.active > 0) {
2963 r = libipv6calc_db_registry_filter_check(&filter->filter_db_registry, IPV6CALC_PROTO_IPV6);
2964 if (r > 0) { result = 1; };
2965 };
2966
2967 //END_ipv6addr_filter_check:
2968 return (result);
2969 };
2970
2971
2972 /*
2973 * filter IPv6 address
2974 *
2975 * in : *ipv6addrp = IPv6 address structure
2976 * in : *filter = filter structure
2977 * ret: 0=match 1=not match
2978 */
ipv6addr_filter(const ipv6calc_ipv6addr * ipv6addrp,const s_ipv6calc_filter_ipv6addr * filter)2979 int ipv6addr_filter(const ipv6calc_ipv6addr *ipv6addrp, const s_ipv6calc_filter_ipv6addr *filter) {
2980 int result = 0, r, i, t;
2981
2982 if (filter->active == 0) {
2983 DEBUGPRINT_NA(DEBUG_libipv6addr, "No filter active (SKIP)");
2984 return (1);
2985 };
2986
2987 DEBUGPRINT_NA(DEBUG_libipv6addr, "start");
2988
2989 if ((filter->filter_typeinfo.active > 0) || (filter->filter_typeinfo2.active > 0)) {
2990 if (ipv6addrp->flag_typeinfo == 0) {
2991 fprintf(stderr, "FATAL error, typeinfo not valid - FIX CODE of caller\n");
2992 exit(2);
2993 };
2994 };
2995
2996 if (filter->filter_typeinfo.active > 0) {
2997 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare typeinfo against must_have: 0x%08x/0x%08x", ipv6addrp->typeinfo, filter->filter_typeinfo.typeinfo_must_have);
2998
2999 if ((ipv6addrp->typeinfo & filter->filter_typeinfo.typeinfo_must_have) != filter->filter_typeinfo.typeinfo_must_have) {
3000 /* no match */
3001 result = 1;
3002 } else {
3003 if ((ipv6addrp->typeinfo & filter->filter_typeinfo.typeinfo_may_not_have) != 0) {
3004 /* no match */
3005 result = 1;
3006 };
3007 };
3008 };
3009
3010 if (filter->filter_typeinfo2.active > 0) {
3011 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare typeinfo2 against must_have: 0x%08x/0x%08x", ipv6addrp->typeinfo2, filter->filter_typeinfo2.typeinfo_must_have);
3012
3013 if ((ipv6addrp->typeinfo2 & filter->filter_typeinfo2.typeinfo_must_have) != filter->filter_typeinfo2.typeinfo_must_have) {
3014 /* no match */
3015 result = 1;
3016 } else {
3017 if ((ipv6addrp->typeinfo & filter->filter_typeinfo2.typeinfo_may_not_have) != 0) {
3018 /* no match */
3019 result = 1;
3020 };
3021 };
3022 };
3023
3024 if (filter->filter_addr.active > 0) {
3025 if (filter->filter_addr.addr_must_have_max > 0) {
3026 DEBUGPRINT_NA(DEBUG_libipv6addr, "compare against ipv6addr/must_have");
3027 r = 1;
3028 for (i = 0; i < filter->filter_addr.addr_must_have_max; i++) {
3029 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare against ipv6addr/must_have filter number: %d", i);
3030 t = ipv6addr_compare(ipv6addrp, &filter->filter_addr.ipv6addr_must_have[i],
3031 (filter->filter_addr.ipv6addr_must_have[i].test_mode == IPV6CALC_TEST_PREFIX) ? 1 : 0);
3032
3033 switch (filter->filter_addr.ipv6addr_must_have[i].test_mode) {
3034 case IPV6CALC_TEST_PREFIX:
3035 if (t != 0) { r = 0; }; break;
3036
3037 case IPV6CALC_TEST_LE:
3038 if (t > 0) { r = 0; }; break;
3039
3040 case IPV6CALC_TEST_LT:
3041 if (t >= 0) { r = 0; }; break;
3042
3043 case IPV6CALC_TEST_GE:
3044 if (t < 0) { r = 0; }; break;
3045
3046 case IPV6CALC_TEST_GT:
3047 if (t <= 0) { r = 0; }; break;
3048
3049 default:
3050 ERRORPRINT_WA("unsupported test mode (FIX CODE): %d", filter->filter_addr.ipv6addr_must_have[i].test_mode);
3051 break;
3052 };
3053
3054 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare against ipv6addr/must_have result filter number: %d r=%d", i, r);
3055 };
3056 if (r == 0) {
3057 /* no match */
3058 result = 1;
3059 };
3060 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare against ipv6addr/must_have result: r=%d result=%d", r, result);
3061 };
3062 if (filter->filter_addr.addr_may_not_have_max > 0) {
3063 DEBUGPRINT_NA(DEBUG_libipv6addr, "compare against ipv6addr/may_not_have");
3064 r = 0;
3065 for (i = 0; i < filter->filter_addr.addr_may_not_have_max; i++) {
3066 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare against ipv6addr/may_not_have filter number: %d", i);
3067 t = ipv6addr_compare(ipv6addrp, &filter->filter_addr.ipv6addr_may_not_have[i],
3068 (filter->filter_addr.ipv6addr_may_not_have[i].test_mode == IPV6CALC_TEST_PREFIX) ? 1 : 0);
3069
3070 switch (filter->filter_addr.ipv6addr_may_not_have[i].test_mode) {
3071 case IPV6CALC_TEST_PREFIX:
3072 if (t == 0) { r = 1; }; break;
3073
3074 case IPV6CALC_TEST_LE:
3075 if (t <= 0) { r = 1; }; break;
3076
3077 case IPV6CALC_TEST_LT:
3078 if (t < 0) { r = 1; }; break;
3079
3080 case IPV6CALC_TEST_GE:
3081 if (t >= 0) { r = 1; }; break;
3082
3083 case IPV6CALC_TEST_GT:
3084 if (t > 0) { r = 1; }; break;
3085
3086 default:
3087 ERRORPRINT_WA("unsupported test mode (FIX CODE): %d", filter->filter_addr.ipv6addr_must_have[i].test_mode);
3088 break;
3089 };
3090 DEBUGPRINT_WA(DEBUG_libipv6addr, "compare against ipv6addr/may_not_have result filter number: %d r=%d", i, r);
3091 };
3092 if (r == 1) {
3093 /* match may_not_have*/
3094 result = 1;
3095 };
3096 };
3097 };
3098
3099 if (filter->filter_db_cc.active > 0) {
3100 uint16_t cc_index = libipv6addr_cc_index_by_addr(ipv6addrp, NULL);
3101
3102 if (libipv6calc_db_cc_filter(cc_index, &filter->filter_db_cc) > 0) {
3103 /* no match */
3104 result = 1;
3105 };
3106 };
3107
3108 if (filter->filter_db_asn.active > 0) {
3109 uint32_t asn = libipv6addr_as_num32_by_addr(ipv6addrp, NULL);
3110
3111 if (libipv6calc_db_asn_filter(asn, &filter->filter_db_asn) > 0) {
3112 /* no match */
3113 result = 1;
3114 };
3115 };
3116
3117 if (filter->filter_db_registry.active > 0) {
3118 int registry = libipv6addr_registry_num_by_addr(ipv6addrp);
3119
3120 if (libipv6calc_db_registry_filter(registry, &filter->filter_db_registry) > 0) {
3121 /* no match */
3122 result = 1;
3123 };
3124 };
3125
3126 return (result);
3127 };
3128
3129
3130 /* get included IPv4 address from an IPv6 address */
3131 /* in: IPv6 address pointer (ro)
3132 * selector: in case of Teredo (otherwise ignored):
3133 * IPV6_ADDR_SELECT_IPV4_DEFAULT (TEREDO_CLIENT)
3134 * IPV6_ADDR_SELECT_IPV4_TEREDO_SERVER
3135 * IPV6_ADDR_SELECT_IPV4_PREFIX2_LENGTH
3136 * mod: IPv4 address pointer (rw)
3137 * ret: 0=ok, !=0: no IPv4 adress included
3138 */
libipv6addr_get_included_ipv4addr(const ipv6calc_ipv6addr * ipv6addrp,ipv6calc_ipv4addr * ipv4addrp,const int selector)3139 int libipv6addr_get_included_ipv4addr(const ipv6calc_ipv6addr *ipv6addrp, ipv6calc_ipv4addr *ipv4addrp, const int selector) {
3140 int result = -1;
3141 uint32_t typeinfo, typeinfo2;
3142 int begin = -1, shift = 0;
3143 int i;
3144 uint8_t xor = 0;
3145
3146 typeinfo = ipv6addrp->typeinfo;
3147 typeinfo2 = ipv6addrp->typeinfo2;
3148
3149 DEBUGPRINT_WA(DEBUG_libipv6addr, "Called with IPv6 address having typeinfo: 0x%08x-0x%08x", typeinfo, typeinfo2);
3150
3151 if (selector == IPV6_ADDR_SELECT_IPV4_PREFIX2_LENGTH) {
3152 begin = ipv6addrp->prefix2length / 8;
3153 shift = ipv6addrp->prefix2length % 8;
3154 } else {
3155 if ((typeinfo & (IPV6_ADDR_COMPATv4 | IPV6_ADDR_MAPPED | IPV6_NEW_ADDR_NAT64)) != 0) {
3156 begin = 12;
3157 } else if ((typeinfo & IPV6_NEW_ADDR_TEREDO) != 0) {
3158 if (selector == IPV6_ADDR_SELECT_IPV4_DEFAULT) {
3159 // Teredo client
3160 begin = 12;
3161 xor = 0xff;
3162 } else if (selector == IPV6_ADDR_SELECT_IPV4_TEREDO_SERVER) {
3163 // Teredo server
3164 begin = 4;
3165 } else {
3166 fprintf(stderr, "libipv6addr_get_included_ipv4addr FAILED (unsupported value of selector: %d - FIX CALLING CODE)", selector);
3167 exit(1);
3168 };
3169 } else if ((typeinfo & IPV6_NEW_ADDR_6TO4) != 0) {
3170 begin = 2;
3171 };
3172 };
3173
3174 if (begin > 0) {
3175 if (shift > 0) {
3176 DEBUGPRINT_WA(DEBUG_libipv6addr, "IPv6 address contains IPv4 address in octets %d-%d and shift %d", begin, begin+3, shift);
3177 } else {
3178 DEBUGPRINT_WA(DEBUG_libipv6addr, "IPv6 address contains IPv4 address in octets %d-%d", begin, begin+3);
3179 };
3180
3181 ipv4addr_clearall(ipv4addrp);
3182
3183 if (shift > 0) {
3184 for (i = 0; i <= 4; i++) {
3185 int ipv6_p = ipv6addr_getoctet(ipv6addrp, i + begin);
3186
3187 DEBUGPRINT_WA(DEBUG_libipv6addr, "IPv6[%d]=%02x", i + begin, ipv6_p);
3188 ipv6_p <<= shift;
3189
3190 if (ipv6_p > 0xff) {
3191 if (i > 0) {
3192 // update higher octet
3193 ipv4addr_setoctet(ipv4addrp
3194 , (unsigned int) i - 1
3195 , (unsigned int) (ipv4addr_getoctet(ipv4addrp, i - 1) | (ipv6_p >> 8))
3196 );
3197 };
3198 };
3199
3200 if (i <= 3) {
3201 ipv4addr_setoctet(ipv4addrp
3202 , (unsigned int) i
3203 , (unsigned int) (ipv6_p & 0xff)
3204 );
3205 };
3206 };
3207 } else {
3208 for (i = 0; i <= 3; i++) {
3209 ipv4addr_setoctet(ipv4addrp
3210 , (unsigned int) i
3211 , (unsigned int) ipv6addr_getoctet(ipv6addrp, (unsigned int) (i + begin)) ^ xor
3212 );
3213 };
3214 };
3215
3216 ipv4addr_settype(ipv4addrp, 1);
3217 ipv4addrp->flag_valid = 1;
3218
3219 result = 0;
3220 };
3221
3222 if (result == -1) {
3223 // fprintf(stderr, "libipv6addr_get_included_ipv4addr FAILED (this should not happen)");
3224 };
3225
3226 DEBUGPRINT_WA(DEBUG_libipv6addr, "Return with result: %d", result);
3227
3228 return(result);
3229 };
3230
3231
3232 /*
3233 * country code index of IPv6 address
3234 *
3235 * in : *ipv6addrp = IPv6 address structure
3236 * out: country code index
3237 */
libipv6addr_cc_index_by_addr(const ipv6calc_ipv6addr * ipv6addrp,unsigned int * data_source_ptr)3238 uint16_t libipv6addr_cc_index_by_addr(const ipv6calc_ipv6addr *ipv6addrp, unsigned int *data_source_ptr) {
3239 uint32_t cc_index = COUNTRYCODE_INDEX_UNKNOWN;
3240 ipv6calc_ipv4addr ipv4addr;
3241 ipv6calc_ipv6addr ipv6addr;
3242 ipv6calc_ipaddr ipaddr;
3243 int retval;
3244
3245 DEBUGPRINT_NA(DEBUG_libipv6addr, "start");
3246
3247 if ((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_PREFIX) != 0) {
3248 DEBUGPRINT_NA(DEBUG_libipv6addr, "anonymized prefix handling");
3249 if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) == 0) {
3250 if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0) {
3251 // no country code included
3252 cc_index = COUNTRYCODE_INDEX_LISP;
3253 } else {
3254 /* retrieve CountryCodeIndex from anonymization value */
3255 retval = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_CCINDEX, &cc_index);
3256 if (retval != 0) {
3257 fprintf(stderr, "Error getting CountryCode index from anonymized IPv6 address\n");
3258 goto END_libipv6addr_cc_index_by_addr;
3259 };
3260 };
3261 } else {
3262 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6TO4) != 0) {
3263 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3264 if (retval != 0) {
3265 fprintf(stderr, "Error getting included IPv4 address from anonymized IPv6 address\n");
3266 goto END_libipv6addr_cc_index_by_addr;
3267 };
3268
3269 cc_index = libipv4addr_cc_index_by_addr(&ipv4addr, NULL);
3270 };
3271 };
3272 } else if (((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_IID) != 0) && ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0)) {
3273 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3274 if (retval != 0) {
3275 fprintf(stderr, "Error getting included IPv4 address from anonymized IPv6 address\n");
3276 goto END_libipv6addr_cc_index_by_addr;
3277 };
3278
3279 cc_index = libipv4addr_cc_index_by_addr(&ipv4addr, data_source_ptr);
3280 } else {
3281 if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0) {
3282 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_CC) == 1) {
3283 /* retrieve CountryCodeIndex from IPv4 address inside */
3284 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3285 if (retval != 0) {
3286 fprintf(stderr, "Error getting included IPv4 address from IPv6 address\n");
3287 goto END_libipv6addr_cc_index_by_addr;
3288 };
3289
3290 cc_index = libipv4addr_cc_index_by_addr(&ipv4addr, data_source_ptr);
3291 } else {
3292 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV4_TO_CC");
3293 };
3294 } else if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) != 0) {
3295 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_CC) == 1) {
3296 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3297 if (retval != 0) {
3298 fprintf(stderr, "Error getting included IPv4 address from IPv6 address\n");
3299 goto END_libipv6addr_cc_index_by_addr;
3300 };
3301
3302 cc_index = libipv4addr_cc_index_by_addr(&ipv4addr, data_source_ptr);
3303 } else {
3304 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV4_TO_CC");
3305 };
3306 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6BONE) != 0) {
3307 cc_index = COUNTRYCODE_INDEX_UNKNOWN_REGISTRY_MAP_MIN + IPV6_ADDR_REGISTRY_6BONE;
3308 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_ORCHID) != 0) {
3309 DEBUGPRINT_NA(DEBUG_libipv6addr, "ORCHID has no country");
3310 goto END_libipv6addr_cc_index_by_addr;
3311 } else if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0) {
3312 DEBUGPRINT_NA(DEBUG_libipv6addr, "LISP has no country");
3313 goto END_libipv6addr_cc_index_by_addr;
3314 } else if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_CC) == 1) {
3315 if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_ANON_MASKED_PREFIX) != 0) {
3316 if (ipv6addrp->prefix2length < 48) {
3317 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized prefix prefix length to low for detecting country: %u", ipv6addrp->prefix2length);
3318 goto END_libipv6addr_cc_index_by_addr;
3319 };
3320 ipv6addr = *ipv6addrp;
3321 ipv6addr.flag_prefixuse = 1;
3322 ipv6addr.prefixlength = ipv6addrp->prefix2length;
3323 ipv6addrstruct_maskprefix(&ipv6addr);
3324 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized prefix found, apply prefix length %u", ipv6addr.prefixlength);
3325 CONVERT_IPV6ADDRP_IPADDR(&ipv6addr, ipaddr);
3326 } else {
3327 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
3328 };
3329
3330 cc_index = libipv6calc_db_wrapper_cc_index_by_addr(&ipaddr, data_source_ptr);
3331 } else {
3332 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV6_TO_CC");
3333 };
3334 };
3335
3336 END_libipv6addr_cc_index_by_addr:
3337 DEBUGPRINT_WA(DEBUG_libipv6addr, "cc_index=%d (0x%03x)", cc_index, cc_index);
3338 return(cc_index);
3339 };
3340
3341
3342 /*
3343 * 32-bit AS number of IPv6 address
3344 *
3345 * in : *ipv6addrp = IPv6 address structure
3346 * out: 32-bit AS number
3347 */
libipv6addr_as_num32_by_addr(const ipv6calc_ipv6addr * ipv6addrp,unsigned int * data_source_ptr)3348 uint32_t libipv6addr_as_num32_by_addr(const ipv6calc_ipv6addr *ipv6addrp, unsigned int *data_source_ptr) {
3349 uint32_t as_num32 = ASNUM_AS_UNKNOWN;
3350 ipv6calc_ipv4addr ipv4addr;
3351 ipv6calc_ipv6addr ipv6addr;
3352 ipv6calc_ipaddr ipaddr;
3353 uint32_t payload;
3354 int retval;
3355
3356 DEBUGPRINT_NA(DEBUG_libipv6addr, "start");
3357
3358 if ((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_PREFIX) != 0) {
3359 DEBUGPRINT_NA(DEBUG_libipv6addr, "IPv6 address has anonymized prefix");
3360 if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) == 0) {
3361 if ((ipv6addrp->typeinfo & IPV6_ADDR_IID_32_63_HAS_IPV4) != 0) {
3362 DEBUGPRINT_NA(DEBUG_libipv6addr, "retrieve ASN from anonymized IPv4 in IID");
3363 payload = ipv6addr_get_payload_anonymized_iid(ipv6addrp, ipv6addrp->typeinfo);
3364 /* IPv4 */
3365 ipv4addr_clearall(&ipv4addr);
3366 ipv4addr_setoctet(&ipv4addr, 0, (payload >> 16) & 0xff);
3367 ipv4addr_setoctet(&ipv4addr, 1, (payload >> 8) & 0xff);
3368 ipv4addr_setoctet(&ipv4addr, 2, (payload ) & 0xff);
3369 ipv4addr_setoctet(&ipv4addr, 3, 0);
3370
3371 ipv4addr_settype(&ipv4addr, 1); // set type
3372 ipv4addr.flag_valid = 1;
3373
3374 as_num32 = libipv4addr_as_num32_by_addr(&ipv4addr, data_source_ptr);
3375 } else {
3376 /* retrieve ASN from anonymization value */
3377 DEBUGPRINT_NA(DEBUG_libipv6addr, "retrieve ASN from anonymized prefix");
3378 retval = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_ASN32, &as_num32);
3379 if (retval != 0) {
3380 fprintf(stderr, "Error getting ASN32 from anonymized IPv6 address\n");
3381 goto END_libipv6addr_as_num32_by_addr;
3382 };
3383 };
3384 } else {
3385 if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6TO4) != 0) {
3386 /* retrieve ASN from included IPv4 address */
3387 DEBUGPRINT_NA(DEBUG_libipv6addr, "retrieve ASN from included IPv4 address (6to4)");
3388 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3389 if (retval != 0) {
3390 fprintf(stderr, "Error getting included IPv4 address from anonymized IPv6 address\n");
3391 goto END_libipv6addr_as_num32_by_addr;
3392 };
3393
3394 as_num32 = libipv4addr_as_num32_by_addr(&ipv4addr, data_source_ptr);
3395 };
3396 };
3397 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6BONE) != 0) {
3398 as_num32 = ASNUM_AS_UNKNOWN;
3399 goto END_libipv6addr_as_num32_by_addr;
3400 } else {
3401 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_AS) == 1) {
3402 if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_ANON_MASKED_PREFIX) != 0) {
3403 if (ipv6addrp->prefix2length < 48) {
3404 goto END_libipv6addr_as_num32_by_addr;
3405 };
3406 ipv6addr = *ipv6addrp;
3407 ipv6addr.flag_prefixuse = 1;
3408 ipv6addr.prefixlength = ipv6addrp->prefix2length;
3409 ipv6addrstruct_maskprefix(&ipv6addr);
3410 DEBUGPRINT_WA(DEBUG_libipv6addr, "anonymized prefix found, apply prefix length %u", ipv6addr.prefixlength);
3411 CONVERT_IPV6ADDRP_IPADDR(&ipv6addr, ipaddr);
3412 } else {
3413 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
3414 };
3415
3416 as_num32 = libipv6calc_db_wrapper_as_num32_by_addr(&ipaddr, data_source_ptr);
3417 } else {
3418 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV6_TO_AS");
3419 };
3420 };
3421
3422 END_libipv6addr_as_num32_by_addr:
3423 DEBUGPRINT_WA(DEBUG_libipv6addr, "as_num32=%d (0x%08x)", as_num32, as_num32);
3424 return(as_num32);
3425 };
3426
3427
3428 /*
3429 * registry number of IPv6 address
3430 *
3431 * in : *ipv6addrp = IPv6 address structure
3432 * out: registry number
3433 */
libipv6addr_registry_num_by_addr(const ipv6calc_ipv6addr * ipv6addrp)3434 int libipv6addr_registry_num_by_addr(const ipv6calc_ipv6addr *ipv6addrp) {
3435 int registry = IPV6_ADDR_REGISTRY_UNKNOWN;
3436 uint16_t cc_index;
3437 uint32_t as_num32;
3438 uint32_t geonameid_type;
3439 ipv6calc_ipv6addr ipv6addr;
3440
3441 if (((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_PREFIX) != 0) \
3442 && ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) == 0)) {
3443 if ((ipv6addrp->typeinfo2 & (IPV6_ADDR_TYPE2_ANONYMIZED_GEONAMEID)) == 0) {
3444 /* retrieve registry via cc_index from anonymized address (simple) */
3445 cc_index = libipv6addr_cc_index_by_addr(ipv6addrp, NULL);
3446
3447 if (cc_index == COUNTRYCODE_INDEX_LISP) {
3448 as_num32 = libipv6addr_as_num32_by_addr(ipv6addrp, NULL);
3449 registry = libipv6calc_db_wrapper_registry_num_by_as_num32(as_num32);
3450 } else {
3451 registry = libipv6calc_db_wrapper_registry_num_by_cc_index(cc_index);
3452 };
3453 } else {
3454 if (ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_GEONAMEID_TYPE, &geonameid_type) == 0) {
3455 DEBUGPRINT_WA(DEBUG_libipv6addr, "geonameid_type/registry=%d (0x%03x)", geonameid_type, geonameid_type);
3456 if ((geonameid_type & 0x300) == 0x000) {
3457 registry = (geonameid_type & 0x0f0) >> 4;
3458 };
3459 };
3460 };
3461 } else {
3462 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_REGISTRY) == 1) {
3463 if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_ANON_MASKED_PREFIX) != 0) {
3464 if (ipv6addrp->prefix2length < 12) {
3465 goto END_libipv6addr_registry_by_addr;
3466 };
3467 ipv6addr = *ipv6addrp;
3468 ipv6addr.flag_prefixuse = 1;
3469 ipv6addr.prefixlength = ipv6addrp->prefix2length;
3470 ipv6addrstruct_maskprefix(&ipv6addr);
3471 registry = libipv6calc_db_wrapper_registry_num_by_ipv6addr(&ipv6addr);
3472 } else {
3473 registry = libipv6calc_db_wrapper_registry_num_by_ipv6addr(ipv6addrp);
3474 };
3475 };
3476 };
3477
3478 END_libipv6addr_registry_by_addr:
3479 DEBUGPRINT_WA(DEBUG_libipv6addr, "registry=%d (0x%x)", registry, registry);
3480 return(registry);
3481 };
3482
3483
3484 /*
3485 * GeonameID of IPv6 address
3486 *
3487 * in : *ipv6addrp = IPv6 address structure
3488 * mod: GeonameID_type_ptr
3489 * out: GeonameID
3490 */
libipv6addr_GeonameID_by_addr(const ipv6calc_ipv6addr * ipv6addrp,unsigned int * data_source_ptr,unsigned int * GeonameID_type_ptr)3491 uint32_t libipv6addr_GeonameID_by_addr(const ipv6calc_ipv6addr *ipv6addrp, unsigned int *data_source_ptr, unsigned int *GeonameID_type_ptr) {
3492 uint32_t GeonameID = IPV6CALC_DB_GEO_GEONAMEID_UNKNOWN;
3493 uint32_t GeonameID_type = IPV6CALC_DB_GEO_GEONAMEID_TYPE_UNKNOWN;
3494 unsigned int data_source = IPV6CALC_DB_SOURCE_UNKNOWN;
3495 ipv6calc_ipaddr ipaddr;
3496 ipv6calc_ipv4addr ipv4addr;
3497 int retval;
3498
3499 if ((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_PREFIX) != 0) {
3500 if (((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0)
3501 || ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) != 0)) {
3502 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3503 if (retval != 0) {
3504 fprintf(stderr, "Error getting included IPv4 address from IPv6 address\n");
3505 goto END_libipv6addr_GeonameID_by_addr;
3506 };
3507 GeonameID = libipv4addr_GeonameID_by_addr(&ipv4addr, NULL, &GeonameID_type);
3508 } else if (((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_ANONYMIZED_GEONAMEID) != 0) \
3509 && ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) == 0)) {
3510 // GeonameID included
3511 int r1 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_GEONAMEID, &GeonameID);
3512 int r2 = ipv6addr_get_payload_anonymized_prefix(ipv6addrp, ANON_PREFIX_PAYLOAD_GEONAMEID_TYPE, &GeonameID_type);
3513 GeonameID_type &= 0x00f;
3514 DEBUGPRINT_WA(DEBUG_libipv6addr, "result of anonymized IPv6 GeonameID retrievement: %d (0x%08x) (source: %02x)", GeonameID, GeonameID, GeonameID_type);
3515 if ((r1 == 0) && (r2 == 0)) {
3516 // dummy
3517 };
3518 };
3519 } else if (((ipv6addrp->typeinfo & IPV6_ADDR_ANONYMIZED_IID) != 0) && ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0)) {
3520 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3521 if (retval != 0) {
3522 fprintf(stderr, "Error getting included IPv4 address from anonymized IPv6 address\n");
3523 goto END_libipv6addr_GeonameID_by_addr;
3524 };
3525 GeonameID = libipv4addr_GeonameID_by_addr(&ipv4addr, NULL, &GeonameID_type);
3526 } else {
3527 if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_IID) != 0) {
3528 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_GEONAMEID) == 1) {
3529 /* retrieve GeonameID from IPv4 address inside */
3530 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3531 if (retval != 0) {
3532 fprintf(stderr, "Error getting included IPv4 address from IPv6 address\n");
3533 goto END_libipv6addr_GeonameID_by_addr;
3534 };
3535 GeonameID = libipv4addr_GeonameID_by_addr(&ipv4addr, NULL, &GeonameID_type);
3536 } else {
3537 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV4_TO_GEONAMEID");
3538 };
3539 } else if ((ipv6addrp->typeinfo & IPV6_ADDR_HAS_PUBLIC_IPV4_IN_PREFIX) != 0) {
3540 if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_GEONAMEID) == 1) {
3541 retval = libipv6addr_get_included_ipv4addr(ipv6addrp, &ipv4addr, IPV6_ADDR_SELECT_IPV4_DEFAULT);
3542 if (retval != 0) {
3543 fprintf(stderr, "Error getting included IPv4 address from IPv6 address\n");
3544 goto END_libipv6addr_GeonameID_by_addr;
3545 };
3546 GeonameID = libipv4addr_GeonameID_by_addr(&ipv4addr, NULL, &GeonameID_type);
3547 } else {
3548 DEBUGPRINT_NA(DEBUG_libipv6addr, "DB feature missing: DB_IPV4_TO_GEONAMEID");
3549 };
3550 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_6BONE) != 0) {
3551 DEBUGPRINT_NA(DEBUG_libipv6addr, "6bone has no GeonameID");
3552 goto END_libipv6addr_GeonameID_by_addr;
3553 } else if ((ipv6addrp->typeinfo & IPV6_NEW_ADDR_ORCHID) != 0) {
3554 DEBUGPRINT_NA(DEBUG_libipv6addr, "ORCHID has no GeonameID");
3555 goto END_libipv6addr_GeonameID_by_addr;
3556 } else if ((ipv6addrp->typeinfo2 & IPV6_ADDR_TYPE2_LISP) != 0) {
3557 DEBUGPRINT_NA(DEBUG_libipv6addr, "LISP has no country");
3558 goto END_libipv6addr_GeonameID_by_addr;
3559 } else if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_GEONAMEID) == 1) {
3560 // get GeonameID
3561 CONVERT_IPV6ADDRP_IPADDR(ipv6addrp, ipaddr);
3562 GeonameID = libipv6calc_db_wrapper_GeonameID_by_addr(&ipaddr, &data_source, &GeonameID_type);
3563 DEBUGPRINT_WA(DEBUG_libipv6addr, "result of GeonameID retrievement: %d (0x%08x) (source: %02x)", GeonameID, GeonameID, GeonameID_type);
3564 } else {
3565 DEBUGPRINT_NA(DEBUG_libipv6addr, "No support available for IPV6CALC_DB_IPV6_TO_GEONAMEID");
3566 };
3567 };
3568
3569 DEBUGPRINT_WA(DEBUG_libipv6addr, "GeonameID=%d (0x%x)", GeonameID, GeonameID);
3570
3571 if (data_source_ptr != NULL) {
3572 *data_source_ptr = data_source;
3573 };
3574
3575 if (GeonameID_type_ptr != NULL) {
3576 *GeonameID_type_ptr = GeonameID_type;
3577 };
3578
3579 END_libipv6addr_GeonameID_by_addr:
3580 return(GeonameID);
3581 };
3582