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 |
| : :' : [email protected] |
| `. `' 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;