1 /* Read IPv4 and IPv6 addresses on stdin and print their MMDB entries on stdout.
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * This progam uses the MaxMind DB library (libmaxminddb) and MUST be
8 * compatible with its license (Apache 2.0).
10 * SPDX-License-Identifier: MIT
19 #include <maxminddb.h>
21 #define MAX_ADDR_LEN 46
22 #define MMDBR_STRINGIFY(x) MMDBR_STRINGIFY_S(x)
23 #define MMDBR_STRINGIFY_S(s) #s
24 #define OUT_BUF_SIZE 65536
26 // Uncomment to enable slow lookups. Only useful on Windows for now.
27 // #define MMDB_DEBUG_SLOW 1
29 #ifdef MMDB_DEBUG_SLOW
35 static const char *co_iso_key
[] = {"country", "iso_code", NULL
};
36 static const char *co_name_key
[] = {"country", "names", "en", NULL
};
37 static const char *ci_name_key
[] = {"city", "names", "en", NULL
};
38 static const char *asn_o_key
[] = {"autonomous_system_organization", NULL
};
39 static const char *asn_key
[] = {"autonomous_system_number", NULL
};
40 static const char *l_lat_key
[] = {"location", "latitude", NULL
};
41 static const char *l_lon_key
[] = {"location", "longitude", NULL
};
42 static const char *l_accuracy_key
[] = {"location", "accuracy_radius", NULL
};
43 static const char *empty_key
[] = {NULL
};
45 static const char **lookup_keys
[] = {
57 static void exit_err(void) {
58 fprintf(stderr
, "Usage: mmdbresolve -f db_file [-f db_file ...]\n");
63 main(int argc
, char *argv
[])
65 char addr_str
[MAX_ADDR_LEN
+1];
66 size_t mmdb_count
= 0;
67 MMDB_s
*mmdbs
= NULL
, *new_mmdbs
;
70 char *out_buf
= (char *) malloc(OUT_BUF_SIZE
);
71 if (out_buf
== NULL
) {
72 fprintf(stdout
, "ERROR: malloc failed\n");
75 setvbuf(stdout
, out_buf
, _IOFBF
, OUT_BUF_SIZE
);
77 fprintf(stdout
, "[init]\n");
79 // If we need to handle anything beyond "-f" we'll probably want to
80 // link with GLib and use GOption.
82 while (arg_idx
< argc
- 1) {
83 if (strcmp(argv
[arg_idx
], "-f") == 0) {
85 const char *db_arg
= argv
[arg_idx
];
87 mmdb_err
= MMDB_open(db_arg
, 0, &try_mmdb
);
88 fprintf(stdout
, "db.%zd.path: %s\n", mmdb_count
, db_arg
);
89 fprintf(stdout
, "db.%zd.status: ", mmdb_count
);
90 if (mmdb_err
== MMDB_SUCCESS
) {
92 new_mmdbs
= (MMDB_s
*) realloc(mmdbs
, mmdb_count
* sizeof(MMDB_s
));
93 if (new_mmdbs
== NULL
) {
95 fprintf(stdout
, "ERROR out of memory\n");
99 mmdbs
[mmdb_count
- 1] = try_mmdb
;
100 fprintf(stdout
, "OK\n");
101 fprintf(stdout
, "db.%zd.type: %s\n", mmdb_count
, mmdbs
[mmdb_count
- 1].metadata
.database_type
);
103 fprintf(stdout
, "ERROR %s\n", MMDB_strerror(mmdb_err
));
109 fprintf(stdout
, "mmdbresolve.status: %s\n", mmdb_count
> 0 ? "true": "false");
110 fprintf(stdout
, "# End init\n");
113 if (arg_idx
!= argc
|| mmdb_count
< 1) {
118 while (in_items
!= EOF
) {
121 in_items
= fscanf(stdin
, "%" MMDBR_STRINGIFY(MAX_ADDR_LEN
) "s", addr_str
);
127 fprintf(stdout
, "[%s]\n", addr_str
);
129 #ifdef MMDB_DEBUG_SLOW
135 for (size_t mmdb_idx
= 0; mmdb_idx
< mmdb_count
; mmdb_idx
++) {
136 fprintf(stdout
, "# %s\n", mmdbs
[mmdb_idx
].metadata
.database_type
);
137 MMDB_lookup_result_s result
= MMDB_lookup_string(&mmdbs
[mmdb_idx
], addr_str
, &gai_err
, &mmdb_err
);
139 if (result
.found_entry
&& gai_err
== 0 && mmdb_err
== MMDB_SUCCESS
) {
140 for (size_t key_idx
= 0; lookup_keys
[key_idx
][0]; key_idx
++) {
141 MMDB_entry_data_s entry_data
;
142 int status
= MMDB_aget_value(&result
.entry
, &entry_data
, lookup_keys
[key_idx
]);
143 if (status
== MMDB_SUCCESS
&& entry_data
.has_data
) {
145 for (int idx
= 0; lookup_keys
[key_idx
][idx
] != 0; idx
++) {
146 fprintf(stdout
, "%s%s", sep
, lookup_keys
[key_idx
][idx
]);
149 switch (entry_data
.type
) {
150 case MMDB_DATA_TYPE_UTF8_STRING
:
152 char len_fmt
[12]; // : %.xxxxxs\n\0
153 snprintf(len_fmt
, 11, ": %%.%us\n", entry_data
.data_size
);
154 fprintf(stdout
, len_fmt
, entry_data
.utf8_string
);
157 case MMDB_DATA_TYPE_UINT16
:
158 fprintf(stdout
, ": %u\n", entry_data
.uint16
);
160 case MMDB_DATA_TYPE_UINT32
:
161 fprintf(stdout
, ": %u\n", entry_data
.uint32
);
163 case MMDB_DATA_TYPE_INT32
:
164 fprintf(stdout
, ": %d\n", entry_data
.int32
);
166 case MMDB_DATA_TYPE_BOOLEAN
:
167 fprintf(stdout
, ": %s\n", entry_data
.boolean
? "True" : "False");
169 case MMDB_DATA_TYPE_DOUBLE
:
170 fprintf(stdout
, ": %f\n", entry_data
.double_value
);
172 case MMDB_DATA_TYPE_FLOAT
:
173 fprintf(stdout
, ": %f\n", entry_data
.float_value
);
176 fprintf(stdout
, ": UNKNOWN (%u)\n", entry_data
.type
);
184 fprintf(stdout
, "# End %s\n", addr_str
);
194 * Editor modelines - https://www.wireshark.org/tools/modelines.html
199 * indent-tabs-mode: nil
202 * vi: set shiftwidth=4 tabstop=8 expandtab:
203 * :indentSize=4:tabSize=8:noTabs=true: