mirror of
https://github.com/nginx/nginx.git
synced 2025-02-25 18:55:26 -06:00
GeoIP: IPv6 support.
When using IPv6 databases, IPv4 addresses are looked up as IPv4-mapped IPv6 addresses. Mostly based on a patch by Gregor Kališnik (ticket #250).
This commit is contained in:
parent
6aa684c3c3
commit
db5e48d9b8
@ -69,6 +69,18 @@ if [ $ngx_found = yes ]; then
|
|||||||
CORE_INCS="$CORE_INCS $ngx_feature_path"
|
CORE_INCS="$CORE_INCS $ngx_feature_path"
|
||||||
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
|
CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
|
||||||
|
|
||||||
|
if [ $NGX_IPV6 = YES ]; then
|
||||||
|
ngx_feature="GeoIP IPv6 support"
|
||||||
|
ngx_feature_name="NGX_HAVE_GEOIP_V6"
|
||||||
|
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_CITY_EDITION_REV0_V6);"
|
||||||
|
. auto/feature
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
cat << END
|
cat << END
|
||||||
|
@ -13,12 +13,22 @@
|
|||||||
#include <GeoIPCity.h>
|
#include <GeoIPCity.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define NGX_GEOIP_COUNTRY_CODE 0
|
||||||
|
#define NGX_GEOIP_COUNTRY_CODE3 1
|
||||||
|
#define NGX_GEOIP_COUNTRY_NAME 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GeoIP *country;
|
GeoIP *country;
|
||||||
GeoIP *org;
|
GeoIP *org;
|
||||||
GeoIP *city;
|
GeoIP *city;
|
||||||
ngx_array_t *proxies; /* array of ngx_cidr_t */
|
ngx_array_t *proxies; /* array of ngx_cidr_t */
|
||||||
ngx_flag_t proxy_recursive;
|
ngx_flag_t proxy_recursive;
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
unsigned country_v6:1;
|
||||||
|
unsigned org_v6:1;
|
||||||
|
unsigned city_v6:1;
|
||||||
|
#endif
|
||||||
} ngx_http_geoip_conf_t;
|
} ngx_http_geoip_conf_t;
|
||||||
|
|
||||||
|
|
||||||
@ -28,10 +38,32 @@ typedef struct {
|
|||||||
} ngx_http_geoip_var_t;
|
} ngx_http_geoip_var_t;
|
||||||
|
|
||||||
|
|
||||||
typedef char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
|
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
|
||||||
|
u_long addr);
|
||||||
|
|
||||||
|
|
||||||
|
ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
|
||||||
|
GeoIP_country_code_by_ipnum,
|
||||||
|
GeoIP_country_code3_by_ipnum,
|
||||||
|
GeoIP_country_name_by_ipnum,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
|
||||||
|
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_v6_functions[] = {
|
||||||
|
GeoIP_country_code_by_ipnum_v6,
|
||||||
|
GeoIP_country_code3_by_ipnum_v6,
|
||||||
|
GeoIP_country_name_by_ipnum_v6,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static u_long ngx_http_geoip_addr(ngx_http_request_t *r,
|
|
||||||
ngx_http_geoip_conf_t *gcf);
|
|
||||||
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
|
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_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
||||||
@ -138,19 +170,19 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
|
|||||||
|
|
||||||
{ ngx_string("geoip_country_code"), NULL,
|
{ ngx_string("geoip_country_code"), NULL,
|
||||||
ngx_http_geoip_country_variable,
|
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_string("geoip_country_code3"), NULL,
|
||||||
ngx_http_geoip_country_variable,
|
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_string("geoip_country_name"), NULL,
|
||||||
ngx_http_geoip_country_variable,
|
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_string("geoip_org"), NULL,
|
||||||
ngx_http_geoip_org_variable,
|
ngx_http_geoip_org_variable,
|
||||||
(uintptr_t) GeoIP_name_by_ipnum, 0, 0 },
|
0, 0, 0 },
|
||||||
|
|
||||||
{ ngx_string("geoip_city_continent_code"), NULL,
|
{ ngx_string("geoip_city_continent_code"), NULL,
|
||||||
ngx_http_geoip_city_variable,
|
ngx_http_geoip_city_variable,
|
||||||
@ -255,12 +287,68 @@ ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
|
||||||
|
static geoipv6_t
|
||||||
|
ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
|
||||||
|
{
|
||||||
|
ngx_addr_t addr;
|
||||||
|
ngx_table_elt_t *xfwd;
|
||||||
|
in_addr_t addr4;
|
||||||
|
struct in6_addr addr6;
|
||||||
|
struct sockaddr_in *sin;
|
||||||
|
struct sockaddr_in6 *sin6;
|
||||||
|
|
||||||
|
addr.sockaddr = r->connection->sockaddr;
|
||||||
|
addr.socklen = r->connection->socklen;
|
||||||
|
/* addr.name = r->connection->addr_text; */
|
||||||
|
|
||||||
|
xfwd = r->headers_in.x_forwarded_for;
|
||||||
|
|
||||||
|
if (xfwd != NULL && gcf->proxies != NULL) {
|
||||||
|
(void) ngx_http_get_forwarded_addr(r, &addr, xfwd->value.data,
|
||||||
|
xfwd->value.len, gcf->proxies,
|
||||||
|
gcf->proxy_recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (addr.sockaddr->sa_family) {
|
||||||
|
|
||||||
|
case AF_INET:
|
||||||
|
/* Produce IPv4-mapped IPv6 address. */
|
||||||
|
sin = (struct sockaddr_in *) addr.sockaddr;
|
||||||
|
addr4 = 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] = addr4 >> 24;
|
||||||
|
addr6.s6_addr[13] = addr4 >> 16;
|
||||||
|
addr6.s6_addr[14] = addr4 >> 8;
|
||||||
|
addr6.s6_addr[15] = addr4;
|
||||||
|
return addr6;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
sin6 = (struct sockaddr_in6 *) addr.sockaddr;
|
||||||
|
return sin6->sin6_addr;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return in6addr_any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_http_geoip_country_variable(ngx_http_request_t *r,
|
ngx_http_geoip_country_variable(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
{
|
{
|
||||||
ngx_http_geoip_variable_handler_pt handler =
|
ngx_http_geoip_variable_handler_pt handler =
|
||||||
(ngx_http_geoip_variable_handler_pt) data;
|
ngx_http_geoip_country_functions[data];
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
ngx_http_geoip_variable_handler_v6_pt handler_v6 =
|
||||||
|
ngx_http_geoip_country_v6_functions[data];
|
||||||
|
#endif
|
||||||
|
|
||||||
const char *val;
|
const char *val;
|
||||||
ngx_http_geoip_conf_t *gcf;
|
ngx_http_geoip_conf_t *gcf;
|
||||||
@ -271,7 +359,13 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
|
|||||||
goto not_found;
|
goto not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
val = gcf->country_v6
|
||||||
|
? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r, gcf))
|
||||||
|
: handler(gcf->country, ngx_http_geoip_addr(r, gcf));
|
||||||
|
#else
|
||||||
val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
|
val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (val == NULL) {
|
if (val == NULL) {
|
||||||
goto not_found;
|
goto not_found;
|
||||||
@ -297,9 +391,6 @@ static ngx_int_t
|
|||||||
ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
||||||
ngx_http_variable_value_t *v, uintptr_t data)
|
ngx_http_variable_value_t *v, uintptr_t data)
|
||||||
{
|
{
|
||||||
ngx_http_geoip_variable_handler_pt handler =
|
|
||||||
(ngx_http_geoip_variable_handler_pt) data;
|
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
char *val;
|
char *val;
|
||||||
ngx_http_geoip_conf_t *gcf;
|
ngx_http_geoip_conf_t *gcf;
|
||||||
@ -310,7 +401,15 @@ ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
|||||||
goto not_found;
|
goto not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = handler(gcf->org, ngx_http_geoip_addr(r, gcf));
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
val = gcf->org_v6
|
||||||
|
? GeoIP_name_by_ipnum_v6(gcf->org,
|
||||||
|
ngx_http_geoip_addr_v6(r, gcf))
|
||||||
|
: GeoIP_name_by_ipnum(gcf->org,
|
||||||
|
ngx_http_geoip_addr(r, gcf));
|
||||||
|
#else
|
||||||
|
val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (val == NULL) {
|
if (val == NULL) {
|
||||||
goto not_found;
|
goto not_found;
|
||||||
@ -500,7 +599,15 @@ ngx_http_geoip_get_city_record(ngx_http_request_t *r)
|
|||||||
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
|
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
|
||||||
|
|
||||||
if (gcf->city) {
|
if (gcf->city) {
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
return gcf->city_v6
|
||||||
|
? GeoIP_record_by_ipnum_v6(gcf->city,
|
||||||
|
ngx_http_geoip_addr_v6(r, gcf))
|
||||||
|
: GeoIP_record_by_ipnum(gcf->city,
|
||||||
|
ngx_http_geoip_addr(r, gcf));
|
||||||
|
#else
|
||||||
return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
|
return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -603,6 +710,13 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
case GEOIP_COUNTRY_EDITION_V6:
|
||||||
|
|
||||||
|
gcf->country_v6 = 1;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid GeoIP database \"%V\" type:%d",
|
"invalid GeoIP database \"%V\" type:%d",
|
||||||
@ -654,6 +768,16 @@ ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
case GEOIP_ISP_EDITION_V6:
|
||||||
|
case GEOIP_ORG_EDITION_V6:
|
||||||
|
case GEOIP_DOMAIN_EDITION_V6:
|
||||||
|
case GEOIP_ASNUM_EDITION_V6:
|
||||||
|
|
||||||
|
gcf->org_v6 = 1;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid GeoIP database \"%V\" type:%d",
|
"invalid GeoIP database \"%V\" type:%d",
|
||||||
@ -703,6 +827,14 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_GEOIP_V6)
|
||||||
|
case GEOIP_CITY_EDITION_REV0_V6:
|
||||||
|
case GEOIP_CITY_EDITION_REV1_V6:
|
||||||
|
|
||||||
|
gcf->city_v6 = 1;
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid GeoIP City database \"%V\" type:%d",
|
"invalid GeoIP City database \"%V\" type:%d",
|
||||||
|
Loading…
Reference in New Issue
Block a user