GeoIPv6 patch

Maxim Dounin mdounin at mdounin.ru
Tue Jun 21 20:52:51 MSD 2011


Hello!

On Wed, Jun 15, 2011 at 12:43:49PM +0200, Gregor Kališnik wrote:

> Hi.
> 
> On Wednesday 15 of June 2011 03:47:18 you wrote:
> > Hello!
> > 
> > On Tue, Jun 14, 2011 at 07:52:10AM +0200, Gregor Kališnik wrote:
> > > Hi.
> > > 
> 
> > 
> > I believe it would be sufficient to just check for geoipv6_t type.
> > 
> >     ngx_feature_incs="#include <GeoIP.h>"
> >     ...
> >     ngx_feature_test="geoipv6_t  v6addr;
> >                       v6addr.s6_addr[0] = 1;"
> > 
> 
> I've checked GeoIP.h from geoip-1.4.6 and geoip-1.4.7. Both have geoipv6_t. 
> But the 1.4.6 version doesn't support GeoIP City IPv6 version and check for 
> geoipv6_t would break compilation when using geoip-1.4.6.

Ah, ok, I see now.  IPv6 support appeared in libgeoip 1.4.5, but 
it was rather limited.  So the test for (at least one) constant 
appeared in 1.4.7 is indeed required.

> Should I break GeoIP IPv6 code into two parts? First checking for geoipv6_t 
> and second checking for GeoCity related define/type?

No, I think this would be an overkill.

> > IMHO, something like this will be more readable:
> > 
> > #if (NGX_HAVE_GEOIP_IPV6)
> >     val = gcf->country_ipv6
> >               ? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r))
> > 
> >               : handler(gcf->country,
> >               : ngx_http_geoip_addr(r));
> > 
> > #else
> >     val = handler(gcf->country, ngx_http_geoip_addr(r));
> > #endif
> > 
> > Just a matter of taste though.
> > 
> 
> Hope I got the identitation right :) .

I actually mean "?" to be 4 spaces after "gcf" in previous line.  
Much like in

core/ngx_open_file_cache.c:797:            p = (ngx_strcmp(file->name, file_temp->name) < 0)
core/ngx_open_file_cache.c:798:                    ? &temp->left : &temp->right;

> 
> 
> Best regards,
> Gregor Kališnik

> diff -ru nginx-1.0.4/auto/lib/geoip/conf nginx-1.0.4-patched/auto/lib/geoip/conf
> --- nginx-1.0.4/auto/lib/geoip/conf	2009-07-20 09:10:43.000000000 +0200
> +++ nginx-1.0.4-patched/auto/lib/geoip/conf	2011-06-15 12:22:34.085253223 +0200
> @@ -65,6 +65,24 @@
>  if [ $ngx_found = yes ]; then
>      CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
>  
> +    if [ $NGX_IPV6 = YES ]; then
> +        ngx_feature="GeoIP IPV6 support"
> +        ngx_feature_name="NGX_HAVE_GEOIP_IPV6"
> +        ngx_feature_run=no
> +        ngx_feature_incs="#include <stdio.h>
> +                          #include <GeoIP.h>"
> +        ngx_feature_path=
> +        ngx_feature_libs=
> +        ngx_feature_test='printf("%d", GEOIP_COUNTRY_EDITION_V6);
> +                          printf("%d", GEOIP_ISP_EDITION_V6);
> +                          printf("%d", GEOIP_ORG_EDITION_V6);
> +                          printf("%d", GEOIP_DOMAIN_EDITION_V6);
> +                          printf("%d", GEOIP_ASNUM_EDITION_V6);
> +                          printf("%d", GEOIP_CITY_EDITION_REV0_V6);
> +                          printf("%d", GEOIP_CITY_EDITION_REV1_V6);'
> +        . auto/feature

Please include attached patch for configure part (on top of 
yours).

It cleans up some minor things in original code (missing 
ngx_feature_incs, extra trailing "/" in ngx_feature_path for 
NetBSD port, missing ngx_feature_path for FreeBSD port, missing 
CORE_INCS modification) and modifies your code to not set 
"ngx_feature_path" and "ngx_feature_libs".  This allows correct 
detection of ipv6 support if library was found on non-default 
path.

