1 /*
2  * Project    : ipv6calc/lib
3  * File       : libipv6calc.c
4  * Version    : $Id: 117603045c748f630e6c2cb162a58710de4d60d8 $
5  * Copyright  : 2001-2019 by Peter Bieringer <pb (at) bieringer.de>
6  *
7  * Information:
8  *  Function library for some tools
9  */
10 
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <ctype.h>
15 
16 #include "config.h"
17 
18 #include "ipv6calctypes.h"
19 #include "libipv6calc.h"
20 #include "libipv6calcdebug.h"
21 #include "librfc1924.h"
22 #include "librfc2874.h"
23 #include "librfc1886.h"
24 
25 #include "../databases/lib/libipv6calc_db_wrapper.h"
26 
27 /*
28  * function converts chars in a string to upcase
29  * in : pointer to a string
30  */
string_to_upcase(char * string)31 void string_to_upcase(char *string) {
32 	int i;
33 
34 	if (strlen(string) > 0) {
35 		for (i = 0; i < (int) strlen(string); i++) {
36 			string[i] = toupper(string[i]);
37 		};
38 	};
39 
40 	return;
41 };
42 
43 
44 /*
45  * function converts chars in a string to lowcase
46  * in : pointer to a string
47  */
string_to_lowcase(char * string)48 void string_to_lowcase(char *string) {
49 	int i;
50 
51 	if (strlen(string) > 0) {
52 		for (i = 0; i < (int) strlen(string); i++) {
53 			string[i] = tolower(string[i]);
54 		};
55 	};
56 
57 	return;
58 };
59 
60 
61 /*
62  * reverse string
63  * in : pointer to a string
64  */
string_to_reverse(char * string)65 void string_to_reverse(char *string) {
66 	int i;
67 	char helpchar;
68 	size_t length;
69 
70 	length = strlen(string);
71 
72 	if (length < 2) {
73 		/* nothing to do */
74 		return;
75 	};
76 
77 	for (i = 0; i < ( (int) (length >> 1)); i++) {
78 		helpchar = string[i];
79 		string[i] = string[length - i - 1];
80 		string[length - i - 1] = helpchar;
81 	};
82 
83 	return;
84 };
85 
86 
87 /*
88  * dotted-reverse string
89  * in : pointer to a string
90  */
string_to_reverse_dotted(char * string,const size_t string_length)91 void string_to_reverse_dotted(char *string, const size_t string_length) {
92 	char resultstring[IPV6CALC_STRING_MAX], tempstring[IPV6CALC_STRING_MAX];
93 	char *token, *cptr, **ptrptr;
94 	int flag_first = 1;
95 
96 	ptrptr = &cptr;
97 
98 	/* clear result string */
99 	snprintf(resultstring, sizeof(resultstring), "%s", "");
100 
101 	/* check for starting dot */
102 	if ( string[0] == '.' ) {
103 		snprintf(tempstring, sizeof(tempstring), "%s.", resultstring);
104 		snprintf(resultstring, sizeof(resultstring), "%s", tempstring);
105 	};
106 
107 	token = strtok_r(string, ".", ptrptr);
108 
109 	while (token != NULL) {
110 		if (flag_first == 1) {
111 			snprintf(tempstring, sizeof(tempstring), "%s%s", token, resultstring);
112 			flag_first = 0;
113 		} else {
114 			snprintf(tempstring, sizeof(tempstring), "%s.%s", token, resultstring);
115 		};
116 		snprintf(resultstring, sizeof(resultstring), "%s", tempstring);
117 
118 		token = strtok_r(NULL, ".", ptrptr);
119 	};
120 
121 	if ( string[strlen(string) - 1] == '.' ) {
122 		snprintf(tempstring, sizeof(tempstring), ".%s", resultstring);
123 		snprintf(resultstring, sizeof(resultstring), "%s", tempstring);
124 	};
125 
126 	snprintf(string, string_length, ".%s", resultstring);
127 
128 	return;
129 };
130 
131 
132 /*
133  * function converts chars in a string to upcase
134  * in : pointer to a string
135  * ret: format number
136  */
libipv6calc_autodetectinput(const char * string)137 uint32_t libipv6calc_autodetectinput(const char *string) {
138 	uint32_t type = FORMAT_auto_noresult;
139 	int i, j = 0, result;
140 	unsigned int numdots = 0, numcolons = 0, numdigits = 0, numxdigits = 0, numdashes = 0, numspaces = 0, numslashes = 0, numalnums = 0, numchar_s = 0, numpercents = 0, numcolonsdouble = 0, xdigitlen_max = 0, xdigitlen_min = 0, xdl;
141 	char resultstring[IPV6CALC_STRING_MAX];
142 	size_t length;
143 	ipv6calc_ipv4addr ipv4addr;
144 
145 	length = strlen(string);
146 
147 	if (length == 0) {
148 		/* input is empty */
149 		goto END_libipv6calc_autodetectinput;
150 	};
151 
152 	ipv4addr_clearall(&ipv4addr);
153 	if (addr_to_ipv4addrstruct(string, NULL, 0, &ipv4addr) == 0) {
154 		type = FORMAT_ipv4addr;
155 		goto END_libipv6calc_autodetectinput;
156 	}
157 
158 	xdl = 0;
159 	for (i = 0; i < (int) length; i++) {
160 		if (string[i] == '.') { numdots++; };
161 		if (string[i] == ':') {
162 			numcolons++;
163 			if (i < (int) length + 1) {
164 				/* check for double colons */
165 				if (string[i+1] == ':') {
166 					numcolonsdouble++;
167 					numcolons++;
168 					i++;
169 				};
170 			};
171 		};
172 		if (string[i] == '-') { numdashes++; };
173 		if (string[i] == '/') { numslashes++; };
174 		if (string[i] == ' ') { numspaces++; };
175 		if (string[i] == '%') { numpercents++; };
176 		if (string[i] == 's') { numchar_s++; };
177 		if (isdigit((int) string[i])) { numdigits++; };
178 		if (isxdigit((int) string[i])) {
179 			numxdigits++;
180 			xdl++;
181 		} else {
182 			if (xdigitlen_max == 0 && xdigitlen_min == 0) {
183 				// init
184 				xdigitlen_max = xdl;
185 				xdigitlen_min = xdl;
186 			};
187 			if (xdl > xdigitlen_max) {
188 				xdigitlen_max = xdl;
189 			};
190 			if (xdl < xdigitlen_min) {
191 				xdigitlen_min = xdl;
192 			};
193 			xdl = 0;
194 		};
195 		if (isalnum((int) string[i])) { numalnums++; };
196 	};
197 
198 	DEBUGPRINT_NA(DEBUG_libipv6calc, "Autodetection source:");
199 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numdots        :%d", numdots);
200 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numcolons      :%d", numcolons);
201 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numcolonsdouble:%d", numcolonsdouble);
202 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numdashes      :%d", numdashes);
203 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numspaces      :%d", numspaces);
204 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numslashes     :%d", numslashes);
205 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numdigits      :%d", numdigits);
206 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numxdigits     :%d", numxdigits);
207 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numalnums      :%d", numalnums);
208 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numpercents    :%d", numpercents);
209 	DEBUGPRINT_WA(DEBUG_libipv6calc, " numchar_s      :%d", numchar_s);
210 	DEBUGPRINT_WA(DEBUG_libipv6calc, " xdigit len max :%d", xdigitlen_max);
211 	DEBUGPRINT_WA(DEBUG_libipv6calc, " xdigit len min :%d", xdigitlen_min);
212 	DEBUGPRINT_WA(DEBUG_libipv6calc, " length         :%d", (int) length);
213 
214 	if ( length == 20 && numdots == 0 && numcolons == 0 ) {
215 	        /* probably a base85 one */
216 		DEBUGPRINT_NA(DEBUG_libipv6calc, " check FORMAT_base85");
217 		result = librfc1924_formatcheck(string, resultstring, sizeof(resultstring));
218 	        if ( result == 0 ) {
219 			/* ok: base85 */
220 			type = FORMAT_base85;
221 			goto END_libipv6calc_autodetectinput;
222 		} else DEBUGPRINT_WA(DEBUG_libipv6calc, " check FORMAT_base85 not successful, result: %s", resultstring);
223 	};
224 
225 	if ( strncmp(string, "\\[", 2) == 0 ) {
226 		/* check for Bitstring label: \[x..../dd] */
227 		DEBUGPRINT_NA(DEBUG_libipv6calc, " check FORMAT_bitstring");
228 		result = librfc2874_formatcheck(string, resultstring, strlen(resultstring));
229 	        if ( result == 0 ) {
230 			/* ok: bitstring label */
231 			type = FORMAT_bitstring;
232 			goto END_libipv6calc_autodetectinput;
233 		} else DEBUGPRINT_WA(DEBUG_libipv6calc, " check FORMAT_bitstring not successful, result: %s", resultstring);
234 	};
235 
236 	if (length == 32 && numxdigits == 32 && numdots == 0 && numcolons == 0) {
237 		/* ifinet6 xxxx..xxxx  */
238 		type = FORMAT_ifinet6;
239 		goto END_libipv6calc_autodetectinput;
240 	};
241 
242 	if (((length == 8 && numxdigits == 8) || (length == 7 && numxdigits == 7)) && numdots == 0 && numcolons == 0) {
243 		/* IPv4 hexadecimal: xxxxxxxx or xxxxxxx */
244 		type = FORMAT_ipv4hex;
245 		goto END_libipv6calc_autodetectinput;
246 	};
247 
248 	if ((length >= 11 && length <= 17 && numxdigits >= 6 && numxdigits <= 12 && numdots == 0 && ( (numcolons == 5 && numdashes == 0 && numspaces == 0)
249 	   	 || (numcolons == 0 && numdashes == 5 && numspaces == 0)
250 		    || (numcolons == 0 && numdashes == 0 && numspaces == 5))
251 	    )
252 	    || (length == 13 && numcolons == 0 && numdashes == 1 && numspaces == 0 && numxdigits == 12)
253 	    || (length == 12 && numcolons == 0 && numdashes == 0 && numspaces == 0 && numxdigits == 12)
254 	    || (length == 14 && numdots == 2 && numxdigits ==12 && xdigitlen_min == 4 && xdigitlen_max == 4)
255 	   ) {
256 		/* MAC 00:00:00:00:00:00 or 00-00-00-00-00-00 or "xx xx xx xx xx xx" or "xxxxxx-xxxxxx" or xxxxxxxxxxxx or xxxx.xxxx.xxxx */
257 
258 	    	if (length == 14 && numdots == 2 && numxdigits ==12 && xdigitlen_min == 4 && xdigitlen_max == 4) {
259 			// xxxx.xxxx.xxxx
260 			type = FORMAT_mac;
261 			DEBUGPRINT_NA(DEBUG_libipv6calc, "Autodetection found type: mac");
262 			goto END_libipv6calc_autodetectinput;
263 		};
264 
265 		DEBUGPRINT_NA(DEBUG_libipv6calc, " check FORMAT_mac");
266 
267 		/* Check whether minimum 1 xdigit is between colons, dashes, spaces */
268 		if (numcolons == 0 && numdashes == 1 && numspaces == 0 && numxdigits == 12) {
269 
270 			/* Check xxxxxx-xxxxxx */
271 			j = 0;
272 			for (i = 0; i < (int) length; i++) {
273 				if (isxdigit((int) string[i])) {
274 					j++;
275 					if ( j > 6 ) {
276 						/* more than 6 xdigits */
277 						j = -1;
278 						break;
279 					};
280 					continue;
281 				} else if (string[i] == '-' ) {
282 					if ( j == 0 ) {
283 						/* dash follow dash */
284 						j = -1;
285 						break;
286 					};
287 					j = 0;
288 					continue;
289 				};
290 				/* normally not reached */
291 				j = -1;
292 				break;
293 			};
294 
295 		} else if (numcolons == 0 && numdashes == 0 && numspaces == 0 && numxdigits == 12) {
296 			/* nothing more to check */
297 		} else {
298 
299 			j = 0;
300 			for (i = 0; i < (int) length; i++) {
301 				if (isxdigit((int) string[i])) {
302 					j++;
303 					if ( j > 2 ) {
304 						/* more than 2 xdigits */
305 						j = -1;
306 						break;
307 					};
308 					continue;
309 				} else if (string[i] == ':' || string[i] == '-' || string[i] == ' ') {
310 					if ( j == 0 ) {
311 						/* colon/dash/space follows colon/dash/space */
312 						j = -1;
313 						break;
314 					};
315 					j = 0;
316 					continue;
317 				};
318 				/* normally not reached */
319 				j = -1;
320 				break;
321 			};
322 
323 		}; /* end of if */
324 
325 		if ( j != -1 ) {
326 			type = FORMAT_mac;
327 			DEBUGPRINT_NA(DEBUG_libipv6calc, "Autodetection found type: mac");
328 			goto END_libipv6calc_autodetectinput;
329 		};
330 	};
331 
332 	if ((length >= 15 && length <= 23 && numxdigits >= 8 && numxdigits <= 16 && numdots == 0 && ( (numcolons == 7 && numdashes == 0 && numspaces == 0) || (numcolons == 0 && numdashes == 7 && numspaces == 0) || (numcolons == 0 && numdashes == 0 && numspaces == 7))) || (length == 16 && numcolons == 0 && numdashes == 0 && numspaces == 0 && numxdigits == 16)) {
333 		/* EUI-64 00:00:00:00:00:00:00:00 or 00-00-00-00-00-00-00-00 or "xx xx xx xx xx xx xx xx" or xxxxxxxxxxxxxxxx */
334 
335 		DEBUGPRINT_NA(DEBUG_libipv6calc, " check FORMAT_eui64");
336 
337 		if (numcolons == 0 && numdashes == 0 && numspaces == 0 && numxdigits == 16) {
338 			/* nothing more to check */
339 		} else {
340 
341 			j = 0;
342 			for (i = 0; i < (int) length; i++) {
343 				if (isxdigit((int) string[i])) {
344 					j++;
345 					if ( j > 2 ) {
346 						/* more than 2 xdigits */
347 						j = -1;
348 						break;
349 					};
350 					continue;
351 				} else if (string[i] == ':' || string[i] == '-' || string[i] == ' ') {
352 					if ( j == 0 ) {
353 						/* colon/dash/space follows colon/dash/space */
354 						j = -1;
355 						break;
356 					};
357 					j = 0;
358 					continue;
359 				};
360 				/* normally not reached */
361 				j = -1;
362 				break;
363 			};
364 
365 		}; /* end of if */
366 
367 		if ( j != -1 ) {
368 			type = FORMAT_eui64;
369 			DEBUGPRINT_NA(DEBUG_libipv6calc, "Autodetection found type: eui64");
370 			goto END_libipv6calc_autodetectinput;
371 		};
372 	};
373 
374 	if (numcolons == 0 && numdots > 0 && numslashes == 0 && numspaces == 0 && (numalnums + numdots) == length) {
375 		/* check for reverse nibble string */
376 		DEBUGPRINT_NA(DEBUG_libipv6calc, " check FORMAT_revnibbels_arpa");
377 		result = librfc1886_formatcheck(string, resultstring, sizeof(resultstring));
378 	        if ( result == 0 ) {
379 			/* ok: reverse nibble string */
380 			type = FORMAT_revnibbles_arpa;
381 			goto END_libipv6calc_autodetectinput;
382 		} else DEBUGPRINT_WA(DEBUG_libipv6calc, " check FORMAT_revnibbels_arpa not successful, result: %s", resultstring);
383 	};
384 
385 	if ((numcolons == 3) && (numcolonsdouble == 0) && numdots == 0 && numslashes == 0 && numpercents == 0 && ((numcolons + numxdigits) == length)) {
386 		/* IID */
387 		type = FORMAT_iid;
388 		goto END_libipv6calc_autodetectinput;
389 	};
390 
391 	if (numcolons != 0 && numdots <= 3 && numslashes <= 1 && ((numpercents == 0 && (numdots + numcolons + numxdigits + numslashes) == length) || (numpercents == 1 && (numdots + numcolons + numxdigits + numslashes + numpercents) <= length))) {
392 		/* hopefully an IPv6 address */
393 		/* fe80::1 */
394 		/* fe80::1%eth0 */
395 		type = FORMAT_ipv6addr;
396 		goto END_libipv6calc_autodetectinput;
397 	};
398 
399 	if (numcolons == 0 && numdots == 2 && numslashes == 0 && numdashes >= 3 && ((numchar_s == 0 && (numdashes + numdots + numxdigits + 10) == length) || (numchar_s == 1 && (numdashes + numdots + numxdigits + numchar_s + 10) <= length))) {
400 		/* hopefully an IPv6 literal address (e.g. 2001-DB8--1.IPV6-LITERAL.NET) IPV6-LITERAL.NET has 10 chars which are not xdigit  */
401 		/* also supported with scope: fe80--218-8bff-fe17-a226s4.ipv6-literal.net */
402 		type = FORMAT_ipv6literal;
403 		goto END_libipv6calc_autodetectinput;
404 	};
405 
406 END_libipv6calc_autodetectinput:
407 	if (type != FORMAT_auto_noresult) {
408 		DEBUGPRINT_WA(DEBUG_libipv6calc, "Autodetection found type: 0x%08x", (unsigned int) type);
409 	} else {
410 		DEBUGPRINT_NA(DEBUG_libipv6calc, "Autodetection not successful");
411 	};
412 	return (type);
413 };
414 
415 
416 /*
417  * clear filter master structure
418  *
419  * in : *filter    = filter structure
420  */
libipv6calc_filter_clear(s_ipv6calc_filter_master * filter_master)421 void libipv6calc_filter_clear(s_ipv6calc_filter_master *filter_master) {
422 	ipv4addr_filter_clear(&filter_master->filter_ipv4addr);
423 	ipv6addr_filter_clear(&filter_master->filter_ipv6addr);
424         macaddr_filter_clear(&filter_master->filter_macaddr);
425 	return;
426 };
427 
428 /*
429  * clear filter sub structure db_cc
430  *
431  * in : *filter    = filter structure
432  */
libipv6calc_filter_clear_db_cc(s_ipv6calc_filter_db_cc * filter_db_cc)433 void libipv6calc_filter_clear_db_cc(s_ipv6calc_filter_db_cc *filter_db_cc) {
434 	int i;
435 
436 	filter_db_cc->active = 0;
437 	filter_db_cc->cc_must_have_max = 0;
438 	filter_db_cc->cc_may_not_have_max = 0;
439 
440 	for (i = 0; i < IPV6CALC_FILTER_DB_CC_MAX; i++) {
441 		filter_db_cc->cc_must_have[i] = 0;
442 		filter_db_cc->cc_may_not_have[i] = 0;
443 	};
444 
445 	return;
446 };
447 
448 
449 /*
450  * clear filter sub structure db_asn
451  *
452  * in : *filter    = filter structure
453  */
libipv6calc_filter_clear_db_asn(s_ipv6calc_filter_db_asn * filter_db_asn)454 void libipv6calc_filter_clear_db_asn(s_ipv6calc_filter_db_asn *filter_db_asn) {
455 	int i;
456 
457 	filter_db_asn->active = 0;
458 	filter_db_asn->asn_must_have_max = 0;
459 	filter_db_asn->asn_may_not_have_max = 0;
460 
461 	for (i = 0; i < IPV6CALC_FILTER_DB_ASN_MAX; i++) {
462 		filter_db_asn->asn_must_have[i] = 0;
463 		filter_db_asn->asn_may_not_have[i] = 0;
464 	};
465 
466 	return;
467 };
468 
469 
470 /*
471  * clear filter sub structure db_registry
472  *
473  * in : *filter    = filter structure
474  */
libipv6calc_filter_clear_db_registry(s_ipv6calc_filter_db_registry * filter_db_registry)475 void libipv6calc_filter_clear_db_registry(s_ipv6calc_filter_db_registry *filter_db_registry) {
476 	int i;
477 
478 	filter_db_registry->active = 0;
479 	filter_db_registry->registry_must_have_max = 0;
480 	filter_db_registry->registry_may_not_have_max = 0;
481 
482 	for (i = 0; i < IPV6CALC_FILTER_DB_REGISTRY_MAX; i++) {
483 		filter_db_registry->registry_must_have[i] = 0;
484 		filter_db_registry->registry_may_not_have[i] = 0;
485 	};
486 
487 	return;
488 };
489 
490 
491 /*
492  * function parses ipv6calc filter expression
493  *
494  * in : pointer to a string
495  * mod: master filter structure
496  * ret: success
497  */
libipv6calc_filter_parse(const char * expression,s_ipv6calc_filter_master * filter_master)498 int libipv6calc_filter_parse(const char *expression, s_ipv6calc_filter_master *filter_master) {
499 	char tempstring[IPV6CALC_STRING_MAX] = "";
500 	char *charptr, *cptr, **ptrptr;
501 	ptrptr = &cptr;
502 	int r, token_used, result = 0;
503 
504 	DEBUGPRINT_WA(DEBUG_libipv6calc, "called with: %s", expression);
505 
506 	snprintf(tempstring, sizeof(tempstring), "%s", expression);
507 
508 	/* split expression */
509 	charptr = strtok_r(tempstring, ",", ptrptr);
510 	while (charptr != NULL) {
511 		token_used = 0;
512 
513 		r = ipv4addr_filter_parse(&filter_master->filter_ipv4addr, charptr);
514 		if (r == 0) {
515 			token_used = 1;
516 		} else if (r == 2) {
517 			result = 1;
518 			ERRORPRINT_WA("Unrecognized filter token (ipv4.xxx): %s", charptr);
519 		};
520 
521 		r = ipv6addr_filter_parse(&filter_master->filter_ipv6addr, charptr);
522 		if (r == 0) {
523 			token_used = 1;
524 		} else if (r == 2) {
525 			result = 1;
526 			ERRORPRINT_WA("Unrecognized filter token (ipv6.xxx): %s", charptr);
527 		};
528 
529 		// r += macaddr_filter_parse(&filter_macaddr, charptr); // missing implementation
530 
531 		/* overall check */
532 		if ((token_used == 0) && (result != 1)) {
533 			result = 1;
534 			ERRORPRINT_WA("Unrecognized filter token (general): %s", charptr);
535 		};
536 
537 		charptr = strtok_r(NULL, ",", ptrptr);
538 	};
539 
540 	return (result);
541 };
542 
543 
544 /*
545  * function checks ipv6calc filter expression
546  *
547  * in: master filter structure
548  * ret: success
549  */
libipv6calc_filter_check(s_ipv6calc_filter_master * filter_master)550 int libipv6calc_filter_check(s_ipv6calc_filter_master *filter_master) {
551 	int result = 0, r;
552 
553 	DEBUGPRINT_NA(DEBUG_libipv6calc, "called");
554 
555 	r = ipv4addr_filter_check(&filter_master->filter_ipv4addr);
556 	if (r > 0) {
557 		result = 1;
558 	};
559 
560 	r = ipv6addr_filter_check(&filter_master->filter_ipv6addr);
561 	if (r > 0) {
562 		result = 1;
563 	};
564 
565 	if (result == 1) {
566 		ERRORPRINT_NA("filter check failed");
567 	};
568 
569 	return (result);
570 };
571 
572 
573 /*
574  * return proper anonymization set by name
575  *
576  * in : *name = name of anonymization set
577  *      *ipv6calc_anon_set = pointer to anonymization set to be filled
578  * return: 1=not found, 0=success
579  */
libipv6calc_anon_set_by_name(s_ipv6calc_anon_set * ipv6calc_anon_set,const char * name)580 int libipv6calc_anon_set_by_name(s_ipv6calc_anon_set *ipv6calc_anon_set, const char *name) {
581 	int i;
582 
583 	if (strlen(name) == 0) {
584 		fprintf(stderr, "Name of anonymization set is empty\n");
585 		return 1;
586 	};
587 
588 	DEBUGPRINT_WA(DEBUG_libipv6calc, "search for anonymization set with name: %s", name);
589 
590 	for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_anon_set_list); i++) {
591 		DEBUGPRINT_WA(DEBUG_libipv6calc, "compare name: %s ? %s", name, ipv6calc_anon_set_list[i].name);
592 
593 		if ((strcmp(name, ipv6calc_anon_set_list[i].name) == 0) || (strcmp(name, ipv6calc_anon_set_list[i].name_short) == 0)) {
594 			DEBUGPRINT_WA(DEBUG_libipv6calc, "hit name: %s = %s", name, ipv6calc_anon_set_list[i].name);
595 
596 			memcpy(ipv6calc_anon_set, &ipv6calc_anon_set_list[i], sizeof(s_ipv6calc_anon_set));
597 			return 0;
598 		};
599 	};
600 
601 	return 1;
602 };
603 
604 
605 /*
606  * get name of anonymization settings
607  *
608  * in : s_ipv6calc_anon_set = anonymization set
609  * return: char *
610  */
libipv6calc_anon_method_name(const s_ipv6calc_anon_set * ipv6calc_anon_set)611 const char *libipv6calc_anon_method_name(const s_ipv6calc_anon_set *ipv6calc_anon_set) {
612 	int i;
613 
614 	for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_anon_methods); i++) {
615 		if (ipv6calc_anon_methods[i].method == ipv6calc_anon_set->method) {
616 			return(ipv6calc_anon_methods[i].name);
617 			break;
618 		};
619 	};
620 
621 	return(NULL);
622 };
623 
624 
625 /*
626  * create string of anonymization settings
627  *
628  * in : *string = string to be filled
629  *      s_ipv6calc_anon_set = anonymization set
630  * return: void
631  */
libipv6calc_anon_infostring(char * string,const int stringlength,const s_ipv6calc_anon_set * ipv6calc_anon_set)632 void libipv6calc_anon_infostring(char *string, const int stringlength, const s_ipv6calc_anon_set *ipv6calc_anon_set) {
633 	const char *method_name = libipv6calc_anon_method_name(ipv6calc_anon_set);
634 
635 	snprintf(string, stringlength, "set=%s,mask-ipv6=%d,mask-ipv4=%d,mask-eui64=%d,mask-mac=%d,method=%s", ipv6calc_anon_set->name, ipv6calc_anon_set->mask_ipv6, ipv6calc_anon_set->mask_ipv4, ipv6calc_anon_set->mask_eui64, ipv6calc_anon_set->mask_mac, (method_name == NULL ? "unknown" : method_name));
636 
637 	return;
638 };
639 
640 
641 /*
642  * check whether anonymization method is supported
643  *
644  * in : s_ipv6calc_anon_set = anonymization set
645  * return:
646  *   2: special check succeeded
647  *   1: no special checks needed
648  *   0: not supported
649  */
libipv6calc_anon_supported(const s_ipv6calc_anon_set * ipv6calc_anon_set)650 int libipv6calc_anon_supported(const s_ipv6calc_anon_set *ipv6calc_anon_set) {
651 	/* check requirements */
652 	if (ipv6calc_anon_set->method == ANON_METHOD_KEEPTYPEASNCC) {
653 		// check for support
654 		if (libipv6calc_db_wrapper_has_features(ANON_METHOD_KEEPTYPEASNCC_IPV4_REQ_DB | ANON_METHOD_KEEPTYPEASNCC_IPV6_REQ_DB) == 1) {
655 			return(2);
656 		} else {
657 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_CC) != 1) {
658 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv4->CountryCode\n");
659 			};
660 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_CC) != 1) {
661 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv6->CountryCode\n");
662 			};
663 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_AS) != 1) {
664 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv4->AutonomousSystemNumber\n");
665 			};
666 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_AS) != 1) {
667 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv6->AutonomousSystemNumber\n");
668 			};
669 			return(0);
670 		};
671 	} else if (ipv6calc_anon_set->method == ANON_METHOD_KEEPTYPEGEONAMEID) {
672 		// check for support
673 		if (libipv6calc_db_wrapper_has_features(ANON_METHOD_KEEPTYPEGEONAMEID_IPV4_REQ_DB | ANON_METHOD_KEEPTYPEGEONAMEID_IPV6_REQ_DB) == 1) {
674 			return(2);
675 		} else {
676 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV4_TO_GEONAMEID) != 1) {
677 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv4->GeonameID\n");
678 			};
679 			if (libipv6calc_db_wrapper_has_features(IPV6CALC_DB_IPV6_TO_GEONAMEID) != 1) {
680 				fprintf(stderr, "ipv6calc anonymization method not supported, missing included/available database: IPv6->GeonameID\n");
681 			};
682 			return(0);
683 		};
684 	} else {
685 		return(1);
686 	};
687 };
688 
689 
690 /*
691  * return pointer to registry name by number
692  */
libipv6calc_registry_string_by_num(const int registry)693 const char *libipv6calc_registry_string_by_num(const int registry) {
694 	int j = -1, i;
695 
696 	DEBUGPRINT_WA(DEBUG_libipv6calc, "Called with registry=%d", registry);
697 
698 	for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_registries); i++ ) {
699 		if (ipv6calc_registries[i].number == registry) {
700 			j = i;
701 			break;
702 		};
703 	};
704 
705 	if (j == -1) {
706 		fprintf(stderr, "ERROR - undefined registry number: %d (this should not happen)\n", registry);
707 		exit(1);
708 	};
709 
710 	return(ipv6calc_registries[j].token);
711 };
712 
713 
714 /*
715  * bit counter
716  */
libipv6calc_bitcount_uint32_t(const uint32_t value)717 int libipv6calc_bitcount_uint32_t(const uint32_t value) {
718 	int i, count = 0;
719 	uint32_t mask = 0x1;
720 
721 	for (i = 0; i < 32; i++) {
722 		if (value & mask) {
723 			count++;
724 		};
725 		mask = mask << 1;
726 	};
727 	return(count);
728 };
729 
730 /*
731  * return library version numeric
732  */
libipv6calc_lib_version_numeric(void)733 uint32_t libipv6calc_lib_version_numeric(void) {
734 	return(IPV6CALC_PACKAGE_VERSION_NUMERIC);
735 };
736 
737 /*
738  * return library version as string
739  */
libipv6calc_lib_version_string(void)740 const char *libipv6calc_lib_version_string(void) {
741 	return(IPV6CALC_PACKAGE_VERSION_STRING);
742 
743 };
744 
745 /*
746  * return API version numeric
747  */
libipv6calc_api_version_numeric(void)748 uint32_t libipv6calc_api_version_numeric(void) {
749 	return(IPV6CALC_API_VERSION_NUMERIC);
750 };
751 
752 /*
753  * return API version as string
754  */
libipv6calc_api_version_string(void)755 const char *libipv6calc_api_version_string(void) {
756 	return(IPV6CALC_API_VERSION_STRING);
757 };
758