Hi, Sorry, the previous patch didn't check for a failure to load the new database, and also always loaded a new database even when it didn't need to. Better patch attached now.
Cheers, -- ----------------------------------------------------------------- | ,''`. Stephen Gran | | : :' : sg...@debian.org | | `. `' Debian user, admin, and developer | | `- http://www.debian.org | -----------------------------------------------------------------
--- geoip-1.4.6.dfsg.orig/libGeoIP/GeoIP.c +++ geoip-1.4.6.dfsg/libGeoIP/GeoIP.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "GeoIP.h" +#include "GeoIP_internal.h" static geoipv6_t IPV6_NULL; @@ -27,6 +27,11 @@ static geoipv6_t IPV6_NULL; #include <sys/mman.h> #endif /* !defined(_WIN32) */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -501,6 +506,52 @@ int _check_mtime(GeoIP *gi) { #define ADDR_STR_LEN (8 * 4 + 7 + 1) unsigned int _GeoIP_seek_record_v6 (GeoIP *gi, geoipv6_t ipnum) { + + /* + * First we check the v6 address to see if it looks like a 6to4 address. + * These begin with 2002:, so it's a fairly easy prefix to check, but we + * have to deal with it in a way that deals with endian issues, so it's not + * all that pretty. Sadly, we don't seem to have portable macros like htonl + * for this v6 funtion just yet. Using a cast to uint32_t so that we get + * the first 4 bytes of the address (as the prefix will actually be in the + * lower two bytes on little endian machines) + */ + +#ifdef _BIG_ENDIAN + if ((((__const uint32_t *) (ipnum.s6_addr))[0] & 0xffff0000) == 0x20020000) { +#else /* _BIG_ENDIAN */ + if ((((__const uint32_t *) (ipnum.s6_addr))[0] & 0x0000ffff) == 0x00000220) { +#endif /* _BIG_ENDIAN */ + + struct in_addr v4; + memset(&v4, 0, sizeof(struct in_addr)); + int part; + unsigned int ret; + + /* + * The v6 address field is uint8_t[16], and the first two members of that + * array are taken up the 2002: prefix. We want to iterate the next 4, as + * that will get us the mapped v4 address back. We don't have to worry about + * endian issues here, as the rest of the code seems to keep ip addresses + * in whichever form is native to the architecture. + */ + + for (part = 2; part <= 5; part++) { + v4.s_addr <<= 8; + v4.s_addr |= (((__const uint8_t *) (ipnum.s6_addr))[part]); + } + + if (gi->databaseType == GEOIP_COUNTRY_EDITION_V6) { + GeoIP *gi2 = GeoIP_open_type(GEOIP_COUNTRY_EDITION, gi->flags); + if (NULL == gi2) + return 0; + ret = _GeoIP_seek_record(gi2, v4.s_addr); + free(gi2); + return ret; + } + return _GeoIP_seek_record(gi, v4.s_addr); + } + int depth; char paddr[ADDR_STR_LEN]; unsigned int x;