diff --git a/config/gcc32/maxminddb_config.h b/config/gcc32/maxminddb_config.h new file mode 100644 index 00000000..12e934e9 --- /dev/null +++ b/config/gcc32/maxminddb_config.h @@ -0,0 +1,195 @@ +/* include/maxminddb_config.h. Generated from maxminddb_config.h.in by configure. */ +#ifndef MAXMINDDB_CONFIG_H +#define MAXMINDDB_CONFIG_H +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if the system has the type `boolean'. */ +/* #undef HAVE_BOOLEAN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Has an open_memstream() function */ +#define HAVE_OPEN_MEMSTREAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Missing the unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 1 + +/* int128 types are available with __attribute__((mode(TI))) */ +/* #undef MMDB_UINT128_USING_MODE */ + +/* Name of package */ +#define PACKAGE "libmaxminddb" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "support@maxmind.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libmaxminddb" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libmaxminddb 1.2.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libmaxminddb" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.0" + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#define restrict __restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ + +#ifndef MMDB_UINT128_USING_MODE +/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */ +#define MMDB_UINT128_USING_MODE 0 +#endif + +#ifndef MMDB_UINT128_IS_BYTE_ARRAY +/* Define as 1 if we don't have an unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 0 +#endif + +#endif /* MAXMINDDB_CONFIG_H */ diff --git a/config/gcc64/maxminddb_config.h b/config/gcc64/maxminddb_config.h new file mode 100644 index 00000000..1f522e90 --- /dev/null +++ b/config/gcc64/maxminddb_config.h @@ -0,0 +1,195 @@ +/* include/maxminddb_config.h. Generated from maxminddb_config.h.in by configure. */ +#ifndef MAXMINDDB_CONFIG_H +#define MAXMINDDB_CONFIG_H +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if the system has the type `boolean'. */ +/* #undef HAVE_BOOLEAN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Has an open_memstream() function */ +#define HAVE_OPEN_MEMSTREAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Missing the unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 0 + +/* int128 types are available with __attribute__((mode(TI))) */ +/* #undef MMDB_UINT128_USING_MODE */ + +/* Name of package */ +#define PACKAGE "libmaxminddb" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "support@maxmind.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libmaxminddb" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libmaxminddb 1.2.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libmaxminddb" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.0" + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#define restrict __restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ + +#ifndef MMDB_UINT128_USING_MODE +/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */ +#define MMDB_UINT128_USING_MODE 0 +#endif + +#ifndef MMDB_UINT128_IS_BYTE_ARRAY +/* Define as 1 if we don't have an unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 0 +#endif + +#endif /* MAXMINDDB_CONFIG_H */ diff --git a/config/mingw32/maxminddb_config.h b/config/mingw32/maxminddb_config.h index 61bd5f3e..57a644e5 100644 --- a/config/mingw32/maxminddb_config.h +++ b/config/mingw32/maxminddb_config.h @@ -3,7 +3,7 @@ #define MAXMINDDB_CONFIG_H /* Define to 1 if you have the header file. */ -#define HAVE_ARPA_INET_H 1 +/* #undef HAVE_ARPA_INET_H */ /* Define to 1 if you have the header file. */ #define HAVE_ASSERT_H 1 @@ -12,7 +12,7 @@ /* #undef HAVE_BOOLEAN */ /* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 +/* #undef HAVE_DLFCN_H */ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 @@ -37,16 +37,16 @@ #define HAVE_MEMORY_H 1 /* Define to 1 if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 +/* #undef HAVE_MMAP */ /* Define to 1 if you have the header file. */ -#define HAVE_NETDB_H 1 +/* #undef HAVE_NETDB_H */ /* Define to 1 if you have the header file. */ -#define HAVE_NETINET_IN_H 1 +/* #undef HAVE_NETINET_IN_H */ /* Has an open_memstream() function */ -#define HAVE_OPEN_MEMSTREAM 1 +/* #undef HAVE_OPEN_MEMSTREAM */ /* Define to 1 if you have the header file. */ #define HAVE_STDARG_H 1 @@ -70,13 +70,13 @@ #define HAVE_STRING_H 1 /* Define to 1 if you have the header file. */ -#define HAVE_SYS_MMAN_H 1 +/* #undef HAVE_SYS_MMAN_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ -#define HAVE_SYS_SOCKET_H 1 +/* #undef HAVE_SYS_SOCKET_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 @@ -110,7 +110,7 @@ #define PACKAGE_NAME "libmaxminddb" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libmaxminddb 1.1.4" +#define PACKAGE_STRING "libmaxminddb 1.2.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libmaxminddb" @@ -119,13 +119,13 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.1.4" +#define PACKAGE_VERSION "1.2.0" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "1.1.4" +#define VERSION "1.2.0" /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the diff --git a/config/mingw64/maxminddb_config.h b/config/mingw64/maxminddb_config.h new file mode 100644 index 00000000..8971512f --- /dev/null +++ b/config/mingw64/maxminddb_config.h @@ -0,0 +1,193 @@ +/* include/maxminddb_config.h. Generated from maxminddb_config.h.in by configure. */ +#ifndef MAXMINDDB_CONFIG_H +#define MAXMINDDB_CONFIG_H + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if the system has the type `boolean'. */ +/* #undef HAVE_BOOLEAN */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have a working `mmap' system call. */ +/* #undef HAVE_MMAP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Has an open_memstream() function */ +/* #undef HAVE_OPEN_MEMSTREAM */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDARG_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_MMAN_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Missing the unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 0 + +/* int128 types are available with __attribute__((mode(TI))) */ +/* #undef MMDB_UINT128_USING_MODE */ + +/* Name of package */ +#define PACKAGE "libmaxminddb" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "support@maxmind.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libmaxminddb" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libmaxminddb 1.2.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libmaxminddb" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.2.0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "1.2.0" + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT32_T */ + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT64_T */ + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +/* #undef _UINT8_T */ + +/* Define to rpl_malloc if the replacement function should be used. */ +/* #undef malloc */ + +/* Define to `long int' if does not define. */ +/* #undef off_t */ + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#define restrict __restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* Define to `int' if does not define. */ +/* #undef ssize_t */ + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint32_t */ + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint64_t */ + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +/* #undef uint8_t */ + +#ifndef MMDB_UINT128_USING_MODE +/* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */ +#define MMDB_UINT128_USING_MODE 0 +#endif + +#ifndef MMDB_UINT128_IS_BYTE_ARRAY +/* Define as 1 if we don't have an unsigned __int128 type */ +#define MMDB_UINT128_IS_BYTE_ARRAY 0 +#endif + +#endif /* MAXMINDDB_CONFIG_H */ diff --git a/external/MaxmindDB/maxminddb.c b/external/MaxmindDB/maxminddb.c index 4b98c88e..a7780c89 100644 --- a/external/MaxmindDB/maxminddb.c +++ b/external/MaxmindDB/maxminddb.c @@ -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]; diff --git a/include/maxminddb.h b/include/maxminddb.h index 76ce9377..2aaa4634 100644 --- a/include/maxminddb.h +++ b/include/maxminddb.h @@ -9,7 +9,7 @@ extern "C" { #define _POSIX_C_SOURCE 200112L #endif -#include +#include "maxminddb_config.h" #include #include #include @@ -20,13 +20,13 @@ extern "C" { #include #include /* libmaxminddb package version from configure */ -#define PACKAGE_VERSION "1.1.4" +#define PACKAGE_VERSION "1.2.0" typedef ADDRESS_FAMILY sa_family_t; #if defined(_MSC_VER) /* MSVC doesn't define signed size_t, copy it from configure */ -#define ssize_t int +#define ssize_t SSIZE_T /* MSVC doesn't support restricted pointers */ #define restrict @@ -54,6 +54,11 @@ typedef ADDRESS_FAMILY sa_family_t; #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) + /* flags for open */ #define MMDB_MODE_MMAP (1) #define MMDB_MODE_MASK (7) @@ -178,6 +183,10 @@ typedef struct 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; /* *INDENT-OFF* */