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 program uses the MaxMind DB library (libmaxminddb) and MUST be
8 * compatible with its license (Apache 2.0).
10 * SPDX-License-Identifier: MIT
18 #include <maxminddb.h>
20 #define MAX_ADDR_LEN 46
21 #define MMDBR_STRINGIFY(x) MMDBR_STRINGIFY_S(x)
22 #define MMDBR_STRINGIFY_S(s) #s
23 #define OUT_BUF_SIZE 65536
25 // Uncomment to enable slow lookups. Only useful on Windows for now.
26 // #define MMDB_DEBUG_SLOW 1
28 #ifdef MMDB_DEBUG_SLOW
34 static const char *co_iso_key
[] = {"country", "iso_code", NULL
};
35 static const char *co_name_key
[] = {"country", "names", "en", NULL
};
36 static const char *ci_name_key
[] = {"city", "names", "en", NULL
};
37 static const char *asn_o_key
[] = {"autonomous_system_organization", NULL
};
38 static const char *asn_key
[] = {"autonomous_system_number", NULL
};
39 static const char *l_lat_key
[] = {"location", "latitude", NULL
};
40 static const char *l_lon_key
[] = {"location", "longitude", NULL
};
41 static const char *l_accuracy_key
[] = {"location", "accuracy_radius", NULL
};
42 static const char *empty_key
[] = {NULL
};
44 static const char **lookup_keys
[] = {
56 static void exit_err(void) {
57 fprintf(stderr
, "Usage: mmdbresolve -f db_file [-f db_file ...]\n");
62 main(int argc
, char *argv
[])
64 char addr_str
[MAX_ADDR_LEN
+1];
65 size_t mmdb_count
= 0;
66 MMDB_s
*mmdbs
= NULL
, *new_mmdbs
;
69 char *out_buf
= (char *) malloc(OUT_BUF_SIZE
);
70 if (out_buf
== NULL
) {
71 fprintf(stdout
, "ERROR: malloc failed\n");
74 setvbuf(stdout
, out_buf
, _IOFBF
, OUT_BUF_SIZE
);
76 fprintf(stdout
, "[init]\n");
78 // If we need to handle anything beyond "-f" we'll probably want to
79 // link with GLib and use GOption.
81 while (arg_idx
< argc
- 1) {
82 if (strcmp(argv
[arg_idx
], "-f") == 0) {
84 const char *db_arg
= argv
[arg_idx
];
86 mmdb_err
= MMDB_open(db_arg
, 0, &try_mmdb
);
87 fprintf(stdout
, "db.%zd.path: %s\n", mmdb_count
, db_arg
);
88 fprintf(stdout
, "db.%zd.status: ", mmdb_count
);
89 if (mmdb_err
== MMDB_SUCCESS
) {
91 new_mmdbs
= (MMDB_s
*) realloc(mmdbs
, mmdb_count
* sizeof(MMDB_s
));
92 if (new_mmdbs
== NULL
) {
94 fprintf(stdout
, "ERROR out of memory\n");
98 mmdbs
[mmdb_count
- 1] = try_mmdb
;
99 fprintf(stdout
, "OK\n");
100 fprintf(stdout
, "db.%zd.type: %s\n", mmdb_count
, mmdbs
[mmdb_count
- 1].metadata
.database_type
);
102 fprintf(stdout
, "ERROR %s\n", MMDB_strerror(mmdb_err
));
108 fprintf(stdout
, "mmdbresolve.status: %s\n", mmdb_count
> 0 ? "true": "false");
109 fprintf(stdout
, "# End init\n");
112 if (arg_idx
!= argc
|| mmdb_count
< 1) {
117 while (in_items
!= EOF
) {
120 in_items
= fscanf(stdin
, "%" MMDBR_STRINGIFY(MAX_ADDR_LEN
) "s", addr_str
);
126 fprintf(stdout
, "[%s]\n", addr_str
);
128 #ifdef MMDB_DEBUG_SLOW
134 for (size_t mmdb_idx
= 0; mmdb_idx
< mmdb_count
; mmdb_idx
++) {
135 fprintf(stdout
, "# %s\n", mmdbs
[mmdb_idx
].metadata
.database_type
);
136 MMDB_lookup_result_s result
= MMDB_lookup_string(&mmdbs
[mmdb_idx
], addr_str
, &gai_err
, &mmdb_err
);
138 if (result
.found_entry
&& gai_err
== 0 && mmdb_err
== MMDB_SUCCESS
) {
139 for (size_t key_idx
= 0; lookup_keys
[key_idx
][0]; key_idx
++) {
140 MMDB_entry_data_s entry_data
;
141 int status
= MMDB_aget_value(&result
.entry
, &entry_data
, lookup_keys
[key_idx
]);
142 if (status
== MMDB_SUCCESS
&& entry_data
.has_data
) {
144 for (int idx
= 0; lookup_keys
[key_idx
][idx
] != 0; idx
++) {
145 fprintf(stdout
, "%s%s", sep
, lookup_keys
[key_idx
][idx
]);
148 switch (entry_data
.type
) {
149 case MMDB_DATA_TYPE_UTF8_STRING
:
151 char len_fmt
[12]; // : %.xxxxxs\n\0
152 snprintf(len_fmt
, 11, ": %%.%us\n", entry_data
.data_size
);
153 fprintf(stdout
, len_fmt
, entry_data
.utf8_string
);
156 case MMDB_DATA_TYPE_UINT16
:
157 fprintf(stdout
, ": %u\n", entry_data
.uint16
);
159 case MMDB_DATA_TYPE_UINT32
:
160 fprintf(stdout
, ": %u\n", entry_data
.uint32
);
162 case MMDB_DATA_TYPE_INT32
:
163 fprintf(stdout
, ": %d\n", entry_data
.int32
);
165 case MMDB_DATA_TYPE_BOOLEAN
:
166 fprintf(stdout
, ": %s\n", entry_data
.boolean
? "True" : "False");
168 case MMDB_DATA_TYPE_DOUBLE
:
169 fprintf(stdout
, ": %f\n", entry_data
.double_value
);
171 case MMDB_DATA_TYPE_FLOAT
:
172 fprintf(stdout
, ": %f\n", entry_data
.float_value
);
175 fprintf(stdout
, ": UNKNOWN (%u)\n", entry_data
.type
);
183 fprintf(stdout
, "# End %s\n", addr_str
);
193 * Editor modelines - https://www.wireshark.org/tools/modelines.html
198 * indent-tabs-mode: nil
201 * vi: set shiftwidth=4 tabstop=8 expandtab:
202 * :indentSize=4:tabSize=8:noTabs=true: