1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 
5 #ifndef MAXMINDDB_H
6 #define MAXMINDDB_H
7 
8 /* Request POSIX.1-2008. However, we want to remain compatible with
9  * POSIX.1-2001 (since we have been historically and see no reason to drop
10  * compatibility). By requesting POSIX.1-2008, we can conditionally use
11  * features provided by that standard if the implementation provides it. We can
12  * check for what the implementation provides by checking the _POSIX_VERSION
13  * macro after including unistd.h. If a feature is in POSIX.1-2008 but not
14  * POSIX.1-2001, check that macro before using the feature (or check for the
15  * feature directly if possible). */
16 #ifndef _POSIX_C_SOURCE
17 #define _POSIX_C_SOURCE 200809L
18 #endif
19 
20 #include "maxminddb_config.h"
21 #include <stdarg.h>
22 #include <stdbool.h>
23 #include <stdint.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 
27 #ifdef _WIN32
28 #include <winsock2.h>
29 #include <ws2tcpip.h>
30 /* libmaxminddb package version from configure */
31 #define PACKAGE_VERSION "1.6.0"
32 
33 typedef ADDRESS_FAMILY sa_family_t;
34 
35 #if defined(_MSC_VER)
36 /* MSVC doesn't define signed size_t, copy it from configure */
37 #define ssize_t SSIZE_T
38 
39 /* MSVC doesn't support restricted pointers */
40 #define restrict
41 #endif
42 #else
43 #include <netdb.h>
44 #include <netinet/in.h>
45 #include <sys/socket.h>
46 #endif
47 
48 #define MMDB_DATA_TYPE_EXTENDED (0)
49 #define MMDB_DATA_TYPE_POINTER (1)
50 #define MMDB_DATA_TYPE_UTF8_STRING (2)
51 #define MMDB_DATA_TYPE_DOUBLE (3)
52 #define MMDB_DATA_TYPE_BYTES (4)
53 #define MMDB_DATA_TYPE_UINT16 (5)
54 #define MMDB_DATA_TYPE_UINT32 (6)
55 #define MMDB_DATA_TYPE_MAP (7)
56 #define MMDB_DATA_TYPE_INT32 (8)
57 #define MMDB_DATA_TYPE_UINT64 (9)
58 #define MMDB_DATA_TYPE_UINT128 (10)
59 #define MMDB_DATA_TYPE_ARRAY (11)
60 #define MMDB_DATA_TYPE_CONTAINER (12)
61 #define MMDB_DATA_TYPE_END_MARKER (13)
62 #define MMDB_DATA_TYPE_BOOLEAN (14)
63 #define MMDB_DATA_TYPE_FLOAT (15)
64 
65 #define MMDB_RECORD_TYPE_SEARCH_NODE (0)
66 #define MMDB_RECORD_TYPE_EMPTY (1)
67 #define MMDB_RECORD_TYPE_DATA (2)
68 #define MMDB_RECORD_TYPE_INVALID (3)
69 
70 /* flags for open */
71 #define MMDB_MODE_MMAP (1)
72 #define MMDB_MODE_MASK (7)
73 
74 /* error codes */
75 #define MMDB_SUCCESS (0)
76 #define MMDB_FILE_OPEN_ERROR (1)
77 #define MMDB_CORRUPT_SEARCH_TREE_ERROR (2)
78 #define MMDB_INVALID_METADATA_ERROR (3)
79 #define MMDB_IO_ERROR (4)
80 #define MMDB_OUT_OF_MEMORY_ERROR (5)
81 #define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR (6)
82 #define MMDB_INVALID_DATA_ERROR (7)
83 #define MMDB_INVALID_LOOKUP_PATH_ERROR (8)
84 #define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR (9)
85 #define MMDB_INVALID_NODE_NUMBER_ERROR (10)
86 #define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR (11)
87 
88 #if !(MMDB_UINT128_IS_BYTE_ARRAY)
89 #if MMDB_UINT128_USING_MODE
90 typedef unsigned int mmdb_uint128_t __attribute__((__mode__(TI)));
91 #else
92 typedef unsigned __int128 mmdb_uint128_t;
93 #endif
94 #endif
95 
96 /* This is a pointer into the data section for a given IP address lookup */
97 typedef struct MMDB_entry_s {
98     const struct MMDB_s *mmdb;
99     uint32_t offset;
100 } MMDB_entry_s;
101 
102 typedef struct MMDB_lookup_result_s {
103     bool found_entry;
104     MMDB_entry_s entry;
105     uint16_t netmask;
106 } MMDB_lookup_result_s;
107 
108 typedef struct MMDB_entry_data_s {
109     bool has_data;
110     union {
111         uint32_t pointer;
112         const char *utf8_string;
113         double double_value;
114         const uint8_t *bytes;
115         uint16_t uint16;
116         uint32_t uint32;
117         int32_t int32;
118         uint64_t uint64;
119 #if MMDB_UINT128_IS_BYTE_ARRAY
120         uint8_t uint128[16];
121 #else
122         mmdb_uint128_t uint128;
123 #endif
124         bool boolean;
125         float float_value;
126     };
127     /* This is a 0 if a given entry cannot be found. This can only happen
128      * when a call to MMDB_(v)get_value() asks for hash keys or array
129      * indices that don't exist. */
130     uint32_t offset;
131     /* This is the next entry in the data section, but it's really only
132      * relevant for entries that part of a larger map or array
133      * struct. There's no good reason for an end user to look at this
134      * directly. */
135     uint32_t offset_to_next;
136     /* This is only valid for strings, utf8_strings or binary data */
137     uint32_t data_size;
138     /* This is an MMDB_DATA_TYPE_* constant */
139     uint32_t type;
140 } MMDB_entry_data_s;
141 
142 /* This is the return type when someone asks for all the entry data in a map or
143  * array */
144 typedef struct MMDB_entry_data_list_s {
145     MMDB_entry_data_s entry_data;
146     struct MMDB_entry_data_list_s *next;
147     void *pool;
148 } MMDB_entry_data_list_s;
149 
150 typedef struct MMDB_description_s {
151     const char *language;
152     const char *description;
153 } MMDB_description_s;
154 
155 /* WARNING: do not add new fields to this struct without bumping the SONAME.
156  * The struct is allocated by the users of this library and increasing the
157  * size will cause existing users to allocate too little space when the shared
158  * library is upgraded */
159 typedef struct MMDB_metadata_s {
160     uint32_t node_count;
161     uint16_t record_size;
162     uint16_t ip_version;
163     const char *database_type;
164     struct {
165         size_t count;
166         const char **names;
167     } languages;
168     uint16_t binary_format_major_version;
169     uint16_t binary_format_minor_version;
170     uint64_t build_epoch;
171     struct {
172         size_t count;
173         MMDB_description_s **descriptions;
174     } description;
175     /* See above warning before adding fields */
176 } MMDB_metadata_s;
177 
178 /* WARNING: do not add new fields to this struct without bumping the SONAME.
179  * The struct is allocated by the users of this library and increasing the
180  * size will cause existing users to allocate too little space when the shared
181  * library is upgraded */
182 typedef struct MMDB_ipv4_start_node_s {
183     uint16_t netmask;
184     uint32_t node_value;
185     /* See above warning before adding fields */
186 } MMDB_ipv4_start_node_s;
187 
188 /* WARNING: do not add new fields to this struct without bumping the SONAME.
189  * The struct is allocated by the users of this library and increasing the
190  * size will cause existing users to allocate too little space when the shared
191  * library is upgraded */
192 typedef struct MMDB_s {
193     uint32_t flags;
194     const char *filename;
195     ssize_t file_size;
196     const uint8_t *file_content;
197     const uint8_t *data_section;
198     uint32_t data_section_size;
199     const uint8_t *metadata_section;
200     uint32_t metadata_section_size;
201     uint16_t full_record_byte_size;
202     uint16_t depth;
203     MMDB_ipv4_start_node_s ipv4_start_node;
204     MMDB_metadata_s metadata;
205     /* See above warning before adding fields */
206 } MMDB_s;
207 
208 typedef struct MMDB_search_node_s {
209     uint64_t left_record;
210     uint64_t right_record;
211     uint8_t left_record_type;
212     uint8_t right_record_type;
213     MMDB_entry_s left_record_entry;
214     MMDB_entry_s right_record_entry;
215 } MMDB_search_node_s;
216 
217 extern int
218 MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb);
219 extern MMDB_lookup_result_s MMDB_lookup_string(const MMDB_s *const mmdb,
220                                                const char *const ipstr,
221                                                int *const gai_error,
222                                                int *const mmdb_error);
223 extern MMDB_lookup_result_s
224 MMDB_lookup_sockaddr(const MMDB_s *const mmdb,
225                      const struct sockaddr *const sockaddr,
226                      int *const mmdb_error);
227 extern int MMDB_read_node(const MMDB_s *const mmdb,
228                           uint32_t node_number,
229                           MMDB_search_node_s *const node);
230 extern int MMDB_get_value(MMDB_entry_s *const start,
231                           MMDB_entry_data_s *const entry_data,
232                           ...);
233 extern int MMDB_vget_value(MMDB_entry_s *const start,
234                            MMDB_entry_data_s *const entry_data,
235                            va_list va_path);
236 extern int MMDB_aget_value(MMDB_entry_s *const start,
237                            MMDB_entry_data_s *const entry_data,
238                            const char *const *const path);
239 extern int MMDB_get_metadata_as_entry_data_list(
240     const MMDB_s *const mmdb, MMDB_entry_data_list_s **const entry_data_list);
241 extern int
242 MMDB_get_entry_data_list(MMDB_entry_s *start,
243                          MMDB_entry_data_list_s **const entry_data_list);
244 extern void
245 MMDB_free_entry_data_list(MMDB_entry_data_list_s *const entry_data_list);
246 extern void MMDB_close(MMDB_s *const mmdb);
247 extern const char *MMDB_lib_version(void);
248 extern int
249 MMDB_dump_entry_data_list(FILE *const stream,
250                           MMDB_entry_data_list_s *const entry_data_list,
251                           int indent);
252 extern const char *MMDB_strerror(int error_code);
253 
254 #endif /* MAXMINDDB_H */
255 
256 #ifdef __cplusplus
257 }
258 #endif
259