> +    fi
> +
>  else
>  
>  cat << END
> diff -ru nginx-1.0.4/src/http/modules/ngx_http_geoip_module.c nginx-1.0.4-patched/src/http/modules/ngx_http_geoip_module.c
> --- nginx-1.0.4/src/http/modules/ngx_http_geoip_module.c	2011-05-16 15:50:58.000000000 +0200
> +++ nginx-1.0.4-patched/src/http/modules/ngx_http_geoip_module.c	2011-06-15 12:28:44.455416386 +0200
> @@ -12,10 +12,18 @@
>  #include <GeoIPCity.h>
>  
>  
> +#define NGX_GEOIP_COUNTRY_CODE  0
> +#define NGX_GEOIP_COUNTRY_CODE3 1
> +#define NGX_GEOIP_COUNTRY_NAME  2
> +
> +
>  typedef struct {
>      GeoIP      *country;
>      GeoIP      *org;
>      GeoIP      *city;
> +    unsigned    country_ipv6:1;
> +    unsigned    org_ipv6:1;
> +    unsigned    city_ipv6:1;
>  } ngx_http_geoip_conf_t;
>  
>  
> @@ -27,6 +35,26 @@
>  
>  typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
>  
> +
> +ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
> +    (ngx_http_geoip_variable_handler_pt) GeoIP_country_code_by_ipnum,
> +    (ngx_http_geoip_variable_handler_pt) GeoIP_country_code3_by_ipnum,
> +    (ngx_http_geoip_variable_handler_pt) GeoIP_country_name_by_ipnum,

I believe cast shouldn't be needed here.

