Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 #include <GeoIP.h>
0013 #include <GeoIPCity.h>
0014 
0015 
0016 #define NGX_GEOIP_COUNTRY_CODE   0
0017 #define NGX_GEOIP_COUNTRY_CODE3  1
0018 #define NGX_GEOIP_COUNTRY_NAME   2
0019 
0020 
0021 typedef struct {
0022     GeoIP        *country;
0023     GeoIP        *org;
0024     GeoIP        *city;
0025     ngx_array_t  *proxies;    /* array of ngx_cidr_t */
0026     ngx_flag_t    proxy_recursive;
0027 #if (NGX_HAVE_GEOIP_V6)
0028     unsigned      country_v6:1;
0029     unsigned      org_v6:1;
0030     unsigned      city_v6:1;
0031 #endif
0032 } ngx_http_geoip_conf_t;
0033 
0034 
0035 typedef struct {
0036     ngx_str_t    *name;
0037     uintptr_t     data;
0038 } ngx_http_geoip_var_t;
0039 
0040 
0041 typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
0042     u_long addr);
0043 
0044 
0045 ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
0046     GeoIP_country_code_by_ipnum,
0047     GeoIP_country_code3_by_ipnum,
0048     GeoIP_country_name_by_ipnum,
0049 };
0050 
0051 
0052 #if (NGX_HAVE_GEOIP_V6)
0053 
0054 typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
0055     geoipv6_t addr);
0056 
0057 
0058 ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_v6_functions[] = {
0059     GeoIP_country_code_by_ipnum_v6,
0060     GeoIP_country_code3_by_ipnum_v6,
0061     GeoIP_country_name_by_ipnum_v6,
0062 };
0063 
0064 #endif
0065 
0066 
0067 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
0068     ngx_http_variable_value_t *v, uintptr_t data);
0069 static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
0070     ngx_http_variable_value_t *v, uintptr_t data);
0071 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
0072     ngx_http_variable_value_t *v, uintptr_t data);
0073 static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
0074     ngx_http_variable_value_t *v, uintptr_t data);
0075 static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
0076     ngx_http_variable_value_t *v, uintptr_t data);
0077 static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
0078     ngx_http_variable_value_t *v, uintptr_t data);
0079 static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
0080 
0081 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
0082 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
0083 static char *ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf);
0084 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
0085     void *conf);
0086 static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
0087     void *conf);
0088 static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
0089     void *conf);
0090 static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
0091     void *conf);
0092 static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
0093     ngx_cidr_t *cidr);
0094 static void ngx_http_geoip_cleanup(void *data);
0095 
0096 
0097 static ngx_command_t  ngx_http_geoip_commands[] = {
0098 
0099     { ngx_string("geoip_country"),
0100       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
0101       ngx_http_geoip_country,
0102       NGX_HTTP_MAIN_CONF_OFFSET,
0103       0,
0104       NULL },
0105 
0106     { ngx_string("geoip_org"),
0107       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
0108       ngx_http_geoip_org,
0109       NGX_HTTP_MAIN_CONF_OFFSET,
0110       0,
0111       NULL },
0112 
0113     { ngx_string("geoip_city"),
0114       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
0115       ngx_http_geoip_city,
0116       NGX_HTTP_MAIN_CONF_OFFSET,
0117       0,
0118       NULL },
0119 
0120     { ngx_string("geoip_proxy"),
0121       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
0122       ngx_http_geoip_proxy,
0123       NGX_HTTP_MAIN_CONF_OFFSET,
0124       0,
0125       NULL },
0126 
0127     { ngx_string("geoip_proxy_recursive"),
0128       NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
0129       ngx_conf_set_flag_slot,
0130       NGX_HTTP_MAIN_CONF_OFFSET,
0131       offsetof(ngx_http_geoip_conf_t, proxy_recursive),
0132       NULL },
0133 
0134       ngx_null_command
0135 };
0136 
0137 
0138 static ngx_http_module_t  ngx_http_geoip_module_ctx = {
0139     ngx_http_geoip_add_variables,          /* preconfiguration */
0140     NULL,                                  /* postconfiguration */
0141 
0142     ngx_http_geoip_create_conf,            /* create main configuration */
0143     ngx_http_geoip_init_conf,              /* init main configuration */
0144 
0145     NULL,                                  /* create server configuration */
0146     NULL,                                  /* merge server configuration */
0147 
0148     NULL,                                  /* create location configuration */
0149     NULL                                   /* merge location configuration */
0150 };
0151 
0152 
0153 ngx_module_t  ngx_http_geoip_module = {
0154     NGX_MODULE_V1,
0155     &ngx_http_geoip_module_ctx,            /* module context */
0156     ngx_http_geoip_commands,               /* module directives */
0157     NGX_HTTP_MODULE,                       /* module type */
0158     NULL,                                  /* init master */
0159     NULL,                                  /* init module */
0160     NULL,                                  /* init process */
0161     NULL,                                  /* init thread */
0162     NULL,                                  /* exit thread */
0163     NULL,                                  /* exit process */
0164     NULL,                                  /* exit master */
0165     NGX_MODULE_V1_PADDING
0166 };
0167 
0168 
0169 static ngx_http_variable_t  ngx_http_geoip_vars[] = {
0170 
0171     { ngx_string("geoip_country_code"), NULL,
0172       ngx_http_geoip_country_variable,
0173       NGX_GEOIP_COUNTRY_CODE, 0, 0 },
0174 
0175     { ngx_string("geoip_country_code3"), NULL,
0176       ngx_http_geoip_country_variable,
0177       NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
0178 
0179     { ngx_string("geoip_country_name"), NULL,
0180       ngx_http_geoip_country_variable,
0181       NGX_GEOIP_COUNTRY_NAME, 0, 0 },
0182 
0183     { ngx_string("geoip_org"), NULL,
0184       ngx_http_geoip_org_variable,
0185       0, 0, 0 },
0186 
0187     { ngx_string("geoip_city_continent_code"), NULL,
0188       ngx_http_geoip_city_variable,
0189       offsetof(GeoIPRecord, continent_code), 0, 0 },
0190 
0191     { ngx_string("geoip_city_country_code"), NULL,
0192       ngx_http_geoip_city_variable,
0193       offsetof(GeoIPRecord, country_code), 0, 0 },
0194 
0195     { ngx_string("geoip_city_country_code3"), NULL,
0196       ngx_http_geoip_city_variable,
0197       offsetof(GeoIPRecord, country_code3), 0, 0 },
0198 
0199     { ngx_string("geoip_city_country_name"), NULL,
0200       ngx_http_geoip_city_variable,
0201       offsetof(GeoIPRecord, country_name), 0, 0 },
0202 
0203     { ngx_string("geoip_region"), NULL,
0204       ngx_http_geoip_city_variable,
0205       offsetof(GeoIPRecord, region), 0, 0 },
0206 
0207     { ngx_string("geoip_region_name"), NULL,
0208       ngx_http_geoip_region_name_variable,
0209       0, 0, 0 },
0210 
0211     { ngx_string("geoip_city"), NULL,
0212       ngx_http_geoip_city_variable,
0213       offsetof(GeoIPRecord, city), 0, 0 },
0214 
0215     { ngx_string("geoip_postal_code"), NULL,
0216       ngx_http_geoip_city_variable,
0217       offsetof(GeoIPRecord, postal_code), 0, 0 },
0218 
0219     { ngx_string("geoip_latitude"), NULL,
0220       ngx_http_geoip_city_float_variable,
0221       offsetof(GeoIPRecord, latitude), 0, 0 },
0222 
0223     { ngx_string("geoip_longitude"), NULL,
0224       ngx_http_geoip_city_float_variable,
0225       offsetof(GeoIPRecord, longitude), 0, 0 },
0226 
0227     { ngx_string("geoip_dma_code"), NULL,
0228       ngx_http_geoip_city_int_variable,
0229       offsetof(GeoIPRecord, dma_code), 0, 0 },
0230 
0231     { ngx_string("geoip_area_code"), NULL,
0232       ngx_http_geoip_city_int_variable,
0233       offsetof(GeoIPRecord, area_code), 0, 0 },
0234 
0235       ngx_http_null_variable
0236 };
0237 
0238 
0239 static u_long
0240 ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
0241 {
0242     ngx_addr_t           addr;
0243     ngx_array_t         *xfwd;
0244     struct sockaddr_in  *sin;
0245 
0246     addr.sockaddr = r->connection->sockaddr;
0247     addr.socklen = r->connection->socklen;
0248     /* addr.name = r->connection->addr_text; */
0249 
0250     xfwd = &r->headers_in.x_forwarded_for;
0251 
0252     if (xfwd->nelts > 0 && gcf->proxies != NULL) {
0253         (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
0254                                            gcf->proxies, gcf->proxy_recursive);
0255     }
0256 
0257 #if (NGX_HAVE_INET6)
0258 
0259     if (addr.sockaddr->sa_family == AF_INET6) {
0260         u_char           *p;
0261         in_addr_t         inaddr;
0262         struct in6_addr  *inaddr6;
0263 
0264         inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
0265 
0266         if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
0267             p = inaddr6->s6_addr;
0268 
0269             inaddr = p[12] << 24;
0270             inaddr += p[13] << 16;
0271             inaddr += p[14] << 8;
0272             inaddr += p[15];
0273 
0274             return inaddr;
0275         }
0276     }
0277 
0278 #endif
0279 
0280     if (addr.sockaddr->sa_family != AF_INET) {
0281         return INADDR_NONE;
0282     }
0283 
0284     sin = (struct sockaddr_in *) addr.sockaddr;
0285     return ntohl(sin->sin_addr.s_addr);
0286 }
0287 
0288 
0289 #if (NGX_HAVE_GEOIP_V6)
0290 
0291 static geoipv6_t
0292 ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
0293 {
0294     ngx_addr_t            addr;
0295     ngx_array_t          *xfwd;
0296     in_addr_t             addr4;
0297     struct in6_addr       addr6;
0298     struct sockaddr_in   *sin;
0299     struct sockaddr_in6  *sin6;
0300 
0301     addr.sockaddr = r->connection->sockaddr;
0302     addr.socklen = r->connection->socklen;
0303     /* addr.name = r->connection->addr_text; */
0304 
0305     xfwd = &r->headers_in.x_forwarded_for;
0306 
0307     if (xfwd->nelts > 0 && gcf->proxies != NULL) {
0308         (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
0309                                            gcf->proxies, gcf->proxy_recursive);
0310     }
0311 
0312     switch (addr.sockaddr->sa_family) {
0313 
0314     case AF_INET:
0315         /* Produce IPv4-mapped IPv6 address. */
0316         sin = (struct sockaddr_in *) addr.sockaddr;
0317         addr4 = ntohl(sin->sin_addr.s_addr);
0318 
0319         ngx_memzero(&addr6, sizeof(struct in6_addr));
0320         addr6.s6_addr[10] = 0xff;
0321         addr6.s6_addr[11] = 0xff;
0322         addr6.s6_addr[12] = addr4 >> 24;
0323         addr6.s6_addr[13] = addr4 >> 16;
0324         addr6.s6_addr[14] = addr4 >> 8;
0325         addr6.s6_addr[15] = addr4;
0326         return addr6;
0327 
0328     case AF_INET6:
0329         sin6 = (struct sockaddr_in6 *) addr.sockaddr;
0330         return sin6->sin6_addr;
0331 
0332     default:
0333         return in6addr_any;
0334     }
0335 }
0336 
0337 #endif
0338 
0339 
0340 static ngx_int_t
0341 ngx_http_geoip_country_variable(ngx_http_request_t *r,
0342     ngx_http_variable_value_t *v, uintptr_t data)
0343 {
0344     ngx_http_geoip_variable_handler_pt     handler =
0345         ngx_http_geoip_country_functions[data];
0346 #if (NGX_HAVE_GEOIP_V6)
0347     ngx_http_geoip_variable_handler_v6_pt  handler_v6 =
0348         ngx_http_geoip_country_v6_functions[data];
0349 #endif
0350 
0351     const char             *val;
0352     ngx_http_geoip_conf_t  *gcf;
0353 
0354     gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
0355 
0356     if (gcf->country == NULL) {
0357         goto not_found;
0358     }
0359 
0360 #if (NGX_HAVE_GEOIP_V6)
0361     val = gcf->country_v6
0362               ? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r, gcf))
0363               : handler(gcf->country, ngx_http_geoip_addr(r, gcf));
0364 #else
0365     val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
0366 #endif
0367 
0368     if (val == NULL) {
0369         goto not_found;
0370     }
0371 
0372     v->len = ngx_strlen(val);
0373     v->valid = 1;
0374     v->no_cacheable = 0;
0375     v->not_found = 0;
0376     v->data = (u_char *) val;
0377 
0378     return NGX_OK;
0379 
0380 not_found:
0381 
0382     v->not_found = 1;
0383 
0384     return NGX_OK;
0385 }
0386 
0387 
0388 static ngx_int_t
0389 ngx_http_geoip_org_variable(ngx_http_request_t *r,
0390     ngx_http_variable_value_t *v, uintptr_t data)
0391 {
0392     size_t                  len;
0393     char                   *val;
0394     ngx_http_geoip_conf_t  *gcf;
0395 
0396     gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
0397 
0398     if (gcf->org == NULL) {
0399         goto not_found;
0400     }
0401 
0402 #if (NGX_HAVE_GEOIP_V6)
0403     val = gcf->org_v6
0404               ? GeoIP_name_by_ipnum_v6(gcf->org,
0405                                        ngx_http_geoip_addr_v6(r, gcf))
0406               : GeoIP_name_by_ipnum(gcf->org,
0407                                     ngx_http_geoip_addr(r, gcf));
0408 #else
0409     val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
0410 #endif
0411 
0412     if (val == NULL) {
0413         goto not_found;
0414     }
0415 
0416     len = ngx_strlen(val);
0417     v->data = ngx_pnalloc(r->pool, len);
0418     if (v->data == NULL) {
0419         ngx_free(val);
0420         return NGX_ERROR;
0421     }
0422 
0423     ngx_memcpy(v->data, val, len);
0424 
0425     v->len = len;
0426     v->valid = 1;
0427     v->no_cacheable = 0;
0428     v->not_found = 0;
0429 
0430     ngx_free(val);
0431 
0432     return NGX_OK;
0433 
0434 not_found:
0435 
0436     v->not_found = 1;
0437 
0438     return NGX_OK;
0439 }
0440 
0441 
0442 static ngx_int_t
0443 ngx_http_geoip_city_variable(ngx_http_request_t *r,
0444     ngx_http_variable_value_t *v, uintptr_t data)
0445 {
0446     char         *val;
0447     size_t        len;
0448     GeoIPRecord  *gr;
0449 
0450     gr = ngx_http_geoip_get_city_record(r);
0451     if (gr == NULL) {
0452         goto not_found;
0453     }
0454 
0455     val = *(char **) ((char *) gr + data);
0456     if (val == NULL) {
0457         goto no_value;
0458     }
0459 
0460     len = ngx_strlen(val);
0461     v->data = ngx_pnalloc(r->pool, len);
0462     if (v->data == NULL) {
0463         GeoIPRecord_delete(gr);
0464         return NGX_ERROR;
0465     }
0466 
0467     ngx_memcpy(v->data, val, len);
0468 
0469     v->len = len;
0470     v->valid = 1;
0471     v->no_cacheable = 0;
0472     v->not_found = 0;
0473 
0474     GeoIPRecord_delete(gr);
0475 
0476     return NGX_OK;
0477 
0478 no_value:
0479 
0480     GeoIPRecord_delete(gr);
0481 
0482 not_found:
0483 
0484     v->not_found = 1;
0485 
0486     return NGX_OK;
0487 }
0488 
0489 
0490 static ngx_int_t
0491 ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
0492     ngx_http_variable_value_t *v, uintptr_t data)
0493 {
0494     size_t        len;
0495     const char   *val;
0496     GeoIPRecord  *gr;
0497 
0498     gr = ngx_http_geoip_get_city_record(r);
0499     if (gr == NULL) {
0500         goto not_found;
0501     }
0502 
0503     val = GeoIP_region_name_by_code(gr->country_code, gr->region);
0504 
0505     GeoIPRecord_delete(gr);
0506 
0507     if (val == NULL) {
0508         goto not_found;
0509     }
0510 
0511     len = ngx_strlen(val);
0512     v->data = ngx_pnalloc(r->pool, len);
0513     if (v->data == NULL) {
0514         return NGX_ERROR;
0515     }
0516 
0517     ngx_memcpy(v->data, val, len);
0518 
0519     v->len = len;
0520     v->valid = 1;
0521     v->no_cacheable = 0;
0522     v->not_found = 0;
0523 
0524     return NGX_OK;
0525 
0526 not_found:
0527 
0528     v->not_found = 1;
0529 
0530     return NGX_OK;
0531 }
0532 
0533 
0534 static ngx_int_t
0535 ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
0536     ngx_http_variable_value_t *v, uintptr_t data)
0537 {
0538     float         val;
0539     GeoIPRecord  *gr;
0540 
0541     gr = ngx_http_geoip_get_city_record(r);
0542     if (gr == NULL) {
0543         v->not_found = 1;
0544         return NGX_OK;
0545     }
0546 
0547     v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
0548     if (v->data == NULL) {
0549         GeoIPRecord_delete(gr);
0550         return NGX_ERROR;
0551     }
0552 
0553     val = *(float *) ((char *) gr + data);
0554 
0555     v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
0556     v->valid = 1;
0557     v->no_cacheable = 0;
0558     v->not_found = 0;
0559 
0560     GeoIPRecord_delete(gr);
0561 
0562     return NGX_OK;
0563 }
0564 
0565 
0566 static ngx_int_t
0567 ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
0568     ngx_http_variable_value_t *v, uintptr_t data)
0569 {
0570     int           val;
0571     GeoIPRecord  *gr;
0572 
0573     gr = ngx_http_geoip_get_city_record(r);
0574     if (gr == NULL) {
0575         v->not_found = 1;
0576         return NGX_OK;
0577     }
0578 
0579     v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
0580     if (v->data == NULL) {
0581         GeoIPRecord_delete(gr);
0582         return NGX_ERROR;
0583     }
0584 
0585     val = *(int *) ((char *) gr + data);
0586 
0587     v->len = ngx_sprintf(v->data, "%d", val) - v->data;
0588     v->valid = 1;
0589     v->no_cacheable = 0;
0590     v->not_found = 0;
0591 
0592     GeoIPRecord_delete(gr);
0593 
0594     return NGX_OK;
0595 }
0596 
0597 
0598 static GeoIPRecord *
0599 ngx_http_geoip_get_city_record(ngx_http_request_t *r)
0600 {
0601     ngx_http_geoip_conf_t  *gcf;
0602 
0603     gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
0604 
0605     if (gcf->city) {
0606 #if (NGX_HAVE_GEOIP_V6)
0607         return gcf->city_v6
0608                    ? GeoIP_record_by_ipnum_v6(gcf->city,
0609                                               ngx_http_geoip_addr_v6(r, gcf))
0610                    : GeoIP_record_by_ipnum(gcf->city,
0611                                            ngx_http_geoip_addr(r, gcf));
0612 #else
0613         return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
0614 #endif
0615     }
0616 
0617     return NULL;
0618 }
0619 
0620 
0621 static ngx_int_t
0622 ngx_http_geoip_add_variables(ngx_conf_t *cf)
0623 {
0624     ngx_http_variable_t  *var, *v;
0625 
0626     for (v = ngx_http_geoip_vars; v->name.len; v++) {
0627         var = ngx_http_add_variable(cf, &v->name, v->flags);
0628         if (var == NULL) {
0629             return NGX_ERROR;
0630         }
0631 
0632         var->get_handler = v->get_handler;
0633         var->data = v->data;
0634     }
0635 
0636     return NGX_OK;
0637 }
0638 
0639 
0640 static void *
0641 ngx_http_geoip_create_conf(ngx_conf_t *cf)
0642 {
0643     ngx_pool_cleanup_t     *cln;
0644     ngx_http_geoip_conf_t  *conf;
0645 
0646     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t));
0647     if (conf == NULL) {
0648         return NULL;
0649     }
0650 
0651     conf->proxy_recursive = NGX_CONF_UNSET;
0652 
0653     cln = ngx_pool_cleanup_add(cf->pool, 0);
0654     if (cln == NULL) {
0655         return NULL;
0656     }
0657 
0658     cln->handler = ngx_http_geoip_cleanup;
0659     cln->data = conf;
0660 
0661     return conf;
0662 }
0663 
0664 
0665 static char *
0666 ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
0667 {
0668     ngx_http_geoip_conf_t  *gcf = conf;
0669 
0670     ngx_conf_init_value(gcf->proxy_recursive, 0);
0671 
0672     return NGX_CONF_OK;
0673 }
0674 
0675 
0676 static char *
0677 ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0678 {
0679     ngx_http_geoip_conf_t  *gcf = conf;
0680 
0681     ngx_str_t  *value;
0682 
0683     if (gcf->country) {
0684         return "is duplicate";
0685     }
0686 
0687     value = cf->args->elts;
0688 
0689     gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0690 
0691     if (gcf->country == NULL) {
0692         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0693                            "GeoIP_open(\"%V\") failed", &value[1]);
0694 
0695         return NGX_CONF_ERROR;
0696     }
0697 
0698     if (cf->args->nelts == 3) {
0699         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0700             GeoIP_set_charset(gcf->country, GEOIP_CHARSET_UTF8);
0701 
0702         } else {
0703             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0704                                "invalid parameter \"%V\"", &value[2]);
0705             return NGX_CONF_ERROR;
0706         }
0707     }
0708 
0709     switch (gcf->country->databaseType) {
0710 
0711     case GEOIP_COUNTRY_EDITION:
0712 
0713         return NGX_CONF_OK;
0714 
0715 #if (NGX_HAVE_GEOIP_V6)
0716     case GEOIP_COUNTRY_EDITION_V6:
0717 
0718         gcf->country_v6 = 1;
0719         return NGX_CONF_OK;
0720 #endif
0721 
0722     default:
0723         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0724                            "invalid GeoIP database \"%V\" type:%d",
0725                            &value[1], gcf->country->databaseType);
0726         return NGX_CONF_ERROR;
0727     }
0728 }
0729 
0730 
0731 static char *
0732 ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0733 {
0734     ngx_http_geoip_conf_t  *gcf = conf;
0735 
0736     ngx_str_t  *value;
0737 
0738     if (gcf->org) {
0739         return "is duplicate";
0740     }
0741 
0742     value = cf->args->elts;
0743 
0744     gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0745 
0746     if (gcf->org == NULL) {
0747         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0748                            "GeoIP_open(\"%V\") failed", &value[1]);
0749 
0750         return NGX_CONF_ERROR;
0751     }
0752 
0753     if (cf->args->nelts == 3) {
0754         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0755             GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8);
0756 
0757         } else {
0758             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0759                                "invalid parameter \"%V\"", &value[2]);
0760             return NGX_CONF_ERROR;
0761         }
0762     }
0763 
0764     switch (gcf->org->databaseType) {
0765 
0766     case GEOIP_ISP_EDITION:
0767     case GEOIP_ORG_EDITION:
0768     case GEOIP_DOMAIN_EDITION:
0769     case GEOIP_ASNUM_EDITION:
0770 
0771         return NGX_CONF_OK;
0772 
0773 #if (NGX_HAVE_GEOIP_V6)
0774     case GEOIP_ISP_EDITION_V6:
0775     case GEOIP_ORG_EDITION_V6:
0776     case GEOIP_DOMAIN_EDITION_V6:
0777     case GEOIP_ASNUM_EDITION_V6:
0778 
0779         gcf->org_v6 = 1;
0780         return NGX_CONF_OK;
0781 #endif
0782 
0783     default:
0784         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0785                            "invalid GeoIP database \"%V\" type:%d",
0786                            &value[1], gcf->org->databaseType);
0787         return NGX_CONF_ERROR;
0788     }
0789 }
0790 
0791 
0792 static char *
0793 ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0794 {
0795     ngx_http_geoip_conf_t  *gcf = conf;
0796 
0797     ngx_str_t  *value;
0798 
0799     if (gcf->city) {
0800         return "is duplicate";
0801     }
0802 
0803     value = cf->args->elts;
0804 
0805     gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0806 
0807     if (gcf->city == NULL) {
0808         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0809                            "GeoIP_open(\"%V\") failed", &value[1]);
0810 
0811         return NGX_CONF_ERROR;
0812     }
0813 
0814     if (cf->args->nelts == 3) {
0815         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0816             GeoIP_set_charset(gcf->city, GEOIP_CHARSET_UTF8);
0817 
0818         } else {
0819             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0820                                "invalid parameter \"%V\"", &value[2]);
0821             return NGX_CONF_ERROR;
0822         }
0823     }
0824 
0825     switch (gcf->city->databaseType) {
0826 
0827     case GEOIP_CITY_EDITION_REV0:
0828     case GEOIP_CITY_EDITION_REV1:
0829 
0830         return NGX_CONF_OK;
0831 
0832 #if (NGX_HAVE_GEOIP_V6)
0833     case GEOIP_CITY_EDITION_REV0_V6:
0834     case GEOIP_CITY_EDITION_REV1_V6:
0835 
0836         gcf->city_v6 = 1;
0837         return NGX_CONF_OK;
0838 #endif
0839 
0840     default:
0841         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0842                            "invalid GeoIP City database \"%V\" type:%d",
0843                            &value[1], gcf->city->databaseType);
0844         return NGX_CONF_ERROR;
0845     }
0846 }
0847 
0848 
0849 static char *
0850 ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0851 {
0852     ngx_http_geoip_conf_t  *gcf = conf;
0853 
0854     ngx_str_t   *value;
0855     ngx_cidr_t  cidr, *c;
0856 
0857     value = cf->args->elts;
0858 
0859     if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
0860         return NGX_CONF_ERROR;
0861     }
0862 
0863     if (gcf->proxies == NULL) {
0864         gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
0865         if (gcf->proxies == NULL) {
0866             return NGX_CONF_ERROR;
0867         }
0868     }
0869 
0870     c = ngx_array_push(gcf->proxies);
0871     if (c == NULL) {
0872         return NGX_CONF_ERROR;
0873     }
0874 
0875     *c = cidr;
0876 
0877     return NGX_CONF_OK;
0878 }
0879 
0880 static ngx_int_t
0881 ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
0882 {
0883     ngx_int_t  rc;
0884 
0885     if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
0886         cidr->family = AF_INET;
0887         cidr->u.in.addr = 0xffffffff;
0888         cidr->u.in.mask = 0xffffffff;
0889 
0890         return NGX_OK;
0891     }
0892 
0893     rc = ngx_ptocidr(net, cidr);
0894 
0895     if (rc == NGX_ERROR) {
0896         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
0897         return NGX_ERROR;
0898     }
0899 
0900     if (rc == NGX_DONE) {
0901         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
0902                            "low address bits of %V are meaningless", net);
0903     }
0904 
0905     return NGX_OK;
0906 }
0907 
0908 
0909 static void
0910 ngx_http_geoip_cleanup(void *data)
0911 {
0912     ngx_http_geoip_conf_t  *gcf = data;
0913 
0914     if (gcf->country) {
0915         GeoIP_delete(gcf->country);
0916     }
0917 
0918     if (gcf->org) {
0919         GeoIP_delete(gcf->org);
0920     }
0921 
0922     if (gcf->city) {
0923         GeoIP_delete(gcf->city);
0924     }
0925 }