Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

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_stream.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 #if (NGX_HAVE_GEOIP_V6)
0026     unsigned      country_v6:1;
0027     unsigned      org_v6:1;
0028     unsigned      city_v6:1;
0029 #endif
0030 } ngx_stream_geoip_conf_t;
0031 
0032 
0033 typedef struct {
0034     ngx_str_t    *name;
0035     uintptr_t     data;
0036 } ngx_stream_geoip_var_t;
0037 
0038 
0039 typedef const char *(*ngx_stream_geoip_variable_handler_pt)(GeoIP *,
0040     u_long addr);
0041 
0042 
0043 ngx_stream_geoip_variable_handler_pt ngx_stream_geoip_country_functions[] = {
0044     GeoIP_country_code_by_ipnum,
0045     GeoIP_country_code3_by_ipnum,
0046     GeoIP_country_name_by_ipnum,
0047 };
0048 
0049 
0050 #if (NGX_HAVE_GEOIP_V6)
0051 
0052 typedef const char *(*ngx_stream_geoip_variable_handler_v6_pt)(GeoIP *,
0053     geoipv6_t addr);
0054 
0055 
0056 ngx_stream_geoip_variable_handler_v6_pt
0057     ngx_stream_geoip_country_v6_functions[] =
0058 {
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_stream_geoip_country_variable(ngx_stream_session_t *s,
0068     ngx_stream_variable_value_t *v, uintptr_t data);
0069 static ngx_int_t ngx_stream_geoip_org_variable(ngx_stream_session_t *s,
0070     ngx_stream_variable_value_t *v, uintptr_t data);
0071 static ngx_int_t ngx_stream_geoip_city_variable(ngx_stream_session_t *s,
0072     ngx_stream_variable_value_t *v, uintptr_t data);
0073 static ngx_int_t ngx_stream_geoip_region_name_variable(ngx_stream_session_t *s,
0074     ngx_stream_variable_value_t *v, uintptr_t data);
0075 static ngx_int_t ngx_stream_geoip_city_float_variable(ngx_stream_session_t *s,
0076     ngx_stream_variable_value_t *v, uintptr_t data);
0077 static ngx_int_t ngx_stream_geoip_city_int_variable(ngx_stream_session_t *s,
0078     ngx_stream_variable_value_t *v, uintptr_t data);
0079 static GeoIPRecord *ngx_stream_geoip_get_city_record(ngx_stream_session_t *s);
0080 
0081 static ngx_int_t ngx_stream_geoip_add_variables(ngx_conf_t *cf);
0082 static void *ngx_stream_geoip_create_conf(ngx_conf_t *cf);
0083 static char *ngx_stream_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
0084     void *conf);
0085 static char *ngx_stream_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
0086     void *conf);
0087 static char *ngx_stream_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
0088     void *conf);
0089 static void ngx_stream_geoip_cleanup(void *data);
0090 
0091 
0092 static ngx_command_t  ngx_stream_geoip_commands[] = {
0093 
0094     { ngx_string("geoip_country"),
0095       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12,
0096       ngx_stream_geoip_country,
0097       NGX_STREAM_MAIN_CONF_OFFSET,
0098       0,
0099       NULL },
0100 
0101     { ngx_string("geoip_org"),
0102       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12,
0103       ngx_stream_geoip_org,
0104       NGX_STREAM_MAIN_CONF_OFFSET,
0105       0,
0106       NULL },
0107 
0108     { ngx_string("geoip_city"),
0109       NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE12,
0110       ngx_stream_geoip_city,
0111       NGX_STREAM_MAIN_CONF_OFFSET,
0112       0,
0113       NULL },
0114 
0115       ngx_null_command
0116 };
0117 
0118 
0119 static ngx_stream_module_t  ngx_stream_geoip_module_ctx = {
0120     ngx_stream_geoip_add_variables,        /* preconfiguration */
0121     NULL,                                  /* postconfiguration */
0122 
0123     ngx_stream_geoip_create_conf,          /* create main configuration */
0124     NULL,                                  /* init main configuration */
0125 
0126     NULL,                                  /* create server configuration */
0127     NULL                                   /* merge server configuration */
0128 };
0129 
0130 
0131 ngx_module_t  ngx_stream_geoip_module = {
0132     NGX_MODULE_V1,
0133     &ngx_stream_geoip_module_ctx,          /* module context */
0134     ngx_stream_geoip_commands,             /* module directives */
0135     NGX_STREAM_MODULE,                     /* module type */
0136     NULL,                                  /* init master */
0137     NULL,                                  /* init module */
0138     NULL,                                  /* init process */
0139     NULL,                                  /* init thread */
0140     NULL,                                  /* exit thread */
0141     NULL,                                  /* exit process */
0142     NULL,                                  /* exit master */
0143     NGX_MODULE_V1_PADDING
0144 };
0145 
0146 
0147 static ngx_stream_variable_t  ngx_stream_geoip_vars[] = {
0148 
0149     { ngx_string("geoip_country_code"), NULL,
0150       ngx_stream_geoip_country_variable,
0151       NGX_GEOIP_COUNTRY_CODE, 0, 0 },
0152 
0153     { ngx_string("geoip_country_code3"), NULL,
0154       ngx_stream_geoip_country_variable,
0155       NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
0156 
0157     { ngx_string("geoip_country_name"), NULL,
0158       ngx_stream_geoip_country_variable,
0159       NGX_GEOIP_COUNTRY_NAME, 0, 0 },
0160 
0161     { ngx_string("geoip_org"), NULL,
0162       ngx_stream_geoip_org_variable,
0163       0, 0, 0 },
0164 
0165     { ngx_string("geoip_city_continent_code"), NULL,
0166       ngx_stream_geoip_city_variable,
0167       offsetof(GeoIPRecord, continent_code), 0, 0 },
0168 
0169     { ngx_string("geoip_city_country_code"), NULL,
0170       ngx_stream_geoip_city_variable,
0171       offsetof(GeoIPRecord, country_code), 0, 0 },
0172 
0173     { ngx_string("geoip_city_country_code3"), NULL,
0174       ngx_stream_geoip_city_variable,
0175       offsetof(GeoIPRecord, country_code3), 0, 0 },
0176 
0177     { ngx_string("geoip_city_country_name"), NULL,
0178       ngx_stream_geoip_city_variable,
0179       offsetof(GeoIPRecord, country_name), 0, 0 },
0180 
0181     { ngx_string("geoip_region"), NULL,
0182       ngx_stream_geoip_city_variable,
0183       offsetof(GeoIPRecord, region), 0, 0 },
0184 
0185     { ngx_string("geoip_region_name"), NULL,
0186       ngx_stream_geoip_region_name_variable,
0187       0, 0, 0 },
0188 
0189     { ngx_string("geoip_city"), NULL,
0190       ngx_stream_geoip_city_variable,
0191       offsetof(GeoIPRecord, city), 0, 0 },
0192 
0193     { ngx_string("geoip_postal_code"), NULL,
0194       ngx_stream_geoip_city_variable,
0195       offsetof(GeoIPRecord, postal_code), 0, 0 },
0196 
0197     { ngx_string("geoip_latitude"), NULL,
0198       ngx_stream_geoip_city_float_variable,
0199       offsetof(GeoIPRecord, latitude), 0, 0 },
0200 
0201     { ngx_string("geoip_longitude"), NULL,
0202       ngx_stream_geoip_city_float_variable,
0203       offsetof(GeoIPRecord, longitude), 0, 0 },
0204 
0205     { ngx_string("geoip_dma_code"), NULL,
0206       ngx_stream_geoip_city_int_variable,
0207       offsetof(GeoIPRecord, dma_code), 0, 0 },
0208 
0209     { ngx_string("geoip_area_code"), NULL,
0210       ngx_stream_geoip_city_int_variable,
0211       offsetof(GeoIPRecord, area_code), 0, 0 },
0212 
0213       ngx_stream_null_variable
0214 };
0215 
0216 
0217 static u_long
0218 ngx_stream_geoip_addr(ngx_stream_session_t *s, ngx_stream_geoip_conf_t *gcf)
0219 {
0220     ngx_addr_t           addr;
0221     struct sockaddr_in  *sin;
0222 
0223     addr.sockaddr = s->connection->sockaddr;
0224     addr.socklen = s->connection->socklen;
0225     /* addr.name = s->connection->addr_text; */
0226 
0227 #if (NGX_HAVE_INET6)
0228 
0229     if (addr.sockaddr->sa_family == AF_INET6) {
0230         u_char           *p;
0231         in_addr_t         inaddr;
0232         struct in6_addr  *inaddr6;
0233 
0234         inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
0235 
0236         if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
0237             p = inaddr6->s6_addr;
0238 
0239             inaddr = p[12] << 24;
0240             inaddr += p[13] << 16;
0241             inaddr += p[14] << 8;
0242             inaddr += p[15];
0243 
0244             return inaddr;
0245         }
0246     }
0247 
0248 #endif
0249 
0250     if (addr.sockaddr->sa_family != AF_INET) {
0251         return INADDR_NONE;
0252     }
0253 
0254     sin = (struct sockaddr_in *) addr.sockaddr;
0255     return ntohl(sin->sin_addr.s_addr);
0256 }
0257 
0258 
0259 #if (NGX_HAVE_GEOIP_V6)
0260 
0261 static geoipv6_t
0262 ngx_stream_geoip_addr_v6(ngx_stream_session_t *s, ngx_stream_geoip_conf_t *gcf)
0263 {
0264     ngx_addr_t            addr;
0265     in_addr_t             addr4;
0266     struct in6_addr       addr6;
0267     struct sockaddr_in   *sin;
0268     struct sockaddr_in6  *sin6;
0269 
0270     addr.sockaddr = s->connection->sockaddr;
0271     addr.socklen = s->connection->socklen;
0272     /* addr.name = s->connection->addr_text; */
0273 
0274     switch (addr.sockaddr->sa_family) {
0275 
0276     case AF_INET:
0277         /* Produce IPv4-mapped IPv6 address. */
0278         sin = (struct sockaddr_in *) addr.sockaddr;
0279         addr4 = ntohl(sin->sin_addr.s_addr);
0280 
0281         ngx_memzero(&addr6, sizeof(struct in6_addr));
0282         addr6.s6_addr[10] = 0xff;
0283         addr6.s6_addr[11] = 0xff;
0284         addr6.s6_addr[12] = addr4 >> 24;
0285         addr6.s6_addr[13] = addr4 >> 16;
0286         addr6.s6_addr[14] = addr4 >> 8;
0287         addr6.s6_addr[15] = addr4;
0288         return addr6;
0289 
0290     case AF_INET6:
0291         sin6 = (struct sockaddr_in6 *) addr.sockaddr;
0292         return sin6->sin6_addr;
0293 
0294     default:
0295         return in6addr_any;
0296     }
0297 }
0298 
0299 #endif
0300 
0301 
0302 static ngx_int_t
0303 ngx_stream_geoip_country_variable(ngx_stream_session_t *s,
0304     ngx_stream_variable_value_t *v, uintptr_t data)
0305 {
0306     ngx_stream_geoip_variable_handler_pt     handler =
0307         ngx_stream_geoip_country_functions[data];
0308 #if (NGX_HAVE_GEOIP_V6)
0309     ngx_stream_geoip_variable_handler_v6_pt  handler_v6 =
0310         ngx_stream_geoip_country_v6_functions[data];
0311 #endif
0312 
0313     const char               *val;
0314     ngx_stream_geoip_conf_t  *gcf;
0315 
0316     gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module);
0317 
0318     if (gcf->country == NULL) {
0319         goto not_found;
0320     }
0321 
0322 #if (NGX_HAVE_GEOIP_V6)
0323     val = gcf->country_v6
0324               ? handler_v6(gcf->country, ngx_stream_geoip_addr_v6(s, gcf))
0325               : handler(gcf->country, ngx_stream_geoip_addr(s, gcf));
0326 #else
0327     val = handler(gcf->country, ngx_stream_geoip_addr(s, gcf));
0328 #endif
0329 
0330     if (val == NULL) {
0331         goto not_found;
0332     }
0333 
0334     v->len = ngx_strlen(val);
0335     v->valid = 1;
0336     v->no_cacheable = 0;
0337     v->not_found = 0;
0338     v->data = (u_char *) val;
0339 
0340     return NGX_OK;
0341 
0342 not_found:
0343 
0344     v->not_found = 1;
0345 
0346     return NGX_OK;
0347 }
0348 
0349 
0350 static ngx_int_t
0351 ngx_stream_geoip_org_variable(ngx_stream_session_t *s,
0352     ngx_stream_variable_value_t *v, uintptr_t data)
0353 {
0354     size_t                    len;
0355     char                     *val;
0356     ngx_stream_geoip_conf_t  *gcf;
0357 
0358     gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module);
0359 
0360     if (gcf->org == NULL) {
0361         goto not_found;
0362     }
0363 
0364 #if (NGX_HAVE_GEOIP_V6)
0365     val = gcf->org_v6
0366               ? GeoIP_name_by_ipnum_v6(gcf->org,
0367                                        ngx_stream_geoip_addr_v6(s, gcf))
0368               : GeoIP_name_by_ipnum(gcf->org,
0369                                     ngx_stream_geoip_addr(s, gcf));
0370 #else
0371     val = GeoIP_name_by_ipnum(gcf->org, ngx_stream_geoip_addr(s, gcf));
0372 #endif
0373 
0374     if (val == NULL) {
0375         goto not_found;
0376     }
0377 
0378     len = ngx_strlen(val);
0379     v->data = ngx_pnalloc(s->connection->pool, len);
0380     if (v->data == NULL) {
0381         ngx_free(val);
0382         return NGX_ERROR;
0383     }
0384 
0385     ngx_memcpy(v->data, val, len);
0386 
0387     v->len = len;
0388     v->valid = 1;
0389     v->no_cacheable = 0;
0390     v->not_found = 0;
0391 
0392     ngx_free(val);
0393 
0394     return NGX_OK;
0395 
0396 not_found:
0397 
0398     v->not_found = 1;
0399 
0400     return NGX_OK;
0401 }
0402 
0403 
0404 static ngx_int_t
0405 ngx_stream_geoip_city_variable(ngx_stream_session_t *s,
0406     ngx_stream_variable_value_t *v, uintptr_t data)
0407 {
0408     char         *val;
0409     size_t        len;
0410     GeoIPRecord  *gr;
0411 
0412     gr = ngx_stream_geoip_get_city_record(s);
0413     if (gr == NULL) {
0414         goto not_found;
0415     }
0416 
0417     val = *(char **) ((char *) gr + data);
0418     if (val == NULL) {
0419         goto no_value;
0420     }
0421 
0422     len = ngx_strlen(val);
0423     v->data = ngx_pnalloc(s->connection->pool, len);
0424     if (v->data == NULL) {
0425         GeoIPRecord_delete(gr);
0426         return NGX_ERROR;
0427     }
0428 
0429     ngx_memcpy(v->data, val, len);
0430 
0431     v->len = len;
0432     v->valid = 1;
0433     v->no_cacheable = 0;
0434     v->not_found = 0;
0435 
0436     GeoIPRecord_delete(gr);
0437 
0438     return NGX_OK;
0439 
0440 no_value:
0441 
0442     GeoIPRecord_delete(gr);
0443 
0444 not_found:
0445 
0446     v->not_found = 1;
0447 
0448     return NGX_OK;
0449 }
0450 
0451 
0452 static ngx_int_t
0453 ngx_stream_geoip_region_name_variable(ngx_stream_session_t *s,
0454     ngx_stream_variable_value_t *v, uintptr_t data)
0455 {
0456     size_t        len;
0457     const char   *val;
0458     GeoIPRecord  *gr;
0459 
0460     gr = ngx_stream_geoip_get_city_record(s);
0461     if (gr == NULL) {
0462         goto not_found;
0463     }
0464 
0465     val = GeoIP_region_name_by_code(gr->country_code, gr->region);
0466 
0467     GeoIPRecord_delete(gr);
0468 
0469     if (val == NULL) {
0470         goto not_found;
0471     }
0472 
0473     len = ngx_strlen(val);
0474     v->data = ngx_pnalloc(s->connection->pool, len);
0475     if (v->data == NULL) {
0476         return NGX_ERROR;
0477     }
0478 
0479     ngx_memcpy(v->data, val, len);
0480 
0481     v->len = len;
0482     v->valid = 1;
0483     v->no_cacheable = 0;
0484     v->not_found = 0;
0485 
0486     return NGX_OK;
0487 
0488 not_found:
0489 
0490     v->not_found = 1;
0491 
0492     return NGX_OK;
0493 }
0494 
0495 
0496 static ngx_int_t
0497 ngx_stream_geoip_city_float_variable(ngx_stream_session_t *s,
0498     ngx_stream_variable_value_t *v, uintptr_t data)
0499 {
0500     float         val;
0501     GeoIPRecord  *gr;
0502 
0503     gr = ngx_stream_geoip_get_city_record(s);
0504     if (gr == NULL) {
0505         v->not_found = 1;
0506         return NGX_OK;
0507     }
0508 
0509     v->data = ngx_pnalloc(s->connection->pool, NGX_INT64_LEN + 5);
0510     if (v->data == NULL) {
0511         GeoIPRecord_delete(gr);
0512         return NGX_ERROR;
0513     }
0514 
0515     val = *(float *) ((char *) gr + data);
0516 
0517     v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
0518     v->valid = 1;
0519     v->no_cacheable = 0;
0520     v->not_found = 0;
0521 
0522     GeoIPRecord_delete(gr);
0523 
0524     return NGX_OK;
0525 }
0526 
0527 
0528 static ngx_int_t
0529 ngx_stream_geoip_city_int_variable(ngx_stream_session_t *s,
0530     ngx_stream_variable_value_t *v, uintptr_t data)
0531 {
0532     int           val;
0533     GeoIPRecord  *gr;
0534 
0535     gr = ngx_stream_geoip_get_city_record(s);
0536     if (gr == NULL) {
0537         v->not_found = 1;
0538         return NGX_OK;
0539     }
0540 
0541     v->data = ngx_pnalloc(s->connection->pool, NGX_INT64_LEN);
0542     if (v->data == NULL) {
0543         GeoIPRecord_delete(gr);
0544         return NGX_ERROR;
0545     }
0546 
0547     val = *(int *) ((char *) gr + data);
0548 
0549     v->len = ngx_sprintf(v->data, "%d", val) - v->data;
0550     v->valid = 1;
0551     v->no_cacheable = 0;
0552     v->not_found = 0;
0553 
0554     GeoIPRecord_delete(gr);
0555 
0556     return NGX_OK;
0557 }
0558 
0559 
0560 static GeoIPRecord *
0561 ngx_stream_geoip_get_city_record(ngx_stream_session_t *s)
0562 {
0563     ngx_stream_geoip_conf_t  *gcf;
0564 
0565     gcf = ngx_stream_get_module_main_conf(s, ngx_stream_geoip_module);
0566 
0567     if (gcf->city) {
0568 #if (NGX_HAVE_GEOIP_V6)
0569         return gcf->city_v6
0570                    ? GeoIP_record_by_ipnum_v6(gcf->city,
0571                                               ngx_stream_geoip_addr_v6(s, gcf))
0572                    : GeoIP_record_by_ipnum(gcf->city,
0573                                            ngx_stream_geoip_addr(s, gcf));
0574 #else
0575         return GeoIP_record_by_ipnum(gcf->city, ngx_stream_geoip_addr(s, gcf));
0576 #endif
0577     }
0578 
0579     return NULL;
0580 }
0581 
0582 
0583 static ngx_int_t
0584 ngx_stream_geoip_add_variables(ngx_conf_t *cf)
0585 {
0586     ngx_stream_variable_t  *var, *v;
0587 
0588     for (v = ngx_stream_geoip_vars; v->name.len; v++) {
0589         var = ngx_stream_add_variable(cf, &v->name, v->flags);
0590         if (var == NULL) {
0591             return NGX_ERROR;
0592         }
0593 
0594         var->get_handler = v->get_handler;
0595         var->data = v->data;
0596     }
0597 
0598     return NGX_OK;
0599 }
0600 
0601 
0602 static void *
0603 ngx_stream_geoip_create_conf(ngx_conf_t *cf)
0604 {
0605     ngx_pool_cleanup_t       *cln;
0606     ngx_stream_geoip_conf_t  *conf;
0607 
0608     conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_geoip_conf_t));
0609     if (conf == NULL) {
0610         return NULL;
0611     }
0612 
0613     cln = ngx_pool_cleanup_add(cf->pool, 0);
0614     if (cln == NULL) {
0615         return NULL;
0616     }
0617 
0618     cln->handler = ngx_stream_geoip_cleanup;
0619     cln->data = conf;
0620 
0621     return conf;
0622 }
0623 
0624 
0625 static char *
0626 ngx_stream_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0627 {
0628     ngx_stream_geoip_conf_t  *gcf = conf;
0629 
0630     ngx_str_t  *value;
0631 
0632     if (gcf->country) {
0633         return "is duplicate";
0634     }
0635 
0636     value = cf->args->elts;
0637 
0638     gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0639 
0640     if (gcf->country == NULL) {
0641         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0642                            "GeoIP_open(\"%V\") failed", &value[1]);
0643 
0644         return NGX_CONF_ERROR;
0645     }
0646 
0647     if (cf->args->nelts == 3) {
0648         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0649             GeoIP_set_charset(gcf->country, GEOIP_CHARSET_UTF8);
0650 
0651         } else {
0652             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0653                                "invalid parameter \"%V\"", &value[2]);
0654             return NGX_CONF_ERROR;
0655         }
0656     }
0657 
0658     switch (gcf->country->databaseType) {
0659 
0660     case GEOIP_COUNTRY_EDITION:
0661 
0662         return NGX_CONF_OK;
0663 
0664 #if (NGX_HAVE_GEOIP_V6)
0665     case GEOIP_COUNTRY_EDITION_V6:
0666 
0667         gcf->country_v6 = 1;
0668         return NGX_CONF_OK;
0669 #endif
0670 
0671     default:
0672         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0673                            "invalid GeoIP database \"%V\" type:%d",
0674                            &value[1], gcf->country->databaseType);
0675         return NGX_CONF_ERROR;
0676     }
0677 }
0678 
0679 
0680 static char *
0681 ngx_stream_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0682 {
0683     ngx_stream_geoip_conf_t  *gcf = conf;
0684 
0685     ngx_str_t  *value;
0686 
0687     if (gcf->org) {
0688         return "is duplicate";
0689     }
0690 
0691     value = cf->args->elts;
0692 
0693     gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0694 
0695     if (gcf->org == NULL) {
0696         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0697                            "GeoIP_open(\"%V\") failed", &value[1]);
0698 
0699         return NGX_CONF_ERROR;
0700     }
0701 
0702     if (cf->args->nelts == 3) {
0703         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0704             GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8);
0705 
0706         } else {
0707             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0708                                "invalid parameter \"%V\"", &value[2]);
0709             return NGX_CONF_ERROR;
0710         }
0711     }
0712 
0713     switch (gcf->org->databaseType) {
0714 
0715     case GEOIP_ISP_EDITION:
0716     case GEOIP_ORG_EDITION:
0717     case GEOIP_DOMAIN_EDITION:
0718     case GEOIP_ASNUM_EDITION:
0719 
0720         return NGX_CONF_OK;
0721 
0722 #if (NGX_HAVE_GEOIP_V6)
0723     case GEOIP_ISP_EDITION_V6:
0724     case GEOIP_ORG_EDITION_V6:
0725     case GEOIP_DOMAIN_EDITION_V6:
0726     case GEOIP_ASNUM_EDITION_V6:
0727 
0728         gcf->org_v6 = 1;
0729         return NGX_CONF_OK;
0730 #endif
0731 
0732     default:
0733         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0734                            "invalid GeoIP database \"%V\" type:%d",
0735                            &value[1], gcf->org->databaseType);
0736         return NGX_CONF_ERROR;
0737     }
0738 }
0739 
0740 
0741 static char *
0742 ngx_stream_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0743 {
0744     ngx_stream_geoip_conf_t  *gcf = conf;
0745 
0746     ngx_str_t  *value;
0747 
0748     if (gcf->city) {
0749         return "is duplicate";
0750     }
0751 
0752     value = cf->args->elts;
0753 
0754     gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
0755 
0756     if (gcf->city == NULL) {
0757         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0758                            "GeoIP_open(\"%V\") failed", &value[1]);
0759 
0760         return NGX_CONF_ERROR;
0761     }
0762 
0763     if (cf->args->nelts == 3) {
0764         if (ngx_strcmp(value[2].data, "utf8") == 0) {
0765             GeoIP_set_charset(gcf->city, GEOIP_CHARSET_UTF8);
0766 
0767         } else {
0768             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0769                                "invalid parameter \"%V\"", &value[2]);
0770             return NGX_CONF_ERROR;
0771         }
0772     }
0773 
0774     switch (gcf->city->databaseType) {
0775 
0776     case GEOIP_CITY_EDITION_REV0:
0777     case GEOIP_CITY_EDITION_REV1:
0778 
0779         return NGX_CONF_OK;
0780 
0781 #if (NGX_HAVE_GEOIP_V6)
0782     case GEOIP_CITY_EDITION_REV0_V6:
0783     case GEOIP_CITY_EDITION_REV1_V6:
0784 
0785         gcf->city_v6 = 1;
0786         return NGX_CONF_OK;
0787 #endif
0788 
0789     default:
0790         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
0791                            "invalid GeoIP City database \"%V\" type:%d",
0792                            &value[1], gcf->city->databaseType);
0793         return NGX_CONF_ERROR;
0794     }
0795 }
0796 
0797 
0798 static void
0799 ngx_stream_geoip_cleanup(void *data)
0800 {
0801     ngx_stream_geoip_conf_t  *gcf = data;
0802 
0803     if (gcf->country) {
0804         GeoIP_delete(gcf->country);
0805     }
0806 
0807     if (gcf->org) {
0808         GeoIP_delete(gcf->org);
0809     }
0810 
0811     if (gcf->city) {
0812         GeoIP_delete(gcf->city);
0813     }
0814 }