> +};
> +
> +
> +#if (NGX_HAVE_GEOIP_IPV6)
> +typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *, geoipv6_t addr);
> +
> +
> +ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_ipv6_functions[] = {
> +    (ngx_http_geoip_variable_handler_v6_pt) GeoIP_country_code_by_ipnum_v6,
> +    (ngx_http_geoip_variable_handler_v6_pt) GeoIP_country_code3_by_ipnum_v6,
> +    (ngx_http_geoip_variable_handler_v6_pt) GeoIP_country_name_by_ipnum_v6,

And here.

> +};
> +#endif
> +
> +
>  static ngx_int_t ngx_http_geoip_country_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,
> @@ -114,19 +142,19 @@
>  
>      { ngx_string("geoip_country_code"), NULL,
>        ngx_http_geoip_country_variable,
> -      (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
> +      NGX_GEOIP_COUNTRY_CODE, 0, 0 },
>  
>      { ngx_string("geoip_country_code3"), NULL,
>        ngx_http_geoip_country_variable,
> -      (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
> +      NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
>  
>      { ngx_string("geoip_country_name"), NULL,
>        ngx_http_geoip_country_variable,
> -      (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
> +      NGX_GEOIP_COUNTRY_NAME, 0, 0 },
>  
>      { ngx_string("geoip_org"), NULL,
>        ngx_http_geoip_org_variable,
> -      (uintptr_t) GeoIP_name_by_ipnum, 0, 0 },
> +      0, 0, 0 },
>  
>      { ngx_string("geoip_city_continent_code"), NULL,
>        ngx_http_geoip_city_variable,
> @@ -217,16 +245,55 @@
>      return INADDR_NONE;
>  }
>  

Two empty lines between functions, please.

> +#if (NGX_HAVE_GEOIP_IPV6)
> +static geoipv6_t
> +ngx_http_geoip_addr_v6(ngx_http_request_t *r)
> +{
> +    struct sockaddr_in6  *sin6;
> +    struct sockaddr_in   *sin;
> +    struct in6_addr       addr6;
> +    u_long                addr;
> +
> +    switch (r->connection->sockaddr->sa_family) {
> +
> +    case AF_INET:
> +        /* Produce IPv4 mapped IPv6 address  */
> +        sin = (struct sockaddr_in *) r->connection->sockaddr;
> +        addr = ntohl(sin->sin_addr.s_addr);
> +
> +        ngx_memzero(&addr6, sizeof(struct in6_addr));
> +        addr6.s6_addr[10] = 0xFF;
> +        addr6.s6_addr[11] = 0xFF;
> +        addr6.s6_addr[12] = addr >> 24;
> +        addr6.s6_addr[13] = addr >> 16;
> +        addr6.s6_addr[14] = addr >> 8;
> +        addr6.s6_addr[15] = addr;
> +        return addr6;
> +
> +    case AF_INET6:
> +        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
> +        return sin6->sin6_addr;
> +
> +    }
> +
> +    return in6addr_any;
> +}
> +#endif
> +
>  
>  static ngx_int_t
>  ngx_http_geoip_country_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;
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    ngx_http_geoip_variable_handler_v6_pt handler_v6 =
> +        ngx_http_geoip_country_ipv6_functions[data];
> +#endif
> +    ngx_http_geoip_variable_handler_pt    handler =
> +        ngx_http_geoip_country_functions[data];
>  
> -    const char             *val;
> -    ngx_http_geoip_conf_t  *gcf;
> +    const char                           *val;
> +    ngx_http_geoip_conf_t                *gcf;
>  
>      gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
>  
> @@ -234,7 +301,13 @@
>          goto not_found;
>      }
>  
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    val = gcf->country_ipv6
> +           ? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r))
> +           : handler(gcf->country, ngx_http_geoip_addr(r));
> +#else
>      val = handler(gcf->country, ngx_http_geoip_addr(r));
> +#endif
>  
>      if (val == NULL) {
>          goto not_found;
> @@ -260,9 +333,6 @@
>  ngx_http_geoip_org_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;
>  
> @@ -272,7 +342,13 @@
>          goto not_found;
>      }
>  
> -    val = handler(gcf->org, ngx_http_geoip_addr(r));
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    val = gcf->country_ipv6
> +           ? GeoIP_name_by_ipnum_v6(gcf->country, ngx_http_geoip_addr_v6(r))
> +           : GeoIP_name_by_ipnum(gcf->country, ngx_http_geoip_addr(r));
> +#else
> +    val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r));
> +#endif
>  
>      if (val == NULL) {
>          goto not_found;
> @@ -452,7 +528,15 @@
>      gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
>  
>      if (gcf->city) {
> +#if (NGX_HAVE_GEOIP_IPV6)
> +        if (gcf->city_ipv6) {
> +            return GeoIP_record_by_ipnum_v6(gcf->city, ngx_http_geoip_addr_v6(r));
> +        } else {
> +            return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
> +        }
> +#else
>          return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
> +#endif

The same form here.

>      }
>  
>      return NULL;
> @@ -540,8 +624,16 @@
>      case GEOIP_PROXY_EDITION:
>      case GEOIP_NETSPEED_EDITION:
>  
> +        gcf->country_ipv6 = 0;
>          return NGX_CONF_OK;
>  
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    case GEOIP_COUNTRY_EDITION_V6:
> +
> +        gcf->country_ipv6 = 1;
> +        return NGX_CONF_OK;
> +#endif
> +
>      default:
>          ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
>                             "invalid GeoIP database \"%V\" type:%d",
> @@ -591,8 +683,19 @@
>      case GEOIP_DOMAIN_EDITION:
>      case GEOIP_ASNUM_EDITION:
>  
> +        gcf->org_ipv6 = 0;
>          return NGX_CONF_OK;
>  
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    case GEOIP_ISP_EDITION_V6:
> +    case GEOIP_ORG_EDITION_V6:
> +    case GEOIP_DOMAIN_EDITION_V6:
> +    case GEOIP_ASNUM_EDITION_V6:
> +
> +        gcf->org_ipv6 = 1;
> +        return NGX_CONF_OK;
> +#endif
> +
>      default:
>          ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
>                             "invalid GeoIP database \"%V\" type:%d",
> @@ -640,7 +743,16 @@
>      case GEOIP_CITY_EDITION_REV0:
>      case GEOIP_CITY_EDITION_REV1:
>  
> +        gcf->city_ipv6 = 0;
> +        return NGX_CONF_OK;
> +
> +#if (NGX_HAVE_GEOIP_IPV6)
> +    case GEOIP_CITY_EDITION_REV0_V6:
> +    case GEOIP_CITY_EDITION_REV1_V6:
> +
> +        gcf->city_ipv6 = 1;
>          return NGX_CONF_OK;
> +#endif
>  
>      default:
>          ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

Overall, looks good for me except some minor style nits.

Maxim Dounin



More information about the nginx-devel mailing list