# Add IPv6 support to GeoIP module

**URL:** <https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477>\
**Category:** NGINX\
**Created:** [October 4, 2011, 9:22am UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477 "2011-10-04T09:22:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [October 4, 2011, 9:22am UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/1 "2011-10-04T09:22:55Z")

</div>

Hello all,

geoip module currently only supports a single country and a single city  
MaxMind database that must cover IPv4 address range.

Below patch allows setting up to two city and country databases, one  
for IPv4 and one for IPv6. It then looks-up the requesting IP address in  
the appropriate database.

Please review and consider applying,

Bruno

diff -NurpP nginx-1.0.4.orig/src/http/modules/ngx\_http\_geoip\_module.c  
nginx-1.0.4/src/http/modules/ngx\_http\_geoip\_module.c  
— nginx-1.0.4.orig/src/http/modules/ngx\_http\_geoip\_module.c  
2011-05-16 15:50:58.000000000 +0200  
+++ nginx-1.0.4/src/http/modules/ngx\_http\_geoip\_module.c 2011-09-30  
10:30:18.785083263 +0200  
@@ -16,6 +16,9 @@ typedef struct {  
GeoIP \*country;  
GeoIP \*org;  
GeoIP \*city;

- GeoIP \*country\_v6;
- GeoIP \*org\_v6;
- GeoIP \*city\_v6;  
} ngx\_http\_geoip\_conf\_t;

@@ -26,8 +29,13 @@ typedef struct {

typedef const char \*(\*ngx\_http\_geoip\_variable\_handler\_pt)(GeoIP \*,  
u\_long addr);  
+typedef const char \*(\*ngx\_http\_geoip\_variable\_handler6\_pt)(GeoIP \*,  
struct in6\_addr addr);

-static ngx\_int\_t ngx\_http\_geoip\_country\_variable(ngx\_http\_request\_t \*r,  
+static ngx\_int\_t  
ngx\_http\_geoip\_country\_code\_variable(ngx\_http\_request\_t \*r,

- ngx\_http\_variable\_value\_t \*v, uintptr\_t data);  
+static ngx\_int\_t  
ngx\_http\_geoip\_country\_code3\_variable(ngx\_http\_request\_t \*r,

- ngx\_http\_variable\_value\_t \*v, uintptr\_t data);  
+static ngx\_int\_t  
ngx\_http\_geoip\_country\_name\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v, uintptr\_t data);  
static ngx\_int\_t ngx\_http\_geoip\_org\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v, uintptr\_t data);  
@@ -113,16 +121,16 @@ ngx\_module\_t ngx\_http\_geoip\_module = {  
static ngx\_http\_variable\_t ngx\_http\_geoip\_vars[] = {

- 

```
 ngx_http_geoip_country_variable,

```

- 

```
 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },

```

- 

```
 ngx_http_geoip_country_code_variable,

```

- 

```
 0, 0, 0 },

```

{ ngx\_string(“geoip\_country\_code3”), NULL,

- 

```
 ngx_http_geoip_country_variable,

```

- 

```
 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },

```

- 

```
 ngx_http_geoip_country_code3_variable,

```

- 

```
 0, 0, 0 },

```

{ ngx\_string(“geoip\_country\_name”), NULL,

- 

```
 ngx_http_geoip_country_variable,

```

- 

```
 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },

```

- 

```
 ngx_http_geoip_country_name_variable,

```

- 

```
 0, 0, 0 },

```

{ ngx\_string(“geoip\_org”), NULL,  
ngx\_http\_geoip\_org\_variable,  
@@ -180,117 +188,146 @@ static ngx\_http\_variable\_t ngx\_http\_geo  
};

-static u\_long  
-ngx\_http\_geoip\_addr(ngx\_http\_request\_t \*r)  
+static ngx\_int\_t  
+ngx\_http\_geoip\_get\_char(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v,

- GeoIP \*src, ngx\_http\_geoip\_variable\_handler\_pt handler,
- GeoIP \*src\_v6, ngx\_http\_geoip\_variable\_handler6\_pt handler\_v6)  
{

- struct sockaddr\_in \*sin;  
-#if (NGX\_HAVE\_INET6)
- u\_char \*p;
- u\_long addr;
- struct sockaddr\_in6 \*sin6;  
-#endif
- 

- const char \*ret = NULL;  
switch (r-\>connection-\>sockaddr-\>sa\_family) {

- case AF\_INET:
- 

```
   sin = (struct sockaddr_in *) r->connection->sockaddr;

```

- 

```
   return ntohl(sin->sin_addr.s_addr);

```

- 

- 

```
   if (src) {

```

- 

```
       struct sockaddr_in *sin = (struct sockaddr_in *) 

```

r-\>connection-\>sockaddr;

- 

```
       ret = handler(src, ntohl(sin->sin_addr.s_addr));

```

- 

```
   }

```

- 

```
   break;

```

## #if (NGX\_HAVE\_INET6)

```
 case AF_INET6:

```

- 

```
   sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;

```

- 
- 

```
   if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {

```

- 

```
       p = sin6->sin6_addr.s6_addr;

```

- 

```
       addr = p[12] << 24;

```

- 

```
       addr += p[13] << 16;

```

- 

```
       addr += p[14] << 8;

```

- 

```
       addr += p[15];

```

- 
- 

```
       return addr;

```

- 

```
   if (src_v6) {

```

- 

```
       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 

```

r-\>connection-\>sockaddr;

- 

```
       if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {

```

- 

```
           u_char *p = sin6->sin6_addr.s6_addr;

```

- 

```
           ret = src ? handler(src, (p[12] << 24) + (p[13] << 16) 

```

- (p[14] \<\< 8) + p[15]) : NULL;
- 

```
       } else

```

- 

```
           ret = handler_v6(src_v6, sin6->sin6_addr);
   }

```

- 

- 

```
   break;

```

#endif  
}

- return INADDR\_NONE;

- if (ret == NULL) {
- 

```
   goto not_found;

```

- }
- 
- v-\>len = ngx\_strlen(ret);
- v-\>valid = 1;
- v-\>no\_cacheable = 0;
- v-\>not\_found = 0;
- v-\>data = (u\_char \*) ret;
- 
- return NGX\_OK;
- 

+not\_found:  
+

- v-\>not\_found = 1;
- 
- return NGX\_OK;  
}

static ngx\_int\_t  
-ngx\_http\_geoip\_country\_variable(ngx\_http\_request\_t \*r,  
+ngx\_http\_geoip\_country\_code\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v, uintptr\_t data)  
{

- ngx\_http\_geoip\_variable\_handler\_pt handler =

- 

```
   (ngx_http_geoip_variable_handler_pt) data;

```

- 
- const char \*val;  
ngx\_http\_geoip\_conf\_t \*gcf;

- if (gcf-\>country == NULL) {

- 

```
   goto not_found;

```

- if (gcf-\>country == NULL && gcf-\>country\_v6 == NULL) {
- 

```
   v->not_found = 1;

```

- 
- 

```
   return NGX_OK;

```

}

- val = handler(gcf-\>country, ngx\_http\_geoip\_addr®);

- return ngx\_http\_geoip\_get\_char(r, v, gcf-\>country,  
&GeoIP\_country\_code\_by\_ipnum,  
+#if (NGX\_HAVE\_INET6)
- 

```
                gcf->country_v6, &GeoIP_country_code_by_ipnum_v6

```

+#else

- 

```
                NULL, NULL

```

+#endif

- 

```
                );

```

+}

- if (val == NULL) {

- 

```
   goto not_found;

```

- }

- v-\>len = ngx\_strlen(val);

- v-\>valid = 1;

- v-\>no\_cacheable = 0;

- v-\>not\_found = 0;

- v-\>data = (u\_char \*) val;  
+static ngx\_int\_t  
+ngx\_http\_geoip\_country\_code3\_variable(ngx\_http\_request\_t \*r,

- ngx\_http\_variable\_value\_t \*v, uintptr\_t data)  
+{
- ngx\_http\_geoip\_conf\_t \*gcf;

- return NGX\_OK;

- gcf = ngx\_http\_get\_module\_main\_conf(r, ngx\_http\_geoip\_module);

-not\_found:

- if (gcf-\>country == NULL && gcf-\>country\_v6 == NULL) {
- 

```
   v->not_found = 1;

```

- v-\>not\_found = 1;

- 

```
   return NGX_OK;

```

- }

- return NGX\_OK;

- return ngx\_http\_geoip\_get\_char(r, v, gcf-\>country,  
&GeoIP\_country\_code3\_by\_ipnum,  
+#if (NGX\_HAVE\_INET6)
- 

```
                gcf->country_v6, &GeoIP_country_code3_by_ipnum_v6

```

+#else

- 

```
                NULL, NULL

```

+#endif

- 

```
                );

```

}

static ngx\_int\_t  
-ngx\_http\_geoip\_org\_variable(ngx\_http\_request\_t \*r,  
+ngx\_http\_geoip\_country\_name\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v, uintptr\_t data)  
{

- ngx\_http\_geoip\_variable\_handler\_pt handler =

- 

```
   (ngx_http_geoip_variable_handler_pt) data;

```

- 
- const char \*val;  
ngx\_http\_geoip\_conf\_t \*gcf;

- if (gcf-\>org == NULL) {

- 

```
   goto not_found;

```

- if (gcf-\>country == NULL && gcf-\>country\_v6 == NULL) {
- 

```
   v->not_found = 1;

```

- 
- 

```
   return NGX_OK;

```

}

- val = handler(gcf-\>org, ngx\_http\_geoip\_addr®);

- return ngx\_http\_geoip\_get\_char(r, v, gcf-\>country,  
&GeoIP\_country\_name\_by\_ipnum,  
+#if (NGX\_HAVE\_INET6)
- 

```
                gcf->country_v6, &GeoIP_country_name_by_ipnum_v6

```

+#else

- 

```
                NULL, NULL

```

+#endif

- 

```
                );

```

+}

- if (val == NULL) {

- 

```
   goto not_found;

```

- }

- v-\>len = ngx\_strlen(val);

- v-\>valid = 1;

- v-\>no\_cacheable = 0;

- v-\>not\_found = 0;

- v-\>data = (u\_char \*) val;  
+static ngx\_int\_t  
+ngx\_http\_geoip\_org\_variable(ngx\_http\_request\_t \*r,

- ngx\_http\_variable\_value\_t \*v, uintptr\_t data)  
+{
- ngx\_http\_geoip\_conf\_t \*gcf;

- return NGX\_OK;

- gcf = ngx\_http\_get\_module\_main\_conf(r, ngx\_http\_geoip\_module);

-not\_found:

- if (gcf-\>org == NULL && gcf-\>org\_v6 == NULL) {
- 

```
   v->not_found = 1;

```

- v-\>not\_found = 1;

- 

```
   return NGX_OK;

```

- }

- return NGX\_OK;

- return ngx\_http\_geoip\_get\_char(r, v, gcf-\>org,  
(ngx\_http\_geoip\_variable\_handler\_pt)&GeoIP\_name\_by\_ipnum,  
+#if (NGX\_HAVE\_INET6)
- 

```
                gcf->org_v6, 

```

(ngx\_http\_geoip\_variable\_handler6\_pt)&GeoIP\_name\_by\_ipnum\_v6  
+#else

- 

```
                NULL, NULL

```

+#endif

- 

```
                );

```

}

@@ -451,8 +488,26 @@ ngx\_http\_geoip\_get\_city\_record(ngx\_http\_

```
 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);

```

- if (gcf-\>city) {
- 

```
   return GeoIP_record_by_ipnum(gcf->city, 

```

ngx\_http\_geoip\_addr®);

- switch (r-\>connection-\>sockaddr-\>sa\_family) {
- case AF\_INET:
- 

```
   if (gcf->city) {

```

- 

```
       struct sockaddr_in *sin = (struct sockaddr_in *) 

```

r-\>connection-\>sockaddr;

- 

```
       return GeoIP_record_by_ipnum(gcf->city, 

```

ntohl(sin-\>sin\_addr.s\_addr));

- 

```
   }

```

- 

```
   return NULL;

```

+#if (NGX\_HAVE\_INET6)

- case AF\_INET6:
- 

```
   if (gcf->city_v6) {

```

- 

```
       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) 

```

r-\>connection-\>sockaddr;

- 

```
       if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {

```

- 

```
           u_char *p = sin6->sin6_addr.s6_addr;

```

- 

```
           return gcf->city ? GeoIP_record_by_ipnum(gcf->city,

```

- 

```
                        (p[12] << 24) + (p[13] << 16) + (p[14] << 

```

1. 
  - p[15]) : NULL;

- 

```
       } else

```

- 

```
           return GeoIP_record_by_ipnum_v6(gcf->city_v6, 

```

sin6-\>sin6\_addr);

- 

```
   }

```

- 

```
   return NULL;

```

+#endif  
}

```
 return NULL;

```

@@ -505,18 +560,19 @@ static char \*  
ngx\_http\_geoip\_country(ngx\_conf\_t \*cf, ngx\_command\_t \*cmd, void \*conf)  
{  
ngx\_http\_geoip\_conf\_t \*gcf = conf;

- GeoIP \*tmp;

- if (gcf-\>country) {

- if (gcf-\>country && gcf-\>country\_v6) {  
return “is duplicate”;  
}

- gcf-\>country = GeoIP\_open((char \*) value[1].data,  
GEOIP\_MEMORY\_CACHE);

- tmp = GeoIP\_open((char \*) value[1].data, GEOIP\_MEMORY\_CACHE);

- if (gcf-\>country == NULL) {

- if (tmp == NULL) {  
ngx\_conf\_log\_error(NGX\_LOG\_EMERG, cf, 0,  
“GeoIP\_open(”%V") failed", &value[1]);

@@ -525,7 +581,7 @@ ngx\_http\_geoip\_country(ngx\_conf\_t \*cf, n

```
 if (cf->args->nelts == 3) {
     if (ngx_strcmp(value[2].data, "utf8") == 0) {

```

- 

```
       GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8);

```

- 

```
       GeoIP_set_charset (tmp, GEOIP_CHARSET_UTF8);

   } else {
       ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

@@ -534,18 +590,33 @@ ngx\_http\_geoip\_country(ngx\_conf\_t \*cf, n  
}  
}

- switch (gcf-\>country-\>databaseType) {

- switch (tmp-\>databaseType) {

- 

```
   if (gcf->country) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->country = tmp;

```

- 

```
   return NGX_CONF_OK;

```

+#if (NGX\_HAVE\_INET6)

- case GEOIP\_COUNTRY\_EDITION\_V6:
- 

```
   if (gcf->country_v6) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->country_v6 = tmp;
   return NGX_CONF_OK;

```

+#endif

```
 default:
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                        "invalid GeoIP database \"%V\" type:%d",

```

- 

```
                      &value[1], gcf->country->databaseType);

```

- 

```
                      &value[1], tmp->databaseType);

```

- 

```
   GeoIP_delete(tmp);
   return NGX_CONF_ERROR;

```

}  
}  
@@ -555,18 +626,19 @@ static char \*  
ngx\_http\_geoip\_org(ngx\_conf\_t \*cf, ngx\_command\_t \*cmd, void \*conf)  
{  
ngx\_http\_geoip\_conf\_t \*gcf = conf;

- GeoIP \*tmp;

- if (gcf-\>org) {

- if (gcf-\>org && gcf-\>org\_v6) {  
return “is duplicate”;  
}

- gcf-\>org = GeoIP\_open((char \*) value[1].data, GEOIP\_MEMORY\_CACHE);

- tmp = GeoIP\_open((char \*) value[1].data, GEOIP\_MEMORY\_CACHE);

- if (gcf-\>org == NULL) {

- if (tmp == NULL) {  
ngx\_conf\_log\_error(NGX\_LOG\_EMERG, cf, 0,  
“GeoIP\_open(”%V") failed", &value[1]);

@@ -575,7 +647,7 @@ ngx\_http\_geoip\_org(ngx\_conf\_t \*cf, ngx\_c

```
 if (cf->args->nelts == 3) {
     if (ngx_strcmp(value[2].data, "utf8") == 0) {

```

- 

```
       GeoIP_set_charset (gcf->org, GEOIP_CHARSET_UTF8);

```

- 

```
       GeoIP_set_charset (tmp, GEOIP_CHARSET_UTF8);

   } else {
       ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

@@ -584,19 +656,37 @@ ngx\_http\_geoip\_org(ngx\_conf\_t \*cf, ngx\_c  
}  
}

- switch (gcf-\>org-\>databaseType) {

- switch (tmp-\>databaseType) {

- 

```
   if (gcf->org) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->org = tmp;

```

- 

```
   return NGX_CONF_OK;

```

+#if (NGX\_HAVE\_INET6)

- case GEOIP\_ISP\_EDITION\_V6:
- case GEOIP\_ORG\_EDITION\_V6:
- case GEOIP\_DOMAIN\_EDITION\_V6:
- case GEOIP\_ASNUM\_EDITION\_V6:
- 

```
   if (gcf->org_v6) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->org_v6 = tmp;
   return NGX_CONF_OK;

```

+#endif

```
 default:
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                        "invalid GeoIP database \"%V\" type:%d",

```

- 

```
                      &value[1], gcf->org->databaseType);

```

- 

```
                      &value[1], tmp->databaseType);

```

- 

```
   GeoIP_delete(tmp);
   return NGX_CONF_ERROR;

```

}  
}  
@@ -606,18 +696,19 @@ static char \*  
ngx\_http\_geoip\_city(ngx\_conf\_t \*cf, ngx\_command\_t \*cmd, void \*conf)  
{  
ngx\_http\_geoip\_conf\_t \*gcf = conf;

- GeoIP \*tmp;

- if (gcf-\>city) {

- if (gcf-\>city && gcf-\>city\_v6) {  
return “is duplicate”;  
}

- gcf-\>city = GeoIP\_open((char \*) value[1].data, GEOIP\_MEMORY\_CACHE);

- tmp = GeoIP\_open((char \*) value[1].data, GEOIP\_MEMORY\_CACHE);

- if (gcf-\>city == NULL) {

- if (tmp == NULL) {  
ngx\_conf\_log\_error(NGX\_LOG\_EMERG, cf, 0,  
“GeoIP\_open(”%V") failed", &value[1]);

@@ -626,7 +717,7 @@ ngx\_http\_geoip\_city(ngx\_conf\_t \*cf, ngx\_

```
 if (cf->args->nelts == 3) {
     if (ngx_strcmp(value[2].data, "utf8") == 0) {

```

- 

```
       GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8);

```

- 

```
       GeoIP_set_charset (tmp, GEOIP_CHARSET_UTF8);

   } else {
       ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

```

@@ -635,17 +726,32 @@ ngx\_http\_geoip\_city(ngx\_conf\_t \*cf, ngx\_  
}  
}

- switch (gcf-\>city-\>databaseType) {

- switch (tmp-\>databaseType) {

- 

```
   if (gcf->city) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->city = tmp;

```

- 

```
   return NGX_CONF_OK;

```

+#if (NGX\_HAVE\_INET6)

- case GEOIP\_CITY\_EDITION\_REV0\_V6:
- case GEOIP\_CITY\_EDITION\_REV1\_V6:
- 

```
   if (gcf->city_v6) {

```

- 

```
       GeoIP_delete(tmp);

```

- 

```
       return "is duplicate";

```

- 

```
   } else

```

- 

```
       gcf->city_v6 = tmp;
   return NGX_CONF_OK;

```

+#endif

```
 default:
     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                        "invalid GeoIP City database \"%V\" 

```

type:%d",

- 

```
                      &value[1], gcf->city->databaseType);

```

- 

```
                      &value[1], tmp->databaseType);
   return NGX_CONF_ERROR;

```

}  
}  
@@ -659,12 +765,21 @@ ngx\_http\_geoip\_cleanup(void \*data)  
if (gcf-\>country) {  
GeoIP\_delete(gcf-\>country);  
}

- if (gcf-\>country\_v6) {

- 

```
   GeoIP_delete(gcf->country_v6);

```

- }

- if (gcf-\>org\_v6) {

- 

```
   GeoIP_delete(gcf->org_v6);

```

- }

- if (gcf-\>city\_v6) {

- 

```
   GeoIP_delete(gcf->city_v6);

```

- }  
}

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [October 5, 2011, 1:05pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/2 "2011-10-05T13:05:58Z")

</div>

Hello!

On Tue, Oct 04, 2011 at 09:22:31AM +0200, Bruno Prémont wrote:

> Please review and consider applying,  
> Please take a look at this patch instead (this one is sitting in  
> my TODO queue, waiting for more thoughtfull review and likely  
> commit):

> **[GeoIPv6 patch](http://mailman.nginx.org/pipermail/nginx-devel/2011-June/000971.html)**

Do you have any problems with Gregor Kališnik’s patch? How your  
patch is different?

Maxim D.

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [October 5, 2011, 1:27pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/3 "2011-10-05T13:27:35Z")

</div>

Most IPv6 stuff was introduced with newer versions of the GeoIP library  
(IIRC something around 1.4.7), so you might either want to autodetect  
GeoIP’s capabilities or embed the relevant stuff into

#if LIBGEOIP\_VERSION \>= 1004007  
…  
#endif

directives. Otherwise you might break builds against older versions of  
the library.

Posted at Nginx Forum:

> **[Re: \[PATCH\] Add IPv6 support to GeoIP module](https://forum.nginx.org/read.php?2,216238,216265#msg-216265)**
>
> Hello all, geoip module currently only supports a single country and a single city MaxMind database that must cover IPv4 address range. Below patch allows setting up to two city and country databases, one for IPv4 and one for IPv6. It then looks-up...

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [October 5, 2011, 1:32pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/4 "2011-10-05T13:32:32Z")

</div>

Hi.

On Wednesday 05 of October 2011 13:26:47 csg wrote:

> Most IPv6 stuff was introduced with newer versions of the GeoIP library  
> (IIRC something around 1.4.7), so you might either want to autodetect  
> GeoIP’s capabilities or embed the relevant stuff into
> 
> #if LIBGEOIP\_VERSION \>= 1004007  
> …  
> #endif
> 
> directives. Otherwise you might break builds against older versions of  
> the library.

My patch does config checking if some GeoIPv6 specific constant exists.  
And I’ve  
tested agains older and newer versions of GeoIP. And it build without  
any  
problems.

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [October 5, 2011, 1:57pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/5 "2011-10-05T13:57:14Z")

</div>

Hallo,

On Wed, 5 Oct 2011 15:05:28 Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Please take a look at this patch instead (this one is sitting in  
> my TODO queue, waiting for more thoughtfull review and likely  
> commit):
> 
> [GeoIPv6 patch](http://mailman.nginx.org/pipermail/nginx-devel/2011-June/000971.html)
> 
> Do you have any problems with Gregor Kališnik’s patch?

I didn’t stumble on Gregor’s patch before writing mine and your  
reference made me aware of it.

> How your patch is different?

The difference between both patches is that mine accepts to load two  
databases, one for IPv4 and one for IPv6.

From a short test with geoiplookup6 it seems that MaxMind’s IPv6 country  
database includes the IPv4 database and thus can answer for mapped IPv4  
addresses (which I didn’t know).

So as long as that remains true Gregor’s patch looks more simple (while  
covering feature-test of geoip lib which mine doesn’t) and provides the  
same features.

If IPv6 database once stops including knowledge about IPv4 addresses  
lookup would start failing (but that hopefully would only happen when  
IPv4 gets irrelevant).

Thanks,  
Bruno

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [October 5, 2011, 2:52pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/6 "2011-10-05T14:52:52Z")

</div>

Hello!

On Wed, Oct 05, 2011 at 01:56:35PM +0200, Bruno Prémont wrote:

> > >
> 
> I didn’t stumble on Gregor’s patch before writing mine and your
> 
> So as long as that remains true Gregor’s patch looks more simple (while  
> covering feature-test of geoip lib which mine doesn’t) and provides the  
> same features.
> 
> If IPv6 database once stops including knowledge about IPv4 addresses  
> lookup would start failing (but that hopefully would only happen when  
> IPv4 gets irrelevant).

IPv6 database can’t really drop ipv4 mapped addresses, as it’s just  
part of ipv6 address space and may appear even if you aren’t using  
ipv4 at all. (This isn’t really good for security reasons, but  
that’s completely different story.)

So you are happy with Gregor’s patch, right? Let’s focus on it  
then.

Maxim D.

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [April 13, 2012, 10:12am UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/7 "2012-04-13T10:12:41Z")

</div>

Hello Maxim,

On Wed, 5 Oct 2011 16:52:10 Maxim D. wrote:

> IPv6 database can’t really drop ipv4 mapped addresses, as it’s just  
> part of ipv6 address space and may appear even if you aren’t using  
> ipv4 at all. (This isn’t really good for security reasons, but  
> that’s completely different story.)
> 
> So you are happy with Gregor’s patch, right? Let’s focus on it  
> then.

What’s the state of/progress with Gregor’s patch?

I’ve been using it on top of 1.0.x since October without any issues.  
Is there anything preventing it from being applied?

Thanks,  
Bruno

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [April 13, 2012, 12:56pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/8 "2012-04-13T12:56:10Z")

</div>

Hi.

On Friday 13 of April 2012 14:47:24 Maxim D. wrote:

> We’ll work on various ipv6-related things after 1.2.0 release (it  
> was expected to happen yesterday, but was postponed to avoid  
> interference with security updates; next expected date is about 23  
> april). It will likely be committed then.

Nice to hear that.

Best regards,  
Gregor Kališnik

---

<div class="post-metadata">

**Author:** ![SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/b4bc9f/32.png) [@SSBruno\_PrSSmontSS\_S](https://www.ruby-forum.com/u/SSBruno_PrSSmontSS_S)\
**Post date:** [April 13, 2012, 12:48pm UTC](https://www.ruby-forum.com/t/add-ipv6-support-to-geoip-module/212477/9 "2012-04-13T12:48:05Z")

</div>

Hello!

On Fri, Apr 13, 2012 at 10:11:53AM +0200, Bruno Prémont wrote:

> What’s the state of/progress with Gregor’s patch?
> 
> I’ve been using it on top of 1.0.x since October without any issues.  
> Is there anything preventing it from being applied?

We’ll work on various ipv6-related things after 1.2.0 release (it  
was expected to happen yesterday, but was postponed to avoid  
interference with security updates; next expected date is about 23  
april). It will likely be committed then.

Maxim D.
