13 #include <GeoIPCity.h>
16 #define NGX_GEOIP_COUNTRY_CODE 0
17 #define NGX_GEOIP_COUNTRY_CODE3 1
18 #define NGX_GEOIP_COUNTRY_NAME 2
27 #if (NGX_HAVE_GEOIP_V6)
28 unsigned country_v6:1;
41 typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
46 GeoIP_country_code_by_ipnum,
47 GeoIP_country_code3_by_ipnum,
48 GeoIP_country_name_by_ipnum,
52 #if (NGX_HAVE_GEOIP_V6)
54 typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
58 ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_v6_functions[] = {
59 GeoIP_country_code_by_ipnum_v6,
60 GeoIP_country_code3_by_ipnum_v6,
61 GeoIP_country_name_by_ipnum_v6,
82 static void *ngx_http_geoip_create_conf(
ngx_conf_t *cf);
83 static char *ngx_http_geoip_init_conf(
ngx_conf_t *cf,
void *conf);
94 static void ngx_http_geoip_cleanup(
void *data);
101 ngx_http_geoip_country,
122 ngx_http_geoip_proxy,
139 ngx_http_geoip_add_variables,
142 ngx_http_geoip_create_conf,
143 ngx_http_geoip_init_conf,
155 &ngx_http_geoip_module_ctx,
156 ngx_http_geoip_commands,
172 ngx_http_geoip_country_variable,
176 ngx_http_geoip_country_variable,
180 ngx_http_geoip_country_variable,
184 ngx_http_geoip_org_variable,
187 {
ngx_string(
"geoip_city_continent_code"), NULL,
188 ngx_http_geoip_city_variable,
189 offsetof(GeoIPRecord, continent_code), 0, 0 },
191 {
ngx_string(
"geoip_city_country_code"), NULL,
192 ngx_http_geoip_city_variable,
193 offsetof(GeoIPRecord, country_code), 0, 0 },
195 {
ngx_string(
"geoip_city_country_code3"), NULL,
196 ngx_http_geoip_city_variable,
197 offsetof(GeoIPRecord, country_code3), 0, 0 },
199 {
ngx_string(
"geoip_city_country_name"), NULL,
200 ngx_http_geoip_city_variable,
201 offsetof(GeoIPRecord, country_name), 0, 0 },
204 ngx_http_geoip_city_variable,
205 offsetof(GeoIPRecord, region), 0, 0 },
208 ngx_http_geoip_region_name_variable,
212 ngx_http_geoip_city_variable,
213 offsetof(GeoIPRecord, city), 0, 0 },
216 ngx_http_geoip_city_variable,
217 offsetof(GeoIPRecord, postal_code), 0, 0 },
220 ngx_http_geoip_city_float_variable,
221 offsetof(GeoIPRecord, latitude), 0, 0 },
224 ngx_http_geoip_city_float_variable,
225 offsetof(GeoIPRecord, longitude), 0, 0 },
228 ngx_http_geoip_city_int_variable,
229 offsetof(GeoIPRecord, dma_code), 0, 0 },
232 ngx_http_geoip_city_int_variable,
233 offsetof(GeoIPRecord, area_code), 0, 0 },
244 struct sockaddr_in *sin;
259 if (addr.
sockaddr->sa_family == AF_INET6) {
262 struct in6_addr *inaddr6;
264 inaddr6 = &((
struct sockaddr_in6 *) addr.
sockaddr)->sin6_addr;
266 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
267 p = inaddr6->s6_addr;
269 inaddr = p[12] << 24;
270 inaddr += p[13] << 16;
271 inaddr += p[14] << 8;
280 if (addr.
sockaddr->sa_family != AF_INET) {
284 sin = (
struct sockaddr_in *) addr.
sockaddr;
285 return ntohl(sin->sin_addr.s_addr);
289 #if (NGX_HAVE_GEOIP_V6)
297 struct in6_addr addr6;
298 struct sockaddr_in *sin;
299 struct sockaddr_in6 *sin6;
316 sin = (
struct sockaddr_in *) addr.
sockaddr;
317 addr4 = ntohl(sin->sin_addr.s_addr);
320 addr6.s6_addr[10] = 0xff;
321 addr6.s6_addr[11] = 0xff;
322 addr6.s6_addr[12] = addr4 >> 24;
323 addr6.s6_addr[13] = addr4 >> 16;
324 addr6.s6_addr[14] = addr4 >> 8;
325 addr6.s6_addr[15] = addr4;
329 sin6 = (
struct sockaddr_in6 *) addr.
sockaddr;
330 return sin6->sin6_addr;
346 #if (NGX_HAVE_GEOIP_V6)
347 ngx_http_geoip_variable_handler_v6_pt handler_v6 =
348 ngx_http_geoip_country_v6_functions[data];
360 #if (NGX_HAVE_GEOIP_V6)
361 val = gcf->country_v6
362 ? handler_v6(gcf->
country, ngx_http_geoip_addr_v6(r, gcf))
363 : handler(gcf->country, ngx_http_geoip_addr(r, gcf));
365 val = handler(gcf->
country, ngx_http_geoip_addr(r, gcf));
376 v->
data = (u_char *) val;
398 if (gcf->
org == NULL) {
402 #if (NGX_HAVE_GEOIP_V6)
404 ? GeoIP_name_by_ipnum_v6(gcf->
org,
405 ngx_http_geoip_addr_v6(r, gcf))
406 : GeoIP_name_by_ipnum(gcf->org,
407 ngx_http_geoip_addr(r, gcf));
409 val = GeoIP_name_by_ipnum(gcf->
org, ngx_http_geoip_addr(r, gcf));
418 if (v->
data == NULL) {
450 gr = ngx_http_geoip_get_city_record(r);
455 val = *(
char **) ((
char *) gr + data);
462 if (v->
data == NULL) {
463 GeoIPRecord_delete(gr);
474 GeoIPRecord_delete(gr);
480 GeoIPRecord_delete(gr);
498 gr = ngx_http_geoip_get_city_record(r);
503 val = GeoIP_region_name_by_code(gr->country_code, gr->region);
505 GeoIPRecord_delete(gr);
513 if (v->
data == NULL) {
541 gr = ngx_http_geoip_get_city_record(r);
548 if (v->
data == NULL) {
549 GeoIPRecord_delete(gr);
553 val = *(
float *) ((
char *) gr + data);
557 GeoIPRecord_delete(gr);
570 gr = ngx_http_geoip_get_city_record(r);
577 if (v->
data == NULL) {
578 GeoIPRecord_delete(gr);
582 val = *(
int *) ((
char *) gr + data);
586 GeoIPRecord_delete(gr);
600 #if (NGX_HAVE_GEOIP_V6)
602 ? GeoIP_record_by_ipnum_v6(gcf->
city,
603 ngx_http_geoip_addr_v6(r, gcf))
604 : GeoIP_record_by_ipnum(gcf->city,
605 ngx_http_geoip_addr(r, gcf));
607 return GeoIP_record_by_ipnum(gcf->
city, ngx_http_geoip_addr(r, gcf));
620 for (v = ngx_http_geoip_vars; v->
name.
len; v++) {
652 cln->
handler = ngx_http_geoip_cleanup;
660 ngx_http_geoip_init_conf(
ngx_conf_t *cf,
void *conf)
678 return "is duplicate";
683 gcf->
country = GeoIP_open((
char *) value[1].data, GEOIP_MEMORY_CACHE);
687 "GeoIP_open(\"%V\") failed", &value[1]);
694 GeoIP_set_charset (gcf->
country, GEOIP_CHARSET_UTF8);
698 "invalid parameter \"%V\"", &value[2]);
703 switch (gcf->
country->databaseType) {
705 case GEOIP_COUNTRY_EDITION:
709 #if (NGX_HAVE_GEOIP_V6)
710 case GEOIP_COUNTRY_EDITION_V6:
718 "invalid GeoIP database \"%V\" type:%d",
719 &value[1], gcf->
country->databaseType);
733 return "is duplicate";
738 gcf->
org = GeoIP_open((
char *) value[1].data, GEOIP_MEMORY_CACHE);
740 if (gcf->
org == NULL) {
742 "GeoIP_open(\"%V\") failed", &value[1]);
749 GeoIP_set_charset (gcf->
org, GEOIP_CHARSET_UTF8);
753 "invalid parameter \"%V\"", &value[2]);
758 switch (gcf->
org->databaseType) {
760 case GEOIP_ISP_EDITION:
761 case GEOIP_ORG_EDITION:
762 case GEOIP_DOMAIN_EDITION:
763 case GEOIP_ASNUM_EDITION:
767 #if (NGX_HAVE_GEOIP_V6)
768 case GEOIP_ISP_EDITION_V6:
769 case GEOIP_ORG_EDITION_V6:
770 case GEOIP_DOMAIN_EDITION_V6:
771 case GEOIP_ASNUM_EDITION_V6:
779 "invalid GeoIP database \"%V\" type:%d",
780 &value[1], gcf->
org->databaseType);
794 return "is duplicate";
799 gcf->
city = GeoIP_open((
char *) value[1].data, GEOIP_MEMORY_CACHE);
801 if (gcf->
city == NULL) {
803 "GeoIP_open(\"%V\") failed", &value[1]);
810 GeoIP_set_charset (gcf->
city, GEOIP_CHARSET_UTF8);
814 "invalid parameter \"%V\"", &value[2]);
819 switch (gcf->
city->databaseType) {
821 case GEOIP_CITY_EDITION_REV0:
822 case GEOIP_CITY_EDITION_REV1:
826 #if (NGX_HAVE_GEOIP_V6)
827 case GEOIP_CITY_EDITION_REV0_V6:
828 case GEOIP_CITY_EDITION_REV1_V6:
836 "invalid GeoIP City database \"%V\" type:%d",
837 &value[1], gcf->
city->databaseType);
853 if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) !=
NGX_OK) {
896 "low address bits of %V are meaningless", net);
904 ngx_http_geoip_cleanup(
void *data)
913 GeoIP_delete(gcf->
org);
917 GeoIP_delete(gcf->
city);