#ifndef COSMOPOLITAN_THIRD_PARTY_MAXMIND_MAXMINDDB_H_ #define COSMOPOLITAN_THIRD_PARTY_MAXMIND_MAXMINDDB_H_ #include "libc/sock/sock.h" #include "libc/stdio/stdio.h" #define MMDB_MODE_MMAP 1 #define MMDB_MODE_MASK 7 #define MMDB_DATA_TYPE_EXTENDED 0 #define MMDB_DATA_TYPE_POINTER 1 #define MMDB_DATA_TYPE_UTF8_STRING 2 #define MMDB_DATA_TYPE_DOUBLE 3 #define MMDB_DATA_TYPE_BYTES 4 #define MMDB_DATA_TYPE_UINT16 5 #define MMDB_DATA_TYPE_UINT32 6 #define MMDB_DATA_TYPE_MAP 7 #define MMDB_DATA_TYPE_INT32 8 #define MMDB_DATA_TYPE_UINT64 9 #define MMDB_DATA_TYPE_UINT128 10 #define MMDB_DATA_TYPE_ARRAY 11 #define MMDB_DATA_TYPE_CONTAINER 12 #define MMDB_DATA_TYPE_END_MARKER 13 #define MMDB_DATA_TYPE_BOOLEAN 14 #define MMDB_DATA_TYPE_FLOAT 15 #define MMDB_RECORD_TYPE_SEARCH_NODE 0 #define MMDB_RECORD_TYPE_EMPTY 1 #define MMDB_RECORD_TYPE_DATA 2 #define MMDB_RECORD_TYPE_INVALID 3 #define MMDB_SUCCESS 0 #define MMDB_FILE_OPEN_ERROR 1 #define MMDB_CORRUPT_SEARCH_TREE_ERROR 2 #define MMDB_INVALID_METADATA_ERROR 3 #define MMDB_IO_ERROR 4 #define MMDB_OUT_OF_MEMORY_ERROR 5 #define MMDB_UNKNOWN_DATABASE_FORMAT_ERROR 6 #define MMDB_INVALID_DATA_ERROR 7 #define MMDB_INVALID_LOOKUP_PATH_ERROR 8 #define MMDB_LOOKUP_PATH_DOES_NOT_MATCH_DATA_ERROR 9 #define MMDB_INVALID_NODE_NUMBER_ERROR 10 #define MMDB_IPV6_LOOKUP_IN_IPV4_DATABASE_ERROR 11 COSMOPOLITAN_C_START_ /* This is a pointer into the data section for a given IP address lookup */ typedef struct MMDB_entry_s { const struct MMDB_s *mmdb; uint32_t offset; } MMDB_entry_s; typedef struct MMDB_lookup_result_s { bool found_entry; MMDB_entry_s entry; uint16_t netmask; } MMDB_lookup_result_s; typedef struct MMDB_entry_data_s { bool has_data; union { uint32_t pointer; const char *utf8_string; double double_value; const uint8_t *bytes; uint16_t uint16; uint32_t uint32; int32_t int32; uint64_t uint64; uint128_t uint128; bool boolean; float float_value; }; /* This is a 0 if a given entry cannot be found. This can only happen * when a call to MMDB_(v)get_value() asks for hash keys or array * indices that don't exist. */ uint32_t offset; /* This is the next entry in the data section, but it's really only * relevant for entries that part of a larger map or array * struct. There's no good reason for an end user to look at this * directly. */ uint32_t offset_to_next; /* This is only valid for strings, utf8_strings or binary data */ uint32_t data_size; /* This is an MMDB_DATA_TYPE_* constant */ uint32_t type; } MMDB_entry_data_s; /* This is the return type when someone asks for all the entry data in a map or * array */ typedef struct MMDB_entry_data_list_s { MMDB_entry_data_s entry_data; struct MMDB_entry_data_list_s *next; void *pool; } MMDB_entry_data_list_s; typedef struct MMDB_description_s { const char *language; const char *description; } MMDB_description_s; /* WARNING: do not add new fields to this struct without bumping the SONAME. * The struct is allocated by the users of this library and increasing the * size will cause existing users to allocate too little space when the shared * library is upgraded */ typedef struct MMDB_metadata_s { uint32_t node_count; uint16_t record_size; uint16_t ip_version; const char *database_type; struct { size_t count; const char **names; } languages; uint16_t binary_format_major_version; uint16_t binary_format_minor_version; uint64_t build_epoch; struct { size_t count; MMDB_description_s **descriptions; } description; /* See above warning before adding fields */ } MMDB_metadata_s; /* WARNING: do not add new fields to this struct without bumping the SONAME. * The struct is allocated by the users of this library and increasing the * size will cause existing users to allocate too little space when the shared * library is upgraded */ typedef struct MMDB_ipv4_start_node_s { uint16_t netmask; uint32_t node_value; /* See above warning before adding fields */ } MMDB_ipv4_start_node_s; /* WARNING: do not add new fields to this struct without bumping the SONAME. * The struct is allocated by the users of this library and increasing the * size will cause existing users to allocate too little space when the shared * library is upgraded */ typedef struct MMDB_s { uint32_t flags; const char *filename; ssize_t file_size; const uint8_t *file_content; const uint8_t *data_section; uint32_t data_section_size; const uint8_t *metadata_section; uint32_t metadata_section_size; uint16_t full_record_byte_size; uint16_t depth; MMDB_ipv4_start_node_s ipv4_start_node; MMDB_metadata_s metadata; /* See above warning before adding fields */ } MMDB_s; typedef struct MMDB_search_node_s { uint64_t left_record; uint64_t right_record; uint8_t left_record_type; uint8_t right_record_type; MMDB_entry_s left_record_entry; MMDB_entry_s right_record_entry; } MMDB_search_node_s; void MMDB_close(MMDB_s *); int MMDB_open(const char *, uint32_t, MMDB_s *); MMDB_lookup_result_s MMDB_lookup(const MMDB_s *, uint32_t, int *); int MMDB_read_node(const MMDB_s *, uint32_t, MMDB_search_node_s *); int MMDB_get_value(MMDB_entry_s *, MMDB_entry_data_s *, ...); int MMDB_vget_value(MMDB_entry_s *, MMDB_entry_data_s *, va_list); int MMDB_aget_value(MMDB_entry_s *, MMDB_entry_data_s *, const char *const *); int MMDB_get_metadata_as_entry_data_list(const MMDB_s *, MMDB_entry_data_list_s **); int MMDB_get_entry_data_list(MMDB_entry_s *, MMDB_entry_data_list_s **); void MMDB_free_entry_data_list(MMDB_entry_data_list_s *); int MMDB_dump_entry_data_list(FILE *, MMDB_entry_data_list_s *, int); const char *MMDB_lib_version(void); const char *MMDB_strerror(int); const char *GetMetroName(int); COSMOPOLITAN_C_END_ #endif /* COSMOPOLITAN_THIRD_PARTY_MAXMIND_MAXMINDDB_H_ */