1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-06-16 07:07:13 +02:00

Update the MaxmindDB library to latest version. Also include configs for all platforms.

This commit is contained in:
Sandu Liviu Catalin
2016-11-14 14:05:29 +02:00
parent ded30fdeac
commit 2ef75d0dce
6 changed files with 770 additions and 73 deletions

View File

@ -155,10 +155,14 @@ LOCAL int find_address_in_search_tree(MMDB_s *mmdb, uint8_t *address,
MMDB_lookup_result_s *result);
LOCAL record_info_s record_info_for_database(MMDB_s *mmdb);
LOCAL int find_ipv4_start_node(MMDB_s *mmdb);
LOCAL int populate_result(MMDB_s *mmdb, uint32_t node_count, uint32_t value,
uint16_t netmask, MMDB_lookup_result_s *result);
LOCAL uint8_t maybe_populate_result(MMDB_s *mmdb, uint32_t record,
uint16_t netmask,
MMDB_lookup_result_s *result);
LOCAL uint8_t record_type(MMDB_s *const mmdb, uint64_t record);
LOCAL uint32_t get_left_28_bit_record(const uint8_t *record);
LOCAL uint32_t get_right_28_bit_record(const uint8_t *record);
LOCAL uint32_t data_section_offset_for_record(MMDB_s *const mmdb,
uint64_t record);
LOCAL int path_length(va_list va_path);
LOCAL int lookup_path_in_array(const char *path_elem, MMDB_s *mmdb,
MMDB_entry_data_s *entry_data);
@ -194,20 +198,24 @@ LOCAL char *bytes_to_hex(uint8_t *bytes, uint32_t size);
/* --prototypes end - don't remove this comment-- */
/* *INDENT-ON* */
#define CHECKED_DECODE_ONE(mmdb, offset, entry_data) \
do { \
int status = decode_one(mmdb, offset, entry_data); \
if (MMDB_SUCCESS != status) { \
return status; \
} \
#define CHECKED_DECODE_ONE(mmdb, offset, entry_data) \
do { \
int status = decode_one(mmdb, offset, entry_data); \
if (MMDB_SUCCESS != status) { \
DEBUG_MSGF("CHECKED_DECODE_ONE failed." \
" status = %d (%s)", status, MMDB_strerror(status)); \
return status; \
} \
} while (0)
#define CHECKED_DECODE_ONE_FOLLOW(mmdb, offset, entry_data) \
do { \
int status = decode_one_follow(mmdb, offset, entry_data); \
if (MMDB_SUCCESS != status) { \
return status; \
} \
#define CHECKED_DECODE_ONE_FOLLOW(mmdb, offset, entry_data) \
do { \
int status = decode_one_follow(mmdb, offset, entry_data); \
if (MMDB_SUCCESS != status) { \
DEBUG_MSGF("CHECKED_DECODE_ONE_FOLLOW failed." \
" status = %d (%s)", status, MMDB_strerror(status)); \
return status; \
} \
} while (0)
#define FREE_AND_SET_NULL(p) { free((void *)(p)); (p) = NULL; }
@ -266,12 +274,15 @@ int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb)
uint32_t search_tree_size = mmdb->metadata.node_count *
mmdb->full_record_byte_size;
mmdb->data_section = mmdb->file_content + search_tree_size;
if (search_tree_size > (uint32_t)mmdb->file_size) {
mmdb->data_section = mmdb->file_content + search_tree_size
+ MMDB_DATA_SECTION_SEPARATOR;
if (search_tree_size + MMDB_DATA_SECTION_SEPARATOR >
(uint32_t)mmdb->file_size) {
status = MMDB_INVALID_METADATA_ERROR;
goto cleanup;
}
mmdb->data_section_size = mmdb->file_size - search_tree_size;
mmdb->data_section_size = (uint32_t)mmdb->file_size - search_tree_size -
MMDB_DATA_SECTION_SEPARATOR;
mmdb->metadata_section = metadata;
mmdb->ipv4_start_node.node_value = 0;
mmdb->ipv4_start_node.netmask = 0;
@ -289,7 +300,7 @@ int MMDB_open(const char *const filename, uint32_t flags, MMDB_s *const mmdb)
LOCAL int map_file(MMDB_s *const mmdb)
{
ssize_t size;
DWORD size;
int status = MMDB_SUCCESS;
HANDLE mmh = NULL;
HANDLE fd = CreateFileA(mmdb->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
@ -410,7 +421,7 @@ LOCAL const uint8_t *find_metadata(const uint8_t *file_content,
return NULL;
}
*metadata_size = max_size;
*metadata_size = (uint32_t)max_size;
return search_area;
}
@ -688,6 +699,7 @@ LOCAL int populate_description_metadata(MMDB_s *mmdb, MMDB_s *metadata_db,
}
if (MMDB_DATA_TYPE_MAP != entry_data.type) {
DEBUG_MSGF("Unexpected entry_data type: %d", entry_data.type);
return MMDB_INVALID_METADATA_ERROR;
}
@ -699,6 +711,9 @@ LOCAL int populate_description_metadata(MMDB_s *mmdb, MMDB_s *metadata_db,
MMDB_entry_data_list_s *member;
status = MMDB_get_entry_data_list(&map_start, &member);
if (MMDB_SUCCESS != status) {
DEBUG_MSGF(
"MMDB_get_entry_data_list failed while populating description."
" status = %d (%s)", status, MMDB_strerror(status));
return status;
}
@ -802,8 +817,8 @@ MMDB_lookup_result_s MMDB_lookup_string(MMDB_s *const mmdb,
LOCAL int resolve_any_address(const char *ipstr, struct addrinfo **addresses)
{
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_flags = AI_NUMERICHOST,
.ai_family = AF_UNSPEC,
.ai_flags = AI_NUMERICHOST,
// We set ai_socktype so that we only get one result back
.ai_socktype = SOCK_STREAM
};
@ -869,7 +884,6 @@ LOCAL int find_address_in_search_tree(MMDB_s *mmdb, uint8_t *address,
DEBUG_NL;
DEBUG_MSG("Looking for address in search tree");
uint32_t node_count = mmdb->metadata.node_count;
uint32_t value = 0;
uint16_t max_depth0 = mmdb->depth - 1;
uint16_t start_bit = max_depth0;
@ -882,12 +896,18 @@ LOCAL int find_address_in_search_tree(MMDB_s *mmdb, uint8_t *address,
DEBUG_MSGF("IPv4 start node is %u (netmask %u)",
mmdb->ipv4_start_node.node_value,
mmdb->ipv4_start_node.netmask);
uint8_t type = maybe_populate_result(mmdb,
mmdb->ipv4_start_node.node_value,
mmdb->ipv4_start_node.netmask,
result);
if (MMDB_RECORD_TYPE_INVALID == type) {
return MMDB_CORRUPT_SEARCH_TREE_ERROR;
}
/* We have an IPv6 database with no IPv4 data */
if (mmdb->ipv4_start_node.node_value >= node_count) {
return populate_result(mmdb, node_count,
mmdb->ipv4_start_node.node_value,
mmdb->ipv4_start_node.netmask,
result);
if (MMDB_RECORD_TYPE_SEARCH_NODE != type) {
return MMDB_SUCCESS;
}
value = mmdb->ipv4_start_node.node_value;
@ -916,20 +936,17 @@ LOCAL int find_address_in_search_tree(MMDB_s *mmdb, uint8_t *address,
value = record_info.left_record_getter(record_pointer);
}
/* Ideally we'd check to make sure that a record never points to a
* previously seen value, but that's more complicated. For now, we can
* at least check that we don't end up at the top of the tree again. */
if (0 == value) {
DEBUG_MSGF(" %s record has a value of 0",
bit_is_true ? "right" : "left");
uint8_t type = maybe_populate_result(mmdb, value, (uint16_t)current_bit,
result);
if (MMDB_RECORD_TYPE_INVALID == type) {
return MMDB_CORRUPT_SEARCH_TREE_ERROR;
}
if (value >= node_count) {
return populate_result(mmdb, node_count, value, current_bit, result);
} else {
DEBUG_MSGF(" proceeding to search tree node %i", value);
if (MMDB_RECORD_TYPE_SEARCH_NODE != type) {
return MMDB_SUCCESS;
}
DEBUG_MSGF(" proceeding to search tree node %i", value);
}
DEBUG_MSG(
@ -979,7 +996,7 @@ LOCAL int find_ipv4_start_node(MMDB_s *mmdb)
const uint8_t *search_tree = mmdb->file_content;
uint32_t node_value = 0;
const uint8_t *record_pointer;
uint32_t netmask;
uint16_t netmask;
for (netmask = 0; netmask < 96; netmask++) {
record_pointer = &search_tree[node_value * record_info.record_length];
if (record_pointer + record_info.record_length > mmdb->data_section) {
@ -999,20 +1016,54 @@ LOCAL int find_ipv4_start_node(MMDB_s *mmdb)
return MMDB_SUCCESS;
}
LOCAL int populate_result(MMDB_s *mmdb, uint32_t node_count, uint32_t value,
uint16_t netmask, MMDB_lookup_result_s *result)
LOCAL uint8_t maybe_populate_result(MMDB_s *mmdb, uint32_t record,
uint16_t netmask,
MMDB_lookup_result_s *result)
{
uint32_t offset = value - node_count;
DEBUG_MSGF(" data section offset is %i (record value = %i)", offset, value);
uint8_t type = record_type(mmdb, record);
if (offset > mmdb->data_section_size) {
return MMDB_CORRUPT_SEARCH_TREE_ERROR;
if (MMDB_RECORD_TYPE_SEARCH_NODE == type ||
MMDB_RECORD_TYPE_INVALID == type) {
return type;
}
result->netmask = mmdb->depth - netmask;
result->entry.offset = offset;
result->found_entry = result->entry.offset > 0 ? true : false;
return MMDB_SUCCESS;
result->entry.offset = data_section_offset_for_record(mmdb, record);
// type is either MMDB_RECORD_TYPE_DATA or MMDB_RECORD_TYPE_EMPTY
// at this point
result->found_entry = MMDB_RECORD_TYPE_DATA == type;
return type;
}
LOCAL uint8_t record_type(MMDB_s *const mmdb, uint64_t record)
{
uint32_t node_count = mmdb->metadata.node_count;
/* Ideally we'd check to make sure that a record never points to a
* previously seen value, but that's more complicated. For now, we can
* at least check that we don't end up at the top of the tree again. */
if (record == 0) {
DEBUG_MSG("record has a value of 0");
return MMDB_RECORD_TYPE_INVALID;
}
if (record < node_count) {
return MMDB_RECORD_TYPE_SEARCH_NODE;
}
if (record == node_count) {
return MMDB_RECORD_TYPE_EMPTY;
}
if (record - node_count < mmdb->data_section_size) {
return MMDB_RECORD_TYPE_DATA;
}
DEBUG_MSG("record has a value that points outside of the database");
return MMDB_RECORD_TYPE_INVALID;
}
LOCAL uint32_t get_left_28_bit_record(const uint8_t *record)
@ -1046,9 +1097,31 @@ int MMDB_read_node(MMDB_s *const mmdb, uint32_t node_number,
record_pointer += record_info.right_record_offset;
node->right_record = record_info.right_record_getter(record_pointer);
node->left_record_type = record_type(mmdb, node->left_record);
node->right_record_type = record_type(mmdb, node->right_record);
// Note that offset will be invalid if the record type is not
// MMDB_RECORD_TYPE_DATA, but that's ok. Any use of the record entry
// for other data types is a programming error.
node->left_record_entry = (struct MMDB_entry_s) {
.mmdb = mmdb,
.offset = data_section_offset_for_record(mmdb, node->left_record),
};
node->right_record_entry = (struct MMDB_entry_s) {
.mmdb = mmdb,
.offset = data_section_offset_for_record(mmdb, node->right_record),
};
return MMDB_SUCCESS;
}
LOCAL uint32_t data_section_offset_for_record(MMDB_s *const mmdb,
uint64_t record)
{
return (uint32_t)record - mmdb->metadata.node_count -
MMDB_DATA_SECTION_SEPARATOR;
}
int MMDB_get_value(MMDB_entry_s *const start,
MMDB_entry_data_s *const entry_data,
...)
@ -1312,6 +1385,8 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
const uint8_t *mem = mmdb->data_section;
if (offset + 1 > mmdb->data_section_size) {
DEBUG_MSGF("Offset (%d) past data section (%d)", offset,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
@ -1329,6 +1404,9 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
if (type == MMDB_DATA_TYPE_EXTENDED) {
if (offset + 1 > mmdb->data_section_size) {
DEBUG_MSGF("Extended type offset (%d) past data section (%d)",
offset,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
type = get_ext_type(mem[offset++]);
@ -1338,17 +1416,20 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
entry_data->type = type;
if (type == MMDB_DATA_TYPE_POINTER) {
int psize = (ctrl >> 3) & 3;
int psize = ((ctrl >> 3) & 3) + 1;
DEBUG_MSGF("Pointer size: %i", psize);
if (offset + psize + 1 > mmdb->data_section_size) {
if (offset + psize > mmdb->data_section_size) {
DEBUG_MSGF("Pointer offset (%d) past data section (%d)", offset +
psize,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
entry_data->pointer = get_ptr_from(ctrl, &mem[offset], psize);
DEBUG_MSGF("Pointer to: %i", entry_data->pointer);
entry_data->data_size = psize + 1;
entry_data->offset_to_next = offset + psize + 1;
entry_data->data_size = psize;
entry_data->offset_to_next = offset + psize;
return MMDB_SUCCESS;
}
@ -1356,12 +1437,18 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
switch (size) {
case 29:
if (offset + 1 > mmdb->data_section_size) {
DEBUG_MSGF("String end (%d, case 29) past data section (%d)",
offset,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
size = 29 + mem[offset++];
break;
case 30:
if (offset + 2 > mmdb->data_section_size) {
DEBUG_MSGF("String end (%d, case 30) past data section (%d)",
offset,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
size = 285 + get_uint16(&mem[offset]);
@ -1369,6 +1456,9 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
break;
case 31:
if (offset + 3 > mmdb->data_section_size) {
DEBUG_MSGF("String end (%d, case 31) past data section (%d)",
offset,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
size = 65821 + get_uint24(&mem[offset]);
@ -1396,35 +1486,42 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
// check that the data doesn't extend past the end of the memory
// buffer
if (offset + size > mmdb->data_section_size) {
DEBUG_MSGF("Data end (%d) past data section (%d)", offset + size,
mmdb->data_section_size);
return MMDB_INVALID_DATA_ERROR;
}
if (type == MMDB_DATA_TYPE_UINT16) {
if (size > 2) {
DEBUG_MSGF("uint16 of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
entry_data->uint16 = (uint16_t)get_uintX(&mem[offset], size);
DEBUG_MSGF("uint16 value: %u", entry_data->uint16);
} else if (type == MMDB_DATA_TYPE_UINT32) {
if (size > 4) {
DEBUG_MSGF("uint32 of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
entry_data->uint32 = (uint32_t)get_uintX(&mem[offset], size);
DEBUG_MSGF("uint32 value: %u", entry_data->uint32);
} else if (type == MMDB_DATA_TYPE_INT32) {
if (size > 4) {
DEBUG_MSGF("int32 of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
entry_data->int32 = get_sintX(&mem[offset], size);
DEBUG_MSGF("int32 value: %i", entry_data->int32);
} else if (type == MMDB_DATA_TYPE_UINT64) {
if (size > 8) {
DEBUG_MSGF("uint64 of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
entry_data->uint64 = get_uintX(&mem[offset], size);
DEBUG_MSGF("uint64 value: %" PRIu64, entry_data->uint64);
} else if (type == MMDB_DATA_TYPE_UINT128) {
if (size > 16) {
DEBUG_MSGF("uint128 of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
#if MMDB_UINT128_IS_BYTE_ARRAY
@ -1437,6 +1534,7 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
#endif
} else if (type == MMDB_DATA_TYPE_FLOAT) {
if (size != 4) {
DEBUG_MSGF("float of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
size = 4;
@ -1444,6 +1542,7 @@ LOCAL int decode_one(MMDB_s *mmdb, uint32_t offset,
DEBUG_MSGF("float value: %f", entry_data->float_value);
} else if (type == MMDB_DATA_TYPE_DOUBLE) {
if (size != 8) {
DEBUG_MSGF("double of size %d", size);
return MMDB_INVALID_DATA_ERROR;
}
size = 8;
@ -1481,21 +1580,21 @@ LOCAL uint32_t get_ptr_from(uint8_t ctrl, uint8_t const *const ptr,
{
uint32_t new_offset;
switch (ptr_size) {
case 0:
new_offset = (ctrl & 7) * 256 + ptr[0];
break;
case 1:
new_offset = 2048 + (ctrl & 7) * 65536 + ptr[0] * 256 + ptr[1];
new_offset = ( (ctrl & 7) << 8) + ptr[0];
break;
case 2:
new_offset = 2048 + 524288 + (ctrl & 7) * 16777216 + get_uint24(ptr);
new_offset = 2048 + ( (ctrl & 7) << 16 ) + ( ptr[0] << 8) + ptr[1];
break;
case 3:
new_offset = 2048 + 524288 + ( (ctrl & 7) << 24 ) + get_uint24(ptr);
break;
case 4:
default:
new_offset = get_uint32(ptr);
break;
}
return MMDB_DATA_SECTION_SEPARATOR + new_offset;
return new_offset;
}
int MMDB_get_metadata_as_entry_data_list(
@ -1554,6 +1653,7 @@ LOCAL int get_entry_data_list(MMDB_s *mmdb, uint32_t offset,
get_entry_data_list(mmdb, last_offset, entry_data_list,
depth);
if (MMDB_SUCCESS != status) {
DEBUG_MSG("get_entry_data_list on pointer failed.");
return status;
}
}
@ -1576,6 +1676,7 @@ LOCAL int get_entry_data_list(MMDB_s *mmdb, uint32_t offset,
get_entry_data_list(mmdb, array_offset, entry_data_list_to,
depth);
if (MMDB_SUCCESS != status) {
DEBUG_MSG("get_entry_data_list on array element failed.");
return status;
}
@ -1605,6 +1706,7 @@ LOCAL int get_entry_data_list(MMDB_s *mmdb, uint32_t offset,
get_entry_data_list(mmdb, offset, entry_data_list_to,
depth);
if (MMDB_SUCCESS != status) {
DEBUG_MSG("get_entry_data_list on map key failed.");
return status;
}
@ -1623,6 +1725,7 @@ LOCAL int get_entry_data_list(MMDB_s *mmdb, uint32_t offset,
status = get_entry_data_list(mmdb, offset, entry_data_list_to,
depth);
if (MMDB_SUCCESS != status) {
DEBUG_MSG("get_entry_data_list on map element failed.");
return status;
}
@ -1645,7 +1748,9 @@ LOCAL float get_ieee754_float(const uint8_t *restrict p)
{
volatile float f;
uint8_t *q = (void *)&f;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
/* Windows builds don't use autoconf but we can assume they're all
* little-endian. */
#if MMDB_LITTLE_ENDIAN || _WIN32
q[3] = p[0];
q[2] = p[1];
q[1] = p[2];
@ -1660,7 +1765,7 @@ LOCAL double get_ieee754_double(const uint8_t *restrict p)
{
volatile double d;
uint8_t *q = (void *)&d;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#if MMDB_LITTLE_ENDIAN || _WIN32
q[7] = p[0];
q[6] = p[1];
q[5] = p[2];