0001
0002
0003
0004
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;
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,
0140 NULL,
0141
0142 ngx_http_geoip_create_conf,
0143 ngx_http_geoip_init_conf,
0144
0145 NULL,
0146 NULL,
0147
0148 NULL,
0149 NULL
0150 };
0151
0152
0153 ngx_module_t ngx_http_geoip_module = {
0154 NGX_MODULE_V1,
0155 &ngx_http_geoip_module_ctx,
0156 ngx_http_geoip_commands,
0157 NGX_HTTP_MODULE,
0158 NULL,
0159 NULL,
0160 NULL,
0161 NULL,
0162 NULL,
0163 NULL,
0164 NULL,
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
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
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
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 }