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;

Reply via email to