mirror of
https://github.com/nginx/nginx.git
synced 2024-12-19 05:33:52 -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_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
|
||||
|
||||
cat << END
|
||||
|
@ -13,12 +13,22 @@
|
||||
#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;
|
||||
ngx_array_t *proxies; /* array of ngx_cidr_t */
|
||||
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;
|
||||
|
||||
|
||||
@ -28,10 +38,32 @@ typedef struct {
|
||||
} 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,
|
||||
ngx_http_variable_value_t *v, uintptr_t data);
|
||||
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_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,
|
||||
@ -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
|
||||
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;
|
||||
ngx_http_geoip_variable_handler_pt handler =
|
||||
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;
|
||||
ngx_http_geoip_conf_t *gcf;
|
||||
@ -271,7 +359,13 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
|
||||
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));
|
||||
#endif
|
||||
|
||||
if (val == NULL) {
|
||||
goto not_found;
|
||||
@ -297,9 +391,6 @@ 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_variable_handler_pt handler =
|
||||
(ngx_http_geoip_variable_handler_pt) data;
|
||||
|
||||
size_t len;
|
||||
char *val;
|
||||
ngx_http_geoip_conf_t *gcf;
|
||||
@ -310,7 +401,15 @@ ngx_http_geoip_org_variable(ngx_http_request_t *r,
|
||||
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) {
|
||||
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);
|
||||
|
||||
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));
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -603,6 +710,13 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
||||
#if (NGX_HAVE_GEOIP_V6)
|
||||
case GEOIP_COUNTRY_EDITION_V6:
|
||||
|
||||
gcf->country_v6 = 1;
|
||||
return NGX_CONF_OK;
|
||||
#endif
|
||||
|
||||
default:
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"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;
|
||||
|
||||
#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:
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"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;
|
||||
|
||||
#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:
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid GeoIP City database \"%V\" type:%d",
|
||||
|
Loading…
Reference in New Issue
Block a user