1 /*
2  * Project    : ipv6calc
3  * File       : ipv6calcoptions.c
4  * Version    : $Id: 7c34e1112400d80e1c4b82b3a272280eb1054a00 $
5  * Copyright  : 2013-2019 by Peter Bieringer <pb (at) bieringer.de>
6  *
7  * Information:
8  *  supporting common options
9  */
10 
11 #include <getopt.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "config.h"
16 #include "libipv6calc.h"
17 #include "libipv6calcdebug.h"
18 #include "ipv6calcoptions.h"
19 #include "ipv6calcoptions_common.h"
20 
21 #include "databases/lib/libipv6calc_db_wrapper.h"
22 
23 extern long int ipv6calc_debug; // ipv6calc_debug usage ok
24 int ipv6calc_quiet = 0;
25 int ipv6calc_verbose = 0;
26 
27 
28 /* parse value */
parse_dec_hex_val(const char * string)29 static long int parse_dec_hex_val(const char *string) {
30 	long int value;
31 
32 	if ((strlen(string) > 2) && ((strncmp(string, "0x", 2) == 0) || (strncmp(string, "0X", 2)) == 0)) {
33 		// convert hex
34 		if (sscanf(string + 2, "%lx", &value) == 0) {
35 			ipv6calc_debug = 0; // ipv6calc_debug usage ok
36 			ERRORPRINT_WA("can't parse value for debug option: %s", string);
37 		};
38 	} else {
39 		// convert dec
40 		if (sscanf(string, "%ld", &value) == 0) {
41 			ipv6calc_debug = 0; // ipv6calc_debug usage ok
42 			ERRORPRINT_WA("can't parse value for debug option: %s", string);
43 		};
44 	};
45 
46 	return(value);
47 };
48 
49 
50 /* bootstrap debug option from environment */
ipv6calc_debug_from_env(void)51 void ipv6calc_debug_from_env(void) {
52 	char *ipv6calc_debug_env;
53 	long int ipv6calc_debug_val;
54 
55         ipv6calc_debug_env = getenv("IPV6CALC_DEBUG");
56 
57 	if (ipv6calc_debug_env != NULL) {
58 		ERRORPRINT_WA("IPV6CALC_DEBUG found in environment: %s", ipv6calc_debug_env);
59 
60 		ipv6calc_debug_val = parse_dec_hex_val(ipv6calc_debug_env);
61 
62 		if (ipv6calc_debug_val != 0) {
63 			ipv6calc_debug = ipv6calc_debug_val; // ipv6calc_debug usage ok
64 			ERRORPRINT_WA("IPV6CALC_DEBUG proper parsed: %08lx", ipv6calc_debug); // ipv6calc_debug usage ok
65 		};
66 	};
67 };
68 
69 
70 /*
71  * add given options
72  * hard exit code in case of troubles: 2
73  */
ipv6calc_options_add(char * shortopts_p,const int shortopts_maxlen,struct option longopts[],int * maxentries_p,const char * shortopts_custom,const struct option longopts_custom[],const int longopts_custom_entries)74 void ipv6calc_options_add(char *shortopts_p, const int shortopts_maxlen, struct option longopts[], int *maxentries_p, const char *shortopts_custom, const struct option longopts_custom[], const int longopts_custom_entries) {
75 	int i, l;
76 	unsigned int j, k;
77 	char tempstring[IPV6CALC_STRING_MAX];
78 
79 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Called: longopts_custom_entries=%d shortopts=%s", longopts_custom_entries, shortopts_p);
80 
81 	if (*maxentries_p + longopts_custom_entries >= (IPV6CALC_MAXLONGOPTIONS - 1)) {
82 		fprintf(stderr, "FATAL error, can't add options - FIX CODE by increasing IPV6CALC_MAXLONGOPTIONS\n");
83 		exit(2);
84 	};
85 
86 	for (i = 0; i < longopts_custom_entries; i++) {
87 		/* check for duplicates */
88 		for (l = 0; l < *maxentries_p; l++) {
89 			if (strcmp(longopts[l].name, longopts_custom[i].name) == 0) {
90 				fprintf(stderr, "FATAL error, can't add options - DUPLICATE NAME FOUND: l=%d/%s i=%d/%s\n", l, longopts[l].name, i,  longopts_custom[i].name);
91 				exit(2);
92 			};
93 		};
94 
95 		DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Add long option on position %d/%d: %s", *maxentries_p, i, longopts_custom[i].name);
96 
97 		longopts[*maxentries_p] = longopts_custom[i];
98 		(*maxentries_p)++;
99 	};
100 
101 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Add short options: %s", shortopts_custom);
102 
103 	/* check for duplicates */
104 	if (strlen(shortopts_p) > 0) {
105 		DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Already given short options: %s", shortopts_p);
106 		for (j = 0; j < strlen(shortopts_p); j++) {
107 			for (k = 0; k < strlen(shortopts_custom); k++) {
108 				if (shortopts_custom[k] == ':') {
109 					continue;
110 				};
111 				if (shortopts_p[j] == shortopts_custom[k]) {
112 					fprintf(stderr, "FATAL error, can't add short options - DUPLICATE CHAR FOUND: %c\n", shortopts_p[j]);
113 					exit(2);
114 				};
115 			};
116 		};
117 	} else {
118 		DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Already given short options: (empty)");
119 	};
120 
121 	snprintf(tempstring, sizeof(tempstring), "%s%s", shortopts_p, shortopts_custom);
122 	snprintf(shortopts_p, shortopts_maxlen, "%s", tempstring);
123 
124 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Resulting short options: %s", shortopts_p);
125 
126 	// end of options
127 	longopts[*maxentries_p].name    = NULL;
128 	longopts[*maxentries_p].has_arg = 0;
129 	longopts[*maxentries_p].flag    = NULL;
130 	longopts[*maxentries_p].val     = 0;
131 
132 	/* TODO: implement strlen checks */
133 
134 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Return");
135 
136 	return;
137 };
138 
139 
140 /*
141  * add given options "common basic"
142  */
ipv6calc_options_add_common_basic(char * shortopts_p,const int shortopts_maxlen,struct option longopts[],int * maxentries_p)143 void ipv6calc_options_add_common_basic(char *shortopts_p, const int shortopts_maxlen, struct option longopts[], int *maxentries_p) {
144 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Called");
145 
146 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_common, ipv6calc_longopts_common, MAXENTRIES_ARRAY(ipv6calc_longopts_common));
147 
148 #ifdef SUPPORT_MMDB
149 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_MMDB");
150 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_mmdb, ipv6calc_longopts_mmdb, MAXENTRIES_ARRAY(ipv6calc_longopts_mmdb));
151 #endif
152 
153 #ifdef SUPPORT_IP2LOCATION
154 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_IP2LOCATION");
155 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_ip2location, ipv6calc_longopts_ip2location, MAXENTRIES_ARRAY(ipv6calc_longopts_ip2location));
156 #endif
157 
158 #ifdef SUPPORT_GEOIP2
159 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_GEOIP2");
160 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_geoip2, ipv6calc_longopts_geoip2, MAXENTRIES_ARRAY(ipv6calc_longopts_geoip2));
161 #endif
162 
163 #ifdef SUPPORT_DBIP2
164 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_DBIP2");
165 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_dbip2, ipv6calc_longopts_dbip2, MAXENTRIES_ARRAY(ipv6calc_longopts_dbip2));
166 #endif
167 
168 #ifdef SUPPORT_EXTERNAL
169 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_EXTERNAL");
170 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_external, ipv6calc_longopts_external, MAXENTRIES_ARRAY(ipv6calc_longopts_external));
171 #endif
172 
173 #ifdef SUPPORT_BUILTIN
174 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "SUPPORT_BUILTIN");
175 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_builtin, ipv6calc_longopts_builtin, MAXENTRIES_ARRAY(ipv6calc_longopts_builtin));
176 #endif
177 
178 #if defined SUPPORT_EXTERNAL || SUPPORT_IP2LOCATION || defined SUPPORT_DBIP2 || defined SUPPORT_GEOIP2
179 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "DB_COMMON");
180 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_db_common, ipv6calc_longopts_db_common, MAXENTRIES_ARRAY(ipv6calc_longopts_db_common));
181 #endif
182 
183 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Finished");
184 };
185 
186 
187 /*
188  * add given options "common anon"
189  */
ipv6calc_options_add_common_anon(char * shortopts_p,const int shortopts_maxlen,struct option longopts[],int * maxentries_p)190 void ipv6calc_options_add_common_anon(char *shortopts_p, const int shortopts_maxlen, struct option longopts[], int *maxentries_p) {
191 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Called");
192 
193 	ipv6calc_options_add(shortopts_p, shortopts_maxlen, longopts, maxentries_p, ipv6calc_shortopts_common_anon, ipv6calc_longopts_common_anon, MAXENTRIES_ARRAY(ipv6calc_longopts_common_anon));
194 
195 	DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Finished");
196 };
197 
198 
199 /*
200  * call option handler "common basic"
201  * return: 0: option found
202  */
ipv6calcoptions_common_basic(const int opt,const char * optarg,const struct option longopts[])203 int ipv6calcoptions_common_basic(const int opt, const char *optarg, const struct option longopts[]) {
204 	int result = -1;
205 
206 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Called opt=0x%08x", opt);
207 
208 	/* general options */
209 	switch(opt) {
210 		case OPTION_NOOP:
211 			DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Found dummy option, skip");
212 			result = 0;
213 			break;
214 
215 		case 'd':
216 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Found debug option with value: %s", optarg);
217 			ipv6calc_debug = parse_dec_hex_val(optarg);
218 			ERRORPRINT_WA("given debug value: %lx", ipv6calc_debug);
219 			result = 0;
220 			break;
221 
222 		case 'q':
223 			DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Found quiet option");
224 			ipv6calc_quiet = 1;
225 			result = 0;
226 			break;
227 
228 		case 'V':
229 			DEBUGPRINT_NA(DEBUG_ipv6calcoptions, "Found verbose option");
230 			ipv6calc_verbose++;
231 			ipv6calc_quiet = 0;
232 			result = 0;
233 			break;
234 
235 		default:
236 			/* jump to other parsers */
237 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Call sub-parser for opt=0x%08x", opt);
238 
239 			result = libipv6calc_db_wrapper_options(opt, optarg, longopts);
240 	};
241 
242 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Return with result: %d", result);
243 
244 	return(result);
245 };
246 
247 
248 /*
249  * call option handler "common anon"
250  * return: 0: option found
251  */
ipv6calcoptions_common_anon(const int opt,const char * optarg,const struct option longopts[],s_ipv6calc_anon_set * ipv6calc_anon_set_p)252 int ipv6calcoptions_common_anon(const int opt, const char *optarg, const struct option longopts[], s_ipv6calc_anon_set *ipv6calc_anon_set_p) {
253 	int result = -1, i;
254 	int mask_ipv4;
255 	int mask_ipv6;
256 	int mask_eui64;
257 	int mask_mac;
258 
259 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Called opt=0x%08x", opt);
260 
261 	if (sizeof (*longopts) == 0) { }; // make compiler happy (avoid unused "...")
262 
263 	/* general options */
264 	switch(opt) {
265 		case CMD_ANON_MASK_AUTOADJUST:
266 			if (strcmp(optarg, "yes") == 0) {
267 				i = 1;
268 			} else if (strcmp(optarg, "no") == 0) {
269 				i = 0;
270 			} else {
271 				fprintf(stderr, " unsupported  value for option 'mask-autoadjust', only yes|no is supported\n");
272 				exit(EXIT_FAILURE);
273 			};
274 			if (ipv6calc_anon_set_p->mask_autoadjust != i) {
275 				ipv6calc_anon_set_p->mask_autoadjust = i;
276 				snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
277 			};
278 			result = 0;
279 			break;
280 
281 		case CMD_ANON_MASK_IID:
282 		case CMD_ANON_MASK_EUI64:
283 			if (opt == CMD_ANON_MASK_IID) {
284 				fprintf(stderr, " option 'mask-iid' is deprecated, please use 'mask-eui64'\n");
285 			};
286 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Found option: mask-eui=%s", optarg);
287 			mask_eui64 = atoi(optarg);
288 			if (mask_eui64 < 0 || mask_eui64 > 64) {
289 				fprintf(stderr, " value for option 'mask-eui64' out-of-range  [0-64]\n");
290 				exit(EXIT_FAILURE);
291 			};
292 
293 			if (ipv6calc_anon_set_p->mask_eui64 != mask_eui64) {
294 				ipv6calc_anon_set_p->mask_eui64 = mask_eui64;
295 				snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
296 			};
297 			result = 0;
298 			break;
299 
300 		case CMD_ANON_MASK_IPV4:
301 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Found option: mask-ipv4=%s", optarg);
302 			mask_ipv4 = atoi(optarg);
303 			if (mask_ipv4 < 0 || mask_ipv4 > 32) {
304 				fprintf(stderr, " value for option 'mask-ipv4' out-of-range  [0-32]\n");
305 				exit(EXIT_FAILURE);
306 			};
307 
308 			if (ipv6calc_anon_set_p->mask_ipv4 != mask_ipv4) {
309 				ipv6calc_anon_set_p->mask_ipv4 = mask_ipv4;
310 				snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
311 			};
312 			result = 0;
313 			break;
314 
315 		case CMD_ANON_MASK_IPV6:
316 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Found option: mask-ipv6=%s", optarg);
317 			mask_ipv6 = atoi(optarg);
318 			if (mask_ipv6 < 0 || mask_ipv6 > 64) {
319 				fprintf(stderr, " value for option 'mask-ipv6' out-of-range  [0-64]\n");
320 				exit(EXIT_FAILURE);
321 			};
322 
323 			if (ipv6calc_anon_set_p->mask_ipv6 != mask_ipv6) {
324 				ipv6calc_anon_set_p->mask_ipv6 = mask_ipv6;
325 				snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
326 			};
327 			result = 0;
328 			break;
329 
330 		case CMD_ANON_MASK_MAC:
331 			mask_mac = atoi(optarg);
332 			if (mask_mac < 0 || mask_mac > 48) {
333 				fprintf(stderr, " value for option 'mask-mac' out-of-range  [0-48]\n");
334 				exit(EXIT_FAILURE);
335 			};
336 
337 			if (ipv6calc_anon_set_p->mask_mac != mask_mac) {
338 				ipv6calc_anon_set_p->mask_mac = mask_mac;
339 				snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
340 			};
341 			result = 0;
342 			break;
343 
344 		case CMD_ANON_PRESET_STANDARD:
345 			result = libipv6calc_anon_set_by_name(ipv6calc_anon_set_p, "as");
346 			if (result != 0) {
347 				fprintf(stderr, "ipv6calc anonymization preset not found: anonymize-standard\n");
348 				exit(EXIT_FAILURE);
349 			};
350 			break;
351 
352 		case CMD_ANON_PRESET_CAREFUL:
353 			result = libipv6calc_anon_set_by_name(ipv6calc_anon_set_p, "ac");
354 			if (result != 0) {
355 				fprintf(stderr, "ipv6calc anonymization preset not found: anonymize-careful\n");
356 				exit(EXIT_FAILURE);
357 			};
358 			result = 0;
359 			break;
360 
361 		case CMD_ANON_PRESET_PARANOID:
362 			result = libipv6calc_anon_set_by_name(ipv6calc_anon_set_p, "ap");
363 			if (result != 0) {
364 				fprintf(stderr, "ipv6calc anonymization preset not found: anonymize-paranoid\n");
365 				exit(EXIT_FAILURE);
366 			};
367 			result = 0;
368 			break;
369 
370 		case CMD_ANON_PRESET_OPTION:
371 			result = libipv6calc_anon_set_by_name(ipv6calc_anon_set_p, optarg);
372 			if (result != 0) {
373 				fprintf(stderr, "ipv6calc anonymization preset not found: %s\n", optarg);
374 				exit(EXIT_FAILURE);
375 			};
376 			result = 0;
377 			break;
378 
379 		case CMD_ANON_METHOD_OPTION:
380 			for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_anon_methods); i++) {
381 				if (strcmp(ipv6calc_anon_methods[i].name, optarg) == 0) {
382 					ipv6calc_anon_set_p->method = ipv6calc_anon_methods[i].method;
383 					snprintf(ipv6calc_anon_set_p->name, sizeof(ipv6calc_anon_set_p->name), "%s", "custom");
384 					break;
385 				};
386 			};
387 
388 			if (i == MAXENTRIES_ARRAY(ipv6calc_anon_methods)) {
389 				fprintf(stderr, "anonymization method not supported: %s\n", optarg);
390 				exit(EXIT_FAILURE);
391 			};
392 			result = 0;
393 			break;
394 	};
395 
396 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Return with result: %d", result);
397 
398 	return(result);
399 };
400 
401 
402 /* get option name for an option
403  * in : opt
404  * ret: char* to string
405  */
ipv6calcoption_name(const int opt,const struct option longopts[])406 const char *ipv6calcoption_name(const int opt, const struct option longopts[]) {
407 	int i = 0;
408 
409 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Called opt=%d", opt);
410 
411 	while (longopts[i].name != NULL) {
412 		if (opt == longopts[i].val) {
413 			return(longopts[i].name);
414 		};
415 		i++;
416 	};
417 
418 	return("UNKNOWN");
419 };
420 
421 
422 /* get common options from environment */
ipv6calc_common_options_from_env(const struct option longopts[],s_ipv6calc_anon_set * ipv6calc_anon_set_p)423 void ipv6calc_common_options_from_env(const struct option longopts[], s_ipv6calc_anon_set *ipv6calc_anon_set_p) {
424 	int i, result;
425 	unsigned int s;
426 	char tempstring[IPV6CALC_STRING_MAX];
427 	char *environment_value;
428 
429 	i = 0;
430 	while(longopts[i].name != NULL) {
431 		// convert long option name to environment name
432 		snprintf(tempstring, sizeof(tempstring), "IPV6CALC_%s", longopts[i].name);
433 		for (s = 0; s < strlen(tempstring); s++) {
434 			switch(tempstring[s]) {
435 			    case '-':
436 				tempstring[s] = '_';
437 				break;
438 
439 			    default:
440 				tempstring[s] = toupper(tempstring[s]);
441 				break;
442 			};
443 		};
444 
445 		DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Long option: %s/%d/%08x env=%s", longopts[i].name, longopts[i].has_arg, longopts[i].val, tempstring);
446 
447 		environment_value = getenv(tempstring);
448 
449 		if (environment_value != NULL) {
450 			DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "found in environment: %s=%s (%08x)", tempstring, environment_value, longopts[i].val);
451 
452 			if (longopts[i].has_arg == 0) {
453 				if (
454 				       (strcasecmp(environment_value, "no") == 0)
455 				    || (strcasecmp(environment_value, "off") == 0)
456 				    || (strcasecmp(environment_value, "0") == 0)
457 				) {
458 					goto NEXT_in_environment;
459 					// skip
460 				};
461 
462 				if (
463 				       (strcasecmp(environment_value, "yes") != 0)
464 				    && (strcasecmp(environment_value, "on") != 0)
465 				    && (strcasecmp(environment_value, "1") != 0)
466 				) {
467 					fprintf(stderr, "value for environment can only be yes|on|1 or no|off|0: %s=%s\n", tempstring, environment_value);
468 					exit(EXIT_FAILURE);
469 				};
470 			};
471 
472 			result = ipv6calcoptions_common_basic(longopts[i].val, environment_value, longopts);
473 			if (result == 0) {
474 				// found
475 				goto NEXT_in_environment;
476 			};
477 
478 			if (ipv6calc_anon_set_p != NULL) {
479 				result = ipv6calcoptions_common_anon(longopts[i].val, environment_value, longopts, ipv6calc_anon_set_p);
480 				if (result == 0) {
481 					// found
482 					goto NEXT_in_environment;
483 				};
484 			};
485 		};
486 NEXT_in_environment:
487 		i++;
488 	};
489 };
490 
491 
492 /*
493  * set a particular (common) option by name/value
494  * in : longopts, name, value, ipv6calc_anon_set_p
495  * out: 0: found/set  <>0: not found
496  */
ipv6calc_set_option(const struct option longopts[],const char * name,const char * value,s_ipv6calc_anon_set * ipv6calc_anon_set_p)497 int ipv6calc_set_option(const struct option longopts[], const char *name, const char *value, s_ipv6calc_anon_set *ipv6calc_anon_set_p) {
498 	int i, result = -1;
499 
500 	DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "called with option: %s=%s", name, value);
501 
502 	i = 0;
503 	while(longopts[i].name != NULL) {
504 		DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "check option: %s/%d/%08x", longopts[i].name, longopts[i].has_arg, longopts[i].val);
505 
506 		if (strcmp(name, longopts[i].name) != 0) {
507 			// no match
508 			goto NEXT_option;
509 		};
510 
511 		DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "found option: %s=%s (%08x)", longopts[i].name, value, longopts[i].val);
512 
513 		if ((longopts[i].has_arg == 0) && (value != NULL)) {
514 			// check value of toggle
515 			if (
516 			       (strcasecmp(value, "no") == 0)
517 			    || (strcasecmp(value, "off") == 0)
518 			    || (strcasecmp(value, "0") == 0)
519 			) {
520 				// skip
521 				break;
522 			};
523 
524 			if (
525 			       (strcasecmp(value, "yes") != 0)
526 			    && (strcasecmp(value, "on") != 0)
527 			    && (strcasecmp(value, "1") != 0)
528 			) {
529 				fprintf(stderr, "value for option can only be yes|on|1 or no|off|0: %s=%s\n", longopts[i].name, value);
530 				exit(EXIT_FAILURE);
531 			};
532 		};
533 
534 		result = ipv6calcoptions_common_basic(longopts[i].val, value, longopts);
535 		if (result == 0) {
536 			// found
537 			break;
538 		};
539 
540 		if (ipv6calc_anon_set_p != NULL) {
541 			result = ipv6calcoptions_common_anon(longopts[i].val, value, longopts, ipv6calc_anon_set_p);
542 			if (result == 0) {
543 				// found
544 				break;
545 			};
546 		};
547 NEXT_option:
548 		i++;
549 	};
550 
551 	return(result);
552 };
553