1 /*
2 * Project : ipv6calc
3 * File : ipv6calchelp.c
4 * Version : $Id: 50128046d35b1cc796bdc470c9c6cacaa87940bd $
5 * Copyright : 2002-2020 by Peter Bieringer <pb (at) bieringer.de>
6 *
7 * Information:
8 * Help library
9 */
10
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include "libipv6calc.h"
15 #include "libipv6calcdebug.h"
16 #include "ipv6calctypes.h"
17 #include "ipv6calcoptions.h"
18 #include "ipv6calchelp.h"
19 #include "config.h"
20
21 #include "libieee.h"
22 #include "databases/lib/libipv6calc_db_wrapper.h"
23 #include "databases/lib/libipv6calc_db_wrapper_GeoIP2.h"
24 #include "databases/lib/libipv6calc_db_wrapper_IP2Location.h"
25 #include "databases/lib/libipv6calc_db_wrapper_DBIP2.h"
26 #include "databases/lib/libipv6calc_db_wrapper_BuiltIn.h"
27 #include "databases/lib/libipv6calc_db_wrapper_External.h"
28
29
30 /* to be defined in each application */
31 extern void printversion(void);
32 extern void printcopyright(void);
33
34
35 /* format option arguments */
printhelp_print(void)36 void printhelp_print(void) {
37 fprintf(stderr, " --printprefix : print only prefix of IPv6 address\n");
38 fprintf(stderr, " --printsuffix : print only suffix of IPv6 address\n");
39 };
40
printhelp_mask(void)41 void printhelp_mask(void) {
42 fprintf(stderr, " --maskprefix : mask IPv6 address with prefix length (clears suffix bits)\n");
43 fprintf(stderr, " --masksuffix : mask IPv6 address with suffix length (clears prefix bits)\n");
44 };
45
printhelp_case(void)46 void printhelp_case(void) {
47 fprintf(stderr, " --uppercase|-u : print chars of IPv6 address in upper case\n");
48 fprintf(stderr, " --lowercase|-l : print chars of IPv6 address in lower case [default]\n");
49 };
50
printhelp_printstartend(void)51 void printhelp_printstartend(void) {
52 fprintf(stderr, " --printstart <1-128> : print part of IPv6 address start from given number\n");
53 fprintf(stderr, " --printend <1-128> : print part of IPv6 address end at given number\n");
54 };
55
printhelp_doublecommands(void)56 void printhelp_doublecommands(void) {
57 printversion();
58 printcopyright();
59 fprintf(stderr, " Only one command may be specified!\n");
60 };
61
printhelp_missinginputdata(void)62 void printhelp_missinginputdata(void) {
63 printversion();
64 printcopyright();
65 fprintf(stderr, " Missing or too few input data given!\n");
66 };
67
68 /* list of input types */
printhelp_inputtypes(const uint32_t formatoptions)69 void printhelp_inputtypes(const uint32_t formatoptions) {
70 int i, j;
71 size_t maxlen = 0;
72 char printformatstring[20];
73
74 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
75 printversion();
76 printcopyright();
77 };
78
79 /* look for longest type definition */
80 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_formatstrings); j++) {
81 if (strlen(ipv6calc_formatstrings[j].token) > maxlen) {
82 maxlen = strlen(ipv6calc_formatstrings[j].token);
83 };
84 };
85
86 if (maxlen > 999) {
87 fprintf(stderr, " Something going wrong with array 'ipv6calc_formatstrings'!\n");
88 exit(EXIT_FAILURE);
89 };
90
91 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
92 snprintf(printformatstring, sizeof(printformatstring), " %%-%ds : %%s\n", (int) maxlen);
93 } else {
94 snprintf(printformatstring, sizeof(printformatstring), "%%-%ds\n", (int) maxlen);
95 }
96
97 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Format string: %s", printformatstring);
98
99 if ((formatoptions & FORMATOPTION_machinereadable) == 0) fprintf(stderr, "\n Available input types:\n");
100
101 /* run through matrix */
102 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_formatmatrix); i++) {
103 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Row %d: %08x - %08x", i, (unsigned int) ipv6calc_formatmatrix[i][0], (unsigned int) ipv6calc_formatmatrix[i][1]);
104 if (ipv6calc_formatmatrix[i][1] != 0) {
105 /* available for input, look for name now */
106 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_formatstrings); j++) {
107 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Format-Row %d: %08x - %s - %s", j, (unsigned int) ipv6calc_formatstrings[j].number, ipv6calc_formatstrings[j].token, ipv6calc_formatstrings[j].explanation);
108 if (ipv6calc_formatstrings[j].number == ipv6calc_formatmatrix[i][0]) {
109 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
110 fprintf(stderr, printformatstring, ipv6calc_formatstrings[j].token, ipv6calc_formatstrings[j].explanation);
111 } else {
112 fprintf(stdout, printformatstring, ipv6calc_formatstrings[j].token);
113 };
114 };
115 };
116 };
117 };
118
119 if ((formatoptions & FORMATOPTION_machinereadable) == 0) fprintf(stderr, "\n");
120 };
121
122
123 /* list of output types */
printhelp_outputtypes(const uint32_t inputtype,const uint32_t formatoptions)124 void printhelp_outputtypes(const uint32_t inputtype, const uint32_t formatoptions) {
125 int i, j;
126 size_t maxlen = 0;
127 char printformatstring[20];
128
129 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
130 printversion();
131 printcopyright();
132 };
133
134 /* look for longest type definition */
135 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_formatstrings); j++) {
136 if (strlen(ipv6calc_formatstrings[j].token) > maxlen) {
137 maxlen = strlen(ipv6calc_formatstrings[j].token);
138 };
139 };
140
141 if (maxlen > 999) {
142 fprintf(stderr, " Something going wrong with array 'ipv6calc_formatstrings'!\n");
143 exit(EXIT_FAILURE);
144 };
145
146 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
147 snprintf(printformatstring, sizeof(printformatstring), " %%-%ds : %%s\n", (int) maxlen);
148 } else {
149 snprintf(printformatstring, sizeof(printformatstring), "%%-%ds\n", (int) maxlen);
150 };
151
152 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Format string: %s", printformatstring);
153
154 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
155 if ( (inputtype & ~ (FORMAT_auto | FORMAT_any) ) != 0 ) {
156 fprintf(stderr, "\n Available output types filtered by input type:\n");
157 } else {
158 fprintf(stderr, "\n Available output types:\n");
159 };
160 };
161
162 /* run through matrix */
163 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_formatstrings); j++) {
164 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Format-Row %d: %08x - %s - %s", j, (unsigned int) ipv6calc_formatstrings[j].number, ipv6calc_formatstrings[j].token, ipv6calc_formatstrings[j].explanation);
165
166 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_formatmatrix); i++) {
167 if ( (inputtype & ~ (FORMAT_auto | FORMAT_any) ) != 0 ) {
168 if (ipv6calc_formatmatrix[i][0] != inputtype) {
169 /* skip */
170 continue;
171 };
172 };
173
174 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Row %d: %08x - %08x", i, (unsigned int) ipv6calc_formatmatrix[i][0], (unsigned int) ipv6calc_formatmatrix[i][1]);
175
176 if ((ipv6calc_formatmatrix[i][1] & ipv6calc_formatstrings[j].number) != 0) {
177 /* available for output, look for name now */
178 if (strlen(ipv6calc_formatstrings[j].explanation) > 0) {
179 fprintf(stderr, printformatstring, ipv6calc_formatstrings[j].token, ipv6calc_formatstrings[j].explanation);
180 } else {
181 fprintf(stdout, printformatstring, ipv6calc_formatstrings[j].token, "(empty)");
182 };
183 break;
184 };
185 };
186 };
187
188 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
189 fprintf(stderr, "\n For examples and available format options use:\n");
190 fprintf(stderr, " -O|--out <type> --examples\n");
191 fprintf(stderr, "\n");
192 };
193 };
194
195
196 /* list of action types */
printhelp_actiontypes(const uint32_t formatoptions,const struct option longopts[])197 void printhelp_actiontypes(const uint32_t formatoptions, const struct option longopts[]) {
198 int i, j, o, test, has_options;
199 size_t maxlen = 0;
200 char printformatstring[20], printformatstring2[20], printformatstring3[20];
201
202 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
203 printversion();
204 printcopyright();
205 };
206
207 /* look for longest type definition */
208 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_actionstrings); j++) {
209 if (strlen(ipv6calc_actionstrings[j].token) > maxlen) {
210 maxlen = strlen(ipv6calc_actionstrings[j].token);
211 };
212 };
213
214 if (maxlen > 999) {
215 fprintf(stderr, " Something going wrong with array 'ipv6calc_actionstrings'!\n");
216 exit (EXIT_FAILURE);
217 };
218
219 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
220 snprintf(printformatstring, sizeof(printformatstring), " %%-%ds : %%s\n", (int) maxlen);
221 } else {
222 snprintf(printformatstring, sizeof(printformatstring), "%%-%ds\n", (int) maxlen);
223 };
224
225 snprintf(printformatstring2, sizeof(printformatstring2), " %%-%ds%%s\n", (int) maxlen + 4);
226 snprintf(printformatstring3, sizeof(printformatstring3), " %%-%ds--%%s", (int) maxlen + 5);
227
228 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Action string: %s", printformatstring);
229
230 if ((formatoptions & FORMATOPTION_machinereadable) == 0) fprintf(stderr, "\n Available action types:\n");
231
232 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_actionstrings); j++) {
233 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Action-Row %d: %08x - %s - %s", j, (unsigned int) ipv6calc_actionstrings[j].number, ipv6calc_actionstrings[j].token, ipv6calc_actionstrings[j].explanation);
234
235 if ((formatoptions & FORMATOPTION_machinereadable) == 0) {
236 fprintf(stderr, printformatstring, ipv6calc_actionstrings[j].token, ipv6calc_actionstrings[j].explanation);
237
238 test = 2;
239 has_options = 0;
240 while (test != 0) {
241 if (test == 1) {
242 fprintf(stderr, printformatstring2, "", "Options:");
243 };
244
245 /* search for defined options */
246 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_actionoptionmap); i++) {
247 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Option %d", i)
248
249 if (ipv6calc_actionstrings[j].number == ipv6calc_actionoptionmap[i][0]) {
250 if (ipv6calc_actionoptionmap[i][1] == 0) {
251 /* no options supported */
252 break;
253 };
254
255 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Option value: %08x", (unsigned int) ipv6calc_actionoptionmap[i][1]);
256
257 /* run through options */
258 o = 0;
259 while(longopts[o].name != NULL) {
260 if ((ipv6calc_actionoptionmap[i][1] == (uint32_t) longopts[o].val)) {
261 has_options = 1;
262 if (test == 1) {
263 fprintf(stderr, printformatstring3, "", longopts[o].name);
264 if (longopts[o].has_arg > 0) {
265 fprintf(stderr, " ...");
266 };
267 if (ipv6calc_actionoptionmap[i][2] > 0) {
268 fprintf(stderr, " (optional)");
269 } else {
270 fprintf(stderr, " (required)");
271 };
272 fprintf(stderr, "\n");
273 };
274 };
275 o++;
276 };
277 };
278 };
279 if (has_options == 0) {
280 break;
281 };
282 test--;
283 };
284 } else {
285 fprintf(stdout, printformatstring, ipv6calc_actionstrings[j].token);
286 };
287 };
288 if ((formatoptions & FORMATOPTION_machinereadable) == 0) fprintf(stderr, "\n");
289 };
290
291
292 /* print global common help */
printhelp_common(const uint32_t help_features)293 void printhelp_common(const uint32_t help_features) {
294 fprintf(stderr, "\n");
295
296 fprintf(stderr, " [-d|--debug <debug value>] : debug value (bitwise like)\n");
297 fprintf(stderr, " can also be set by IPV6CALC_DEBUG environment value\n");
298 fprintf(stderr, " [-v|--version [-v [-v]]] : version information (2 optional detail levels)\n");
299 fprintf(stderr, " [-v|--version -h] : explanation of feature tokens\n");
300 fprintf(stderr, " [-V|--verbose] : be more verbose\n");
301 fprintf(stderr, " [-h|--help|-?] : this online help\n");
302
303 if ((help_features & IPV6CALC_HELP_QUIET) != 0) {
304 fprintf(stderr, " [-q|--quiet] : be more quiet\n");
305 };
306
307 if ((help_features & IPV6CALC_HELP_IP2LOCATION) != 0) {
308 #ifdef SUPPORT_IP2LOCATION
309 fprintf(stderr, "\n");
310 fprintf(stderr, " [--disable-ip2location ] : IP2Location support disabled\n");
311 fprintf(stderr, " [--db-ip2location-disable ] : IP2Location support disabled\n");
312 fprintf(stderr, " [--db-ip2location-dir <directory>] : IP2Location database directory (default: %s)\n", ip2location_db_dir);
313 #ifdef SUPPORT_IP2LOCATION_DYN
314 fprintf(stderr, " [--db-ip2location-lib <file> ] : IP2Location library file (default: %s)\n", ip2location_lib_file);
315 #endif
316 fprintf(stderr, " [--db-ip2location-only-type <TYPE>]: IP2Location database only selected type (1-%d)\n", IP2LOCATION_DB_MAX);
317 fprintf(stderr, " [--db-ip2location-allow-softlinks] : IP2Location database softlinks allowed\n");
318 fprintf(stderr, " by default they are ignored because it is hard to autodetect COMM/LITE/SAMPLE\n");
319 fprintf(stderr, " [--db-ip2location-lite-to-sample-autoswitch-max-delta-months <MONTHS>]:\n");
320 fprintf(stderr, " autoswitch from LITE to SAMPLE databases if possible and delta is not more than %d months (0=disabled)\n", ip2location_db_lite_to_sample_autoswitch_max_delta_months);
321 fprintf(stderr, " [--db-ip2location-comm-to-lite-switch-min-delta-months <MONTHS>]:\n");
322 fprintf(stderr, " switch from COMM to LITE databases if possible and delta more than %d months (0=disabled)\n", ip2location_db_comm_to_lite_switch_min_delta_months);
323 #endif
324 };
325
326 if ((help_features & IPV6CALC_HELP_GEOIP) != 0) {
327 #ifdef SUPPORT_GEOIP
328 fprintf(stderr, "\n");
329 fprintf(stderr, " [--disable-geoip ] : GeoIP support disabled\n");
330 fprintf(stderr, " [--db-geoip-disable ] : GeoIP support disabled\n");
331 fprintf(stderr, " [--db-geoip-dir <directory>] : GeoIP database directory (default: %s)\n", geoip_db_dir);
332 #ifdef SUPPORT_GEOIP_DYN
333 fprintf(stderr, " [--db-geoip-lib <file> ] : GeoIP library file (default: %s)\n", geoip_lib_file);
334 #endif
335 #endif
336 };
337
338 if ((help_features & IPV6CALC_HELP_MMDB) != 0) {
339 #ifdef SUPPORT_MMDB_DYN
340 fprintf(stderr, "\n");
341 fprintf(stderr, " [--db-mmdb-lib <file> ] : MaxMindDB library file (default: %s)\n", mmdb_lib_file);
342 #endif
343
344 #ifdef SUPPORT_GEOIP2
345 fprintf(stderr, "\n");
346 fprintf(stderr, " [--disable-geoip2 ] : GeoIP(MaxMindDB) support disabled\n");
347 fprintf(stderr, " [--db-geoip2-disable ] : GeoIP(MaxMindDB) support disabled\n");
348 fprintf(stderr, " [--db-geoip2-dir <directory>] : GeoIP(MaxMindDB) database directory (default: %s)\n", geoip2_db_dir);
349 #endif
350
351 #ifdef SUPPORT_DBIP2
352 fprintf(stderr, "\n");
353 fprintf(stderr, " [--disable-dbip2 ] : db-ip.com(MaxMindDB) support disabled\n");
354 fprintf(stderr, " [--db-dbip2-disable ] : db-ip.com(MaxMindDB) support disabled\n");
355 fprintf(stderr, " [--db-dbip2-dir <directory>] : db-ip.com(MaxMindDB) database directory (default: %s)\n", dbip2_db_dir);
356 fprintf(stderr, " [--db-dbip2-only-type <TYPE>] : db-ip.com(MaxMindDB) database only selected type (1-%d)\n", DBIP2_DB_MAX);
357 fprintf(stderr, " [--db-dbip2-comm-to-free-switch-min-delta-months <MONTHS>]:\n");
358 fprintf(stderr, " switch from COMM to FREE databases if possible and delta more than %d months (0=disabled)\n", dbip2_db_comm_to_free_switch_min_delta_months);
359 #endif
360 };
361
362 if ((help_features & IPV6CALC_HELP_EXTERNAL) != 0) {
363 #ifdef SUPPORT_EXTERNAL
364 fprintf(stderr, "\n");
365 fprintf(stderr, " [--disable-external ] : External support disabled\n");
366 fprintf(stderr, " [--db-external-disable ] : External support disabled\n");
367 fprintf(stderr, " [--db-external-dir <directory>] : External database directory (default: %s)\n", external_db_dir);
368 #endif
369 };
370
371 if ((help_features & IPV6CALC_HELP_BUILTIN) != 0) {
372 #ifdef SUPPORT_BUILTIN
373 fprintf(stderr, "\n");
374 fprintf(stderr, " [--disable-builtin ] : BuiltIn support disabled\n");
375 fprintf(stderr, " [--db-builtin-disable ] : BuiltIn support disabled\n");
376 #endif
377
378 #if defined SUPPORT_EXTERNAL || defined SUPPORT_DBIP2 || defined SUPPORT_GEOIP2 || SUPPORT_IP2LOCATION
379 fprintf(stderr, "\n");
380 fprintf(stderr, " [--db-priorization <entry1>[:...]] : Database priorization order list (overwrites default)\n");
381 fprintf(stderr, " colon separated:");
382 int i;
383 for (i = 0; i < MAXENTRIES_ARRAY(data_sources); i++) {
384 fprintf(stderr, " %s", data_sources[i].shortname);
385 };
386 fprintf(stderr, "\n");
387 #endif
388 };
389
390 fprintf(stderr, "\n");
391 fprintf(stderr, " Hint: all long options can be predefined from environment by using\n");
392 fprintf(stderr, " prefix: IPV6CALC_ and conversion: '-' -> '_' and lowercase -> uppercase\n");
393 fprintf(stderr, " example for options with values : --db-dbip2-dir=<DIR> -> environment: IPV6CALC_DB_DBIP2_DIR=<DIR>\n");
394 fprintf(stderr, " example for options without values: --db-dbip2-disable -> environment: IPV6CALC_DB_DBIP2_DISABLE=1\n");
395 fprintf(stderr, " on|off|0|1 is supported\n");
396
397 fprintf(stderr, "\n");
398 return;
399 };
400
printhelp_shortcut_options(const struct option longopts[],const s_ipv6calc_longopts_shortopts_map longopts_shortopts_map[])401 void printhelp_shortcut_options(const struct option longopts[], const s_ipv6calc_longopts_shortopts_map longopts_shortopts_map[]) {
402 int i = 0;
403 int j;
404 char c;
405 const char *info;
406
407 fprintf(stderr, "\n");
408 fprintf(stderr, " Usage with shortcut options: <shortcut option> [<format option> ...] <input data>\n");
409 fprintf(stderr, " for more information and available format options use: <shortcut option> -?|-h|--help\n");
410 fprintf(stderr, "\n");
411
412 while(longopts[i].name != NULL) {
413 if (longopts[i].val >= CMD_shortcut_start && longopts[i].val <= CMD_shortcut_end) {
414 c = '\0';
415 info = NULL;
416
417 if (longopts_shortopts_map != NULL) {
418 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Search in longopts_shortopts_map for %08x", longopts[i].val);
419 j = 0;
420 while (longopts_shortopts_map[j].val > 0) {
421 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Check against longopts_shortopts_map entry %d:%08x", j, longopts_shortopts_map[j].val);
422 if (longopts[i].val == longopts_shortopts_map[j].val) {
423 c = longopts_shortopts_map[j].c;
424 info = longopts_shortopts_map[j].info;
425 break;
426 };
427 j++;
428 };
429 };
430
431 if (c != '\0') {
432 fprintf(stderr, " -%c|--%s", c, longopts[i].name);
433 } else {
434 fprintf(stderr, " --%s", longopts[i].name);
435 };
436
437 if (info != NULL) {
438 fprintf(stderr, " (%s)", info);
439 };
440
441 fprintf(stderr, "\n");
442 };
443 i++;
444 };
445
446 fprintf(stderr, "\n");
447 return;
448 };
449
450
451 /* print help for output type examples */
452
453
printhelp_output_base85(void)454 static void printhelp_output_base85(void) {
455 fprintf(stderr, " Print a given IPv6 address in base85 format (RFC 1924), e.g.\n");
456 fprintf(stderr, " 1080:0:0:0:8:800:200c:417a -> 4)+k&C#VzJ4br>0wv%%Yp\n");
457 };
458
printhelp_output_bitstring(void)459 static void printhelp_output_bitstring(void) {
460 fprintf(stderr, " Print a given IPv6 address as a bitstring label for use with DNS, e.g.\n");
461 fprintf(stderr, " 3ffe:ffff::1 -> \\[x3ffeffff000000000000000000000001/128].ip6.arpa.\n");
462 fprintf(stderr, " 3ffe:ffff::1/64 -> \\[x3ffeffff000000000000000000000001/64].ip6.arpa.\n");
463 fprintf(stderr, " --printsuffix 3ffe:ffff::1/64 -> \\[x0000000000000001/64]\n");
464 fprintf(stderr, " --printprefix 3ffe:ffff::1/64 -> \\[x3ffeffff00000000/64]\n");
465 };
466
printhelp_output_ipv6addr(void)467 static void printhelp_output_ipv6addr(void) {
468 fprintf(stderr, " Print a given IPv6 address depending on format options:\n");
469 fprintf(stderr, " Uncompressed, e.g.\n");
470 fprintf(stderr, " 3ffe:ffff:100:f101::1 -> 3ffe:ffff:100:f101:0:0:0:1\n");
471 fprintf(stderr, " 3ffe:ffff:100:f101::1/64 -> 3ffe:ffff:100:f101:0:0:0:1/64\n");
472 fprintf(stderr, " Full uncompressed, e.g.\n");
473 fprintf(stderr, " 3ffe:ffff:100:f101::1 -> 3ffe:ffff:0100:f101:0000:0000:0000:0001\n");
474 fprintf(stderr, " Compressed, e.g.\n");
475 fprintf(stderr, " 3ffe:ffff:0100:f101:0000:0000:0000:0001 -> 3ffe:ffff:100:f101::1\n");
476 };
477
printhelp_output_ipv6literal(void)478 static void printhelp_output_ipv6literal(void) {
479 fprintf(stderr, " Print a given IPv6 address in literal format depending on format options:\n");
480 fprintf(stderr, " Uncompressed, e.g.\n");
481 fprintf(stderr, " 2001:db8::1 -> 2001-db8-0-0-0-0-0-1.ipv6-literal.net\n");
482 fprintf(stderr, " Full uncompressed, e.g.\n");
483 fprintf(stderr, " 2001:db8::1 -> 2001-0db8-0000-0000-0000-0000-0000-0001.ipv6-literal.net\n");
484 fprintf(stderr, " Compressed (default), e.g.\n");
485 fprintf(stderr, " 2001:db8::1 -> 2001-db8--1.ipv6-literal.net\n");
486 fprintf(stderr, " With Scope ID, e.g.\n");
487 fprintf(stderr, " fe80::1%%0 -> fe80--1s0.ipv6-literal.net\n");
488 };
489
printhelp_output_hex(void)490 static void printhelp_output_hex(void) {
491 fprintf(stderr, " Print a given IPv4/v6 address in hex format depending on format options:\n");
492 fprintf(stderr, " without any format option, e.g.\n");
493 fprintf(stderr, " 0123:4567:89ab:cdef:0000:1111:2222:3333 -> 0123456789abcdef0000111122223333\n");
494 fprintf(stderr, " 1.2.3.4 -> 01020304\n");
495 };
496
printhelp_output_eui64(void)497 static void printhelp_output_eui64(void) {
498 fprintf(stderr, " Print a generated EUI-64 identifier, e.g.:\n");
499 fprintf(stderr, " 00:50:BF:06:B4:F5 -> 0250:bfff:fe06:b4f5\n");
500 };
501
printhelp_output_iid_token(void)502 static void printhelp_output_iid_token(void) {
503 fprintf(stderr, " Print generated interface identifier and token, e.g.:\n");
504 fprintf(stderr, " -> 4462:bdea:8654:776d 486072ff7074945e\n");
505 };
506
printhelp_output_revnibble_int(void)507 static void printhelp_output_revnibble_int(void) {
508 fprintf(stderr, " Print a given IPv6 address in dot separated reverse nibble format for use with DNS, e.g.\n");
509 fprintf(stderr, " 3ffe:ffff:100:f101::1\n -> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.1.f.0.0.1.0.0.0.4.0.e.f.f.3.ip6.int.\n");
510 fprintf(stderr, " 3ffe:ffff:100:f101::1/64\n -> 1.0.1.f.0.0.1.0.0.0.4.0.e.f.f.3.ip6.int.\n");
511 };
512
printhelp_output_revnibble_arpa(void)513 static void printhelp_output_revnibble_arpa(void) {
514 fprintf(stderr, " Print a given IPv6 address in dot separated reverse nibble format for use with DNS, e.g.\n");
515 fprintf(stderr, " 3ffe:ffff:100:f101::1\n -> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.1.f.0.0.1.0.0.0.4.0.e.f.f.3.ip6.arpa.\n");
516 fprintf(stderr, " 3ffe:ffff:100:f101::1/64\n -> 1.0.1.f.0.0.1.0.0.0.4.0.e.f.f.3.ip6.arpa.\n");
517 };
518
printhelp_input_revnibbles(void)519 static void printhelp_input_revnibbles(void) {
520 fprintf(stderr, " Print reverse nibble format (used in DNS) as IPv6 address, e.g.\n");
521 fprintf(stderr, " 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.\n -> 2001:db8::1/128\n");
522 fprintf(stderr, " 8.b.d.0.1.0.0.2.ip6.arpa.\n -> 2001:db8::/32\n");
523 fprintf(stderr, " 8.b.d.0.1.0.0.2.ip6.arpa. --printprefix\n -> 2001:db8\n");
524 fprintf(stderr, " 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0\n -> ::1/64\n");
525 fprintf(stderr, " 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 --printsuffix\n -> 0:0:0:1\n");
526 };
527
528
printhelp_output_ifinet6void(void)529 static void printhelp_output_ifinet6void(void) {
530 fprintf(stderr, " Print a given IPv6 address to same format shown in Linux /proc/net/if_inet6:\n");
531 fprintf(stderr, " 3ffe:ffff:100:f101::1 -> 3ffeffff0100f1010000000000000001 00\n");
532 fprintf(stderr, " 3ffe:ffff:100:f101::1/64 -> 3ffeffff0100f1010000000000000001 00 40\n");
533 };
534
printhelp_output_ipv4addr(void)535 static void printhelp_output_ipv4addr(void) {
536 fprintf(stderr, " Print an IPv4 address, depending on format options:\n");
537 fprintf(stderr, " Uncompressed, e.g.\n");
538 fprintf(stderr, " 1.2.0.0 -> 1.2.0.0\n");
539 fprintf(stderr, " 1.2.0. -> 1.2.0.0\n");
540 fprintf(stderr, " 1.2 -> 1.2.0.0\n");
541 fprintf(stderr, " Compressed, e.g.\n");
542 fprintf(stderr, " 1.2.0.0 -> 1.2\n");
543 };
544
printhelp_output_revipv4(void)545 static void printhelp_output_revipv4(void) {
546 fprintf(stderr, " Print an IPv4 address in reverse format for PTR/DNS\n");
547 fprintf(stderr, " 1.2.3.4 -> 4.3.2.1.in-addr.arpa\n");
548 };
549
printhelp_output_addrtype(void)550 static void printhelp_output_addrtype(void) {
551 fprintf(stderr, " Print type of a given IPv4/IPv6 address:\n");
552 fprintf(stderr, " IPv4 address -> ipv4-addr.addrtype.ipv6calc\n");
553 fprintf(stderr, " IPv6 address -> ipv6-addr.addrtype.ipv6calc\n");
554 };
555
printhelp_output_ipv6addrtype(void)556 static void printhelp_output_ipv6addrtype(void) {
557 fprintf(stderr, " Print type of a given IPv6 address:\n");
558 fprintf(stderr, " 3ffe::/16 -> 6bone-global.ipv6addrtype.ipv6calc\n");
559 fprintf(stderr, " 2002::/16 -> 6to4-global.ipv6addrtype.ipv6calc\n");
560 fprintf(stderr, " 2001::/16 -> productive-global.ipv6addrtype.ipv6calc\n");
561 fprintf(stderr, " fe80::/10 -> link-local.ipv6addrtype.ipv6calc\n");
562 fprintf(stderr, " fec0::/10 -> site-local.ipv6addrtype.ipv6calc\n");
563 fprintf(stderr, " ::ffff:0:0:0:0/96 -> mapped-ipv4.ipv6addrtype.ipv6calc\n");
564 fprintf(stderr, " ::0:0:0:0/96 -> compat-ipv4.ipv6addrtype.ipv6calc\n");
565 };
566
printhelp_output_ouitype(void)567 static void printhelp_output_ouitype(void) {
568 fprintf(stderr, " Print OUI name of a given IPv6 address:\n");
569 fprintf(stderr, " IID local scope -> local-scoppe.ouitype.ipv6calc\n");
570 fprintf(stderr, " IID global scope -> vendorname.ouitype.ipv6calc\n");
571 };
572
printhelp_output_octal(void)573 static void printhelp_output_octal(void) {
574 fprintf(stderr, " Print octal representation of a given IPv6 address:\n");
575 fprintf(stderr, " (useful for djbdns/tinydns)\n");
576 fprintf(stderr, " 3ffe:ffff::1 ->\n \\77\\376\\377\\377\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\1\n");
577 fprintf(stderr, " --printfulluncompressed 3ffe:ffff::1 ->\n \\077\\376\\377\\377\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\001\n");
578 };
579
printhelp_output_dispatcher(const uint32_t outputtype,const uint32_t inputtype)580 void printhelp_output_dispatcher(const uint32_t outputtype, const uint32_t inputtype) {
581 int i, j;
582
583 printversion();
584
585 fprintf(stderr, "\n");
586
587 switch (outputtype) {
588 case FORMAT_base85:
589 printhelp_output_base85();
590 break;
591
592 case FORMAT_bitstring:
593 printhelp_output_bitstring();
594 break;
595
596 case FORMAT_ipv6addr:
597 printhelp_output_ipv6addr();
598 break;
599
600 case FORMAT_ipv6literal:
601 printhelp_output_ipv6literal();
602 break;
603
604 case FORMAT_eui64:
605 printhelp_output_eui64();
606 break;
607
608 case FORMAT_revnibbles_int:
609 printhelp_output_revnibble_int();
610 break;
611
612 case FORMAT_revnibbles_arpa:
613 printhelp_output_revnibble_arpa();
614 break;
615
616 case FORMAT_ifinet6:
617 printhelp_output_ifinet6void();
618 break;
619
620 case FORMAT_iid_token:
621 printhelp_output_iid_token();
622 break;
623
624 case FORMAT_ipv4addr:
625 printhelp_output_ipv4addr();
626 break;
627
628 case FORMAT_addrtype:
629 printhelp_output_addrtype();
630 break;
631
632 case FORMAT_ipv6addrtype:
633 printhelp_output_ipv6addrtype();
634 break;
635
636 case FORMAT_ouitype:
637 printhelp_output_ouitype();
638 break;
639
640 case FORMAT_revipv4:
641 printhelp_output_revipv4();
642 break;
643
644 case FORMAT_octal:
645 printhelp_output_octal();
646 break;
647
648 case FORMAT_hex:
649 printhelp_output_hex();
650 break;
651
652 default:
653 switch (inputtype) {
654 case FORMAT_revnibbles_int:
655 case FORMAT_revnibbles_arpa:
656 printhelp_input_revnibbles();
657 break;
658
659 default:
660 fprintf(stderr, " Examples currently missing... (output type)!\n");
661 break;
662 };
663 break;
664 };
665
666 /* looking for outtype */
667 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_outputformatoptionmap); i++) {
668 if (outputtype == ipv6calc_outputformatoptionmap[i][0]) {
669 if (ipv6calc_outputformatoptionmap[i][1] == 0) {
670 fprintf(stderr, " No format options supported\n");
671 break;
672 };
673
674 DEBUGPRINT_WA(DEBUG_ipv6calcoptions, "Format value: %08x", (unsigned int) ipv6calc_outputformatoptionmap[i][1]);
675
676 fprintf(stderr, "\n");
677 fprintf(stderr, " Available format options:\n");
678
679 /* run through format options */
680 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_formatoptionstrings); j++) {
681 if ((ipv6calc_outputformatoptionmap[i][1] & ipv6calc_formatoptionstrings[j].number) != 0) {
682 fprintf(stderr, " %s: %s\n", ipv6calc_formatoptionstrings[j].token, ipv6calc_formatoptionstrings[j].explanation);
683 };
684 };
685 break;
686 };
687 };
688 fprintf(stderr, "\n");
689 };
690
691 /* help regarding action command */
692 /* in: embedded = 1 : do not show version and command */
printhelp_action_dispatcher(const uint32_t action,const int embedded)693 void printhelp_action_dispatcher(const uint32_t action, const int embedded) {
694 int i, j;
695 char method_name[32];
696
697 if (embedded != 1) {
698 printversion();
699 };
700
701 fprintf(stderr, "\n");
702
703 switch (action) {
704 case ACTION_mac_to_eui64:
705 fprintf(stderr, " help still missing - sorry.\n");
706 break;
707
708 case ACTION_ipv4_to_6to4addr:
709 fprintf(stderr, " Convert IPv4 to 6to4 prefix / extract IPv4 from 6to4 prefix\n");
710 fprintf(stderr, " ipv6calc -A conv6to4 192.0.2.1\n");
711 fprintf(stderr, " 2002:c000:201::\n");
712 fprintf(stderr, " ipv6calc -A conv6to4 2002:c000:201::\n");
713 fprintf(stderr, " 192.0.2.1\n");
714 break;
715
716 case ACTION_ipv4_to_nat64:
717 fprintf(stderr, " Convert IPv4 to NAT64 address / extract IPv4 from NAT64 address\n");
718 fprintf(stderr, " ipv6calc -A convnat64 192.0.2.1\n");
719 fprintf(stderr, " 64:ff9b::c000:201\n");
720 fprintf(stderr, " ipv6calc -A convnat64 64:ff9b::c000:201\n");
721 fprintf(stderr, " 192.0.2.1\n");
722 break;
723
724 case ACTION_anonymize:
725 if (embedded != 1) {
726 fprintf(stderr, " Anonymize given address according to preset or custom values, e.g.\n");
727 fprintf(stderr, " ipv6calc -A anonymize 2001:db8:2280:6901:224:21ff:fe01:2345 --anonymize-preset zeroize-standard\n");
728 fprintf(stderr, " 2001:db8:2280:6900:224:21ff:fe00:0\n");
729 fprintf(stderr, " ipv6calc -A anonymize 2001:db8:2280:6901:224:21ff:fe01:2345 --anonymize-preset anonymize-standard\n");
730 fprintf(stderr, " 2001:db8:2280:6909:a929:4291:4022:4217\n");
731 fprintf(stderr, "\n");
732 };
733
734 fprintf(stderr, " Shortcut for anonymization presets:\n");
735 fprintf(stderr, " --anonymize-standard (default)\n");
736 fprintf(stderr, " --anonymize-careful\n");
737 fprintf(stderr, " --anonymize-paranoid\n");
738 fprintf(stderr, "\n");
739 fprintf(stderr, " Supported methods [--anonymize-method METHOD]:\n");
740 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_anon_methods); i++) {
741 fprintf(stderr, " %-10s: %s\n", ipv6calc_anon_methods[i].name, ipv6calc_anon_methods[i].description);
742 };
743 fprintf(stderr, "\n");
744
745 fprintf(stderr, " Available presets (shortcut names) [--anonymize-preset|ap PRESET-NAME]:\n");
746
747 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_anon_set_list); i++) {
748 snprintf(method_name, sizeof(method_name), "%s", "unknown"); // default
749
750 for (j = 0; j < MAXENTRIES_ARRAY(ipv6calc_anon_methods); j++) {
751 if (ipv6calc_anon_methods[j].method == ipv6calc_anon_set_list[i].method) {
752 snprintf(method_name, sizeof(method_name), "%s", ipv6calc_anon_methods[j].name);
753 break;
754 };
755 };
756
757 fprintf(stderr, " %-20s (%2s): mask-ipv6=%3d mask-ipv4=%2d mask-eui64=%2d mask-mac=%2d mask-autoadjust=%-3s method=%s\n", ipv6calc_anon_set_list[i].name, ipv6calc_anon_set_list[i].name_short, ipv6calc_anon_set_list[i].mask_ipv6, ipv6calc_anon_set_list[i].mask_ipv4, ipv6calc_anon_set_list[i].mask_eui64, ipv6calc_anon_set_list[i].mask_mac, (ipv6calc_anon_set_list[i].mask_autoadjust == 1) ? "yes" : "no", method_name);
758 };
759 fprintf(stderr, "\n");
760
761 fprintf(stderr, " Custom control:\n");
762 fprintf(stderr, " --mask-ipv4 <bits> : mask IPv4 address [0-32] (even if occurs in IPv6 address)\n");
763 fprintf(stderr, " --mask-ipv6 <bits> : mask IPv6 prefix [0-64] (only applied to related address types)\n");
764 fprintf(stderr, " --mask-eui64 <bits> : mask EUI-64 address or IPv6 interface identifier [0-64]\n");
765 fprintf(stderr, " --mask-mac <bits> : mask MAC address [0-48]\n");
766 fprintf(stderr, " --mask-autoadjust yes|no: autoadjust mask to keep type/vendor information regardless of less given mask\n");
767
768 break;
769
770 case ACTION_iid_token_to_privacy:
771 fprintf(stderr, " help still missing - sorry.\n");
772 break;
773
774 case ACTION_prefix_mac_to_ipv6:
775 fprintf(stderr, " help still missing - sorry.\n");
776 break;
777
778 case ACTION_6rd_local_prefix:
779 fprintf(stderr, " help still missing - sorry.\n");
780 break;
781
782 case ACTION_filter:
783 fprintf(stderr, " Filter given addresses from stdin by filter expression, e.g.\n");
784 fprintf(stderr, " echo '2001:db8::1' | ipv6calc [-A filter] -E iid-local\n");
785 fprintf(stderr, " echo '2001:db8::1' | ipv6calc [-A filter] -E iid-local,global-unicast\n");
786 fprintf(stderr, " echo '2001:db8::1' | ipv6calc [-A filter] -E ^iid-random\n");
787 fprintf(stderr, "\n");
788 fprintf(stderr, " (note: since version 0.95.0 '-A filter' is autoselected if option '-E <filter expression>' is given)\n");
789 fprintf(stderr, "\n");
790 fprintf(stderr, " negation of filter expression with prefix: ^\n");
791 fprintf(stderr, "\n");
792 fprintf(stderr, " IPv6 address filter tokens:\n");
793 fprintf(stderr, " ipv6 ");
794 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_ipv6addrtypestrings); i++ ) {
795 fprintf(stderr, " %s", ipv6calc_ipv6addrtypestrings[i].token);
796 };
797 fprintf(stderr, "\n");
798 fprintf(stderr, "\n");
799 fprintf(stderr, " IPv4 address filter tokens:\n");
800 fprintf(stderr, " ipv4 ");
801 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_ipv4addrtypestrings); i++ ) {
802 fprintf(stderr, " %s", ipv6calc_ipv4addrtypestrings[i].token);
803 };
804 fprintf(stderr, "\n");
805 fprintf(stderr, "\n");
806 fprintf(stderr, " IPv4/v6 address filter tokens based on databases:\n");
807 fprintf(stderr, " [^][ipv4.|ipv6.]db.cc=<CC>|unknown (Country Code [2 chars])\n");
808 fprintf(stderr, " [^][ipv4.|ipv6.]db.asn=<ASN>|unknown (Autonomous System Number)\n");
809 fprintf(stderr, " [^][ipv4.|ipv6.]db.reg=<REGISTRY>\n");
810 fprintf(stderr, " Registry tokens:");
811 for (i = 0; i < MAXENTRIES_ARRAY(ipv6calc_registries); i++ ) {
812 fprintf(stderr, " %s", ipv6calc_registries[i].token);
813 };
814 fprintf(stderr, "\n");
815 fprintf(stderr, "\n");
816 fprintf(stderr, " IPv4/v6 address filter tokens based on address/mask:\n");
817 fprintf(stderr, " [^]ipv4.addr=<IPV4-ADDRESS>[<PREFIX-LENGTH>]\n");
818 fprintf(stderr, " [^]ipv6.addr=<IPV6-ADDRESS>[<PREFIX-LENGTH>]\n");
819 fprintf(stderr, "\n");
820 fprintf(stderr, " IPv4/v6 address filter tokens based on address ranges (<=|<|>|>=):\n");
821 fprintf(stderr, " [^]ipv4.addr(<=|<|>|>=)<IPV4-ADDRESS>\n");
822 fprintf(stderr, " [^]ipv6.addr(<=|<|>|>=)<IPV6-ADDRESS>\n");
823 fprintf(stderr, "\n");
824 fprintf(stderr, " as alternative in case <|> creating problems also supported: =(le|lt|gt|ge)=:\n");
825 fprintf(stderr, " [^]ipv4.addr=(le|lt|gt|ge)=<IPV4-ADDRESS>\n");
826 fprintf(stderr, " [^]ipv6.addr=(le|lt|gt|ge)=<IPV6-ADDRESS>\n");
827 fprintf(stderr, "\n");
828 fprintf(stderr, " EUI-48/MAC address filter tokens:\n");
829 fprintf(stderr, " ");
830 fprintf(stderr, " IMPLEMENTATION MISSING");
831 fprintf(stderr, "\n");
832 fprintf(stderr, "\n");
833 fprintf(stderr, " EUI-64 address filter tokens:\n");
834 fprintf(stderr, " ");
835 fprintf(stderr, " IMPLEMENTATION MISSING");
836 fprintf(stderr, "\n");
837 break;
838
839 case ACTION_test:
840 fprintf(stderr, " Test given address(es) against supported tests:\n");
841 fprintf(stderr, " --test_prefix <PREFIX> : inside a prefix\n");
842 fprintf(stderr, " --test_gt|--test_ge <ADDRESS>: greater(/equal) than an address\n");
843 fprintf(stderr, " --test_lt|--test_le <ADDRESS>: less(/equal) than an address\n");
844 fprintf(stderr, "\n");
845 fprintf(stderr, " Test given address(es) from stdin, e.g.\n");
846 fprintf(stderr, " echo '2001:db8::1' | ipv6calc [-A test] --test_prefix 2001:db8::/32\n");
847 fprintf(stderr, " echo '2001:db8::1' | ipv6calc [-A test] --test_prefix 2001:db9::/32\n");
848 fprintf(stderr, "\n");
849 fprintf(stderr, " Single address test, return code: 0=inside/matching 1=outside/not-matching 2=uncomparable\n");
850 fprintf(stderr, " ipv6calc [-A test] --test_prefix 2001:db8::/32 2001:db8::1\n");
851 fprintf(stderr, " ipv6calc [-A test] --test_prefix 2001:db9::/32 2001:db8::1\n");
852 fprintf(stderr, " ipv6calc [-A test] --test_ge 2001:db8:: --test_le 2001:db8:ffff:ffff:ffff:ffff:ffff:ffff 2001:db8::1\n");
853 fprintf(stderr, " ipv6calc [-A test] --test_ge 2001:db9:: --test_le 2001:db9:ffff:ffff:ffff:ffff:ffff:ffff 2001:db8::1\n");
854 fprintf(stderr, " ipv6calc [-A test] --test_ge 2001:db9:: --test_lt 2001:dba:: 2001:db8::1\n");
855 fprintf(stderr, " ipv6calc [-A test] --test_ge 2001:db8:: --test_lt 2001:db9:: 2001:db8::1\n");
856 fprintf(stderr, "\n");
857 break;
858
859 case ACTION_addr_to_countrycode:
860 fprintf(stderr, " Convert given IPv4/IPv6 address to country code\n");
861 fprintf(stderr, " --addr2cc|-A addr2cc <ADDRESS>\n");
862 fprintf(stderr, "\n");
863 fprintf(stderr, " Examples:\n");
864 fprintf(stderr, " ipv6calc -A addr2cc 50.60.70.80\n");
865 fprintf(stderr, " US\n");
866 fprintf(stderr, "\n");
867 fprintf(stderr, " Example for address which has no country code:\n");
868 fprintf(stderr, " (reason is only displayed in non-quiet mode)\n");
869 fprintf(stderr, " ipv6calc -A addr2cc 2001:db8::1\n");
870 fprintf(stderr, " -- (unknown)\n");
871 fprintf(stderr, "\n");
872 fprintf(stderr, " Example in case no related database is available:\n");
873 fprintf(stderr, " (reason is only displayed in non-quiet mode)\n");
874 fprintf(stderr, " ipv6calc -A addr2cc 50.60.70.80\n");
875 fprintf(stderr, " -- (no-usable-database)\n");
876 fprintf(stderr, "\n");
877 break;
878 };
879 };
880
881
882 /***************************
883 * verbose feature information
884 * *************************/
885
886 /* display features in verbose mode */
ipv6calc_print_features_verbose(const int level_verbose)887 void ipv6calc_print_features_verbose(const int level_verbose) {
888 char string[IPV6CALC_STRING_MAX] = "";
889
890 libipv6calc_db_wrapper_capabilities(string, sizeof(string));
891 fprintf(stderr, "Capabilities: %s\n\n", string);
892
893 fprintf(stderr, "Internal main library version: %s API: %s (%s)\n"
894 , libipv6calc_lib_version_string()
895 , libipv6calc_api_version_string()
896 #ifdef SHARED_LIBRARY
897 , "shared"
898 #else // SHARED_LIBRARY
899 , "built-in"
900 #endif // SHARED_LIBRARY
901 );
902
903 fprintf(stderr, "Internal database library version: %s API: %s (%s)\n\n"
904 , libipv6calc_db_lib_version_string()
905 , libipv6calc_db_api_version_string()
906 #ifdef SHARED_LIBRARY
907 , "shared"
908 #else // SHARED_LIBRARY
909 , "built-in"
910 #endif // SHARED_LIBRARY
911 );
912
913 #if defined ENABLE_BUNDLED_MD5 || defined ENABLE_BUNDLED_GETOPT
914 fprintf(stderr, "Bundled with:");
915 #ifdef ENABLE_BUNDLED_MD5
916 fprintf(stderr, " MD5");
917 #endif
918 #ifdef ENABLE_BUNDLED_GETOPT
919 fprintf(stderr, " GETOPT");
920 #endif
921 fprintf(stderr, "\n\n");
922 #endif
923
924 fprintf(stderr, "Compiled: %s %s\n\n", __DATE__, __TIME__);
925
926 libipv6calc_db_wrapper_print_features_verbose(level_verbose);
927 };
928