Annotation of embedaddon/nginx/src/http/modules/ngx_http_geoip_module.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_http.h>
! 11:
! 12: #include <GeoIP.h>
! 13: #include <GeoIPCity.h>
! 14:
! 15:
! 16: #define NGX_GEOIP_COUNTRY_CODE 0
! 17: #define NGX_GEOIP_COUNTRY_CODE3 1
! 18: #define NGX_GEOIP_COUNTRY_NAME 2
! 19:
! 20:
! 21: typedef struct {
! 22: GeoIP *country;
! 23: GeoIP *org;
! 24: GeoIP *city;
! 25: ngx_array_t *proxies; /* array of ngx_cidr_t */
! 26: ngx_flag_t proxy_recursive;
! 27: #if (NGX_HAVE_GEOIP_V6)
! 28: unsigned country_v6:1;
! 29: unsigned org_v6:1;
! 30: unsigned city_v6:1;
! 31: #endif
! 32: } ngx_http_geoip_conf_t;
! 33:
! 34:
! 35: typedef struct {
! 36: ngx_str_t *name;
! 37: uintptr_t data;
! 38: } ngx_http_geoip_var_t;
! 39:
! 40:
! 41: typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
! 42: u_long addr);
! 43:
! 44:
! 45: ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
! 46: GeoIP_country_code_by_ipnum,
! 47: GeoIP_country_code3_by_ipnum,
! 48: GeoIP_country_name_by_ipnum,
! 49: };
! 50:
! 51:
! 52: #if (NGX_HAVE_GEOIP_V6)
! 53:
! 54: typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
! 55: geoipv6_t addr);
! 56:
! 57:
! 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,
! 62: };
! 63:
! 64: #endif
! 65:
! 66:
! 67: static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
! 68: ngx_http_variable_value_t *v, uintptr_t data);
! 69: static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
! 70: ngx_http_variable_value_t *v, uintptr_t data);
! 71: static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
! 72: ngx_http_variable_value_t *v, uintptr_t data);
! 73: static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
! 74: ngx_http_variable_value_t *v, uintptr_t data);
! 75: static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
! 76: ngx_http_variable_value_t *v, uintptr_t data);
! 77: static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
! 78: ngx_http_variable_value_t *v, uintptr_t data);
! 79: static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
! 80:
! 81: static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
! 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);
! 84: static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
! 85: void *conf);
! 86: static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
! 87: void *conf);
! 88: static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
! 89: void *conf);
! 90: static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
! 91: void *conf);
! 92: static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
! 93: ngx_cidr_t *cidr);
! 94: static void ngx_http_geoip_cleanup(void *data);
! 95:
! 96:
! 97: static ngx_command_t ngx_http_geoip_commands[] = {
! 98:
! 99: { ngx_string("geoip_country"),
! 100: NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
! 101: ngx_http_geoip_country,
! 102: NGX_HTTP_MAIN_CONF_OFFSET,
! 103: 0,
! 104: NULL },
! 105:
! 106: { ngx_string("geoip_org"),
! 107: NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
! 108: ngx_http_geoip_org,
! 109: NGX_HTTP_MAIN_CONF_OFFSET,
! 110: 0,
! 111: NULL },
! 112:
! 113: { ngx_string("geoip_city"),
! 114: NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
! 115: ngx_http_geoip_city,
! 116: NGX_HTTP_MAIN_CONF_OFFSET,
! 117: 0,
! 118: NULL },
! 119:
! 120: { ngx_string("geoip_proxy"),
! 121: NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
! 122: ngx_http_geoip_proxy,
! 123: NGX_HTTP_MAIN_CONF_OFFSET,
! 124: 0,
! 125: NULL },
! 126:
! 127: { ngx_string("geoip_proxy_recursive"),
! 128: NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
! 129: ngx_conf_set_flag_slot,
! 130: NGX_HTTP_MAIN_CONF_OFFSET,
! 131: offsetof(ngx_http_geoip_conf_t, proxy_recursive),
! 132: NULL },
! 133:
! 134: ngx_null_command
! 135: };
! 136:
! 137:
! 138: static ngx_http_module_t ngx_http_geoip_module_ctx = {
! 139: ngx_http_geoip_add_variables, /* preconfiguration */
! 140: NULL, /* postconfiguration */
! 141:
! 142: ngx_http_geoip_create_conf, /* create main configuration */
! 143: ngx_http_geoip_init_conf, /* init main configuration */
! 144:
! 145: NULL, /* create server configuration */
! 146: NULL, /* merge server configuration */
! 147:
! 148: NULL, /* create location configuration */
! 149: NULL /* merge location configuration */
! 150: };
! 151:
! 152:
! 153: ngx_module_t ngx_http_geoip_module = {
! 154: NGX_MODULE_V1,
! 155: &ngx_http_geoip_module_ctx, /* module context */
! 156: ngx_http_geoip_commands, /* module directives */
! 157: NGX_HTTP_MODULE, /* module type */
! 158: NULL, /* init master */
! 159: NULL, /* init module */
! 160: NULL, /* init process */
! 161: NULL, /* init thread */
! 162: NULL, /* exit thread */
! 163: NULL, /* exit process */
! 164: NULL, /* exit master */
! 165: NGX_MODULE_V1_PADDING
! 166: };
! 167:
! 168:
! 169: static ngx_http_variable_t ngx_http_geoip_vars[] = {
! 170:
! 171: { ngx_string("geoip_country_code"), NULL,
! 172: ngx_http_geoip_country_variable,
! 173: NGX_GEOIP_COUNTRY_CODE, 0, 0 },
! 174:
! 175: { ngx_string("geoip_country_code3"), NULL,
! 176: ngx_http_geoip_country_variable,
! 177: NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
! 178:
! 179: { ngx_string("geoip_country_name"), NULL,
! 180: ngx_http_geoip_country_variable,
! 181: NGX_GEOIP_COUNTRY_NAME, 0, 0 },
! 182:
! 183: { ngx_string("geoip_org"), NULL,
! 184: ngx_http_geoip_org_variable,
! 185: 0, 0, 0 },
! 186:
! 187: { ngx_string("geoip_city_continent_code"), NULL,
! 188: ngx_http_geoip_city_variable,
! 189: offsetof(GeoIPRecord, continent_code), 0, 0 },
! 190:
! 191: { ngx_string("geoip_city_country_code"), NULL,
! 192: ngx_http_geoip_city_variable,
! 193: offsetof(GeoIPRecord, country_code), 0, 0 },
! 194:
! 195: { ngx_string("geoip_city_country_code3"), NULL,
! 196: ngx_http_geoip_city_variable,
! 197: offsetof(GeoIPRecord, country_code3), 0, 0 },
! 198:
! 199: { ngx_string("geoip_city_country_name"), NULL,
! 200: ngx_http_geoip_city_variable,
! 201: offsetof(GeoIPRecord, country_name), 0, 0 },
! 202:
! 203: { ngx_string("geoip_region"), NULL,
! 204: ngx_http_geoip_city_variable,
! 205: offsetof(GeoIPRecord, region), 0, 0 },
! 206:
! 207: { ngx_string("geoip_region_name"), NULL,
! 208: ngx_http_geoip_region_name_variable,
! 209: 0, 0, 0 },
! 210:
! 211: { ngx_string("geoip_city"), NULL,
! 212: ngx_http_geoip_city_variable,
! 213: offsetof(GeoIPRecord, city), 0, 0 },
! 214:
! 215: { ngx_string("geoip_postal_code"), NULL,
! 216: ngx_http_geoip_city_variable,
! 217: offsetof(GeoIPRecord, postal_code), 0, 0 },
! 218:
! 219: { ngx_string("geoip_latitude"), NULL,
! 220: ngx_http_geoip_city_float_variable,
! 221: offsetof(GeoIPRecord, latitude), 0, 0 },
! 222:
! 223: { ngx_string("geoip_longitude"), NULL,
! 224: ngx_http_geoip_city_float_variable,
! 225: offsetof(GeoIPRecord, longitude), 0, 0 },
! 226:
! 227: { ngx_string("geoip_dma_code"), NULL,
! 228: ngx_http_geoip_city_int_variable,
! 229: offsetof(GeoIPRecord, dma_code), 0, 0 },
! 230:
! 231: { ngx_string("geoip_area_code"), NULL,
! 232: ngx_http_geoip_city_int_variable,
! 233: offsetof(GeoIPRecord, area_code), 0, 0 },
! 234:
! 235: { ngx_null_string, NULL, NULL, 0, 0, 0 }
! 236: };
! 237:
! 238:
! 239: static u_long
! 240: ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
! 241: {
! 242: ngx_addr_t addr;
! 243: ngx_array_t *xfwd;
! 244: struct sockaddr_in *sin;
! 245:
! 246: addr.sockaddr = r->connection->sockaddr;
! 247: addr.socklen = r->connection->socklen;
! 248: /* addr.name = r->connection->addr_text; */
! 249:
! 250: xfwd = &r->headers_in.x_forwarded_for;
! 251:
! 252: if (xfwd->nelts > 0 && gcf->proxies != NULL) {
! 253: (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
! 254: gcf->proxies, gcf->proxy_recursive);
! 255: }
! 256:
! 257: #if (NGX_HAVE_INET6)
! 258:
! 259: if (addr.sockaddr->sa_family == AF_INET6) {
! 260: u_char *p;
! 261: in_addr_t inaddr;
! 262: struct in6_addr *inaddr6;
! 263:
! 264: inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
! 265:
! 266: if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
! 267: p = inaddr6->s6_addr;
! 268:
! 269: inaddr = p[12] << 24;
! 270: inaddr += p[13] << 16;
! 271: inaddr += p[14] << 8;
! 272: inaddr += p[15];
! 273:
! 274: return inaddr;
! 275: }
! 276: }
! 277:
! 278: #endif
! 279:
! 280: if (addr.sockaddr->sa_family != AF_INET) {
! 281: return INADDR_NONE;
! 282: }
! 283:
! 284: sin = (struct sockaddr_in *) addr.sockaddr;
! 285: return ntohl(sin->sin_addr.s_addr);
! 286: }
! 287:
! 288:
! 289: #if (NGX_HAVE_GEOIP_V6)
! 290:
! 291: static geoipv6_t
! 292: ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
! 293: {
! 294: ngx_addr_t addr;
! 295: ngx_array_t *xfwd;
! 296: in_addr_t addr4;
! 297: struct in6_addr addr6;
! 298: struct sockaddr_in *sin;
! 299: struct sockaddr_in6 *sin6;
! 300:
! 301: addr.sockaddr = r->connection->sockaddr;
! 302: addr.socklen = r->connection->socklen;
! 303: /* addr.name = r->connection->addr_text; */
! 304:
! 305: xfwd = &r->headers_in.x_forwarded_for;
! 306:
! 307: if (xfwd->nelts > 0 && gcf->proxies != NULL) {
! 308: (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
! 309: gcf->proxies, gcf->proxy_recursive);
! 310: }
! 311:
! 312: switch (addr.sockaddr->sa_family) {
! 313:
! 314: case AF_INET:
! 315: /* Produce IPv4-mapped IPv6 address. */
! 316: sin = (struct sockaddr_in *) addr.sockaddr;
! 317: addr4 = ntohl(sin->sin_addr.s_addr);
! 318:
! 319: ngx_memzero(&addr6, sizeof(struct in6_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;
! 326: return addr6;
! 327:
! 328: case AF_INET6:
! 329: sin6 = (struct sockaddr_in6 *) addr.sockaddr;
! 330: return sin6->sin6_addr;
! 331:
! 332: default:
! 333: return in6addr_any;
! 334: }
! 335: }
! 336:
! 337: #endif
! 338:
! 339:
! 340: static ngx_int_t
! 341: ngx_http_geoip_country_variable(ngx_http_request_t *r,
! 342: ngx_http_variable_value_t *v, uintptr_t data)
! 343: {
! 344: ngx_http_geoip_variable_handler_pt handler =
! 345: ngx_http_geoip_country_functions[data];
! 346: #if (NGX_HAVE_GEOIP_V6)
! 347: ngx_http_geoip_variable_handler_v6_pt handler_v6 =
! 348: ngx_http_geoip_country_v6_functions[data];
! 349: #endif
! 350:
! 351: const char *val;
! 352: ngx_http_geoip_conf_t *gcf;
! 353:
! 354: gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
! 355:
! 356: if (gcf->country == NULL) {
! 357: goto not_found;
! 358: }
! 359:
! 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));
! 364: #else
! 365: val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
! 366: #endif
! 367:
! 368: if (val == NULL) {
! 369: goto not_found;
! 370: }
! 371:
! 372: v->len = ngx_strlen(val);
! 373: v->valid = 1;
! 374: v->no_cacheable = 0;
! 375: v->not_found = 0;
! 376: v->data = (u_char *) val;
! 377:
! 378: return NGX_OK;
! 379:
! 380: not_found:
! 381:
! 382: v->not_found = 1;
! 383:
! 384: return NGX_OK;
! 385: }
! 386:
! 387:
! 388: static ngx_int_t
! 389: ngx_http_geoip_org_variable(ngx_http_request_t *r,
! 390: ngx_http_variable_value_t *v, uintptr_t data)
! 391: {
! 392: size_t len;
! 393: char *val;
! 394: ngx_http_geoip_conf_t *gcf;
! 395:
! 396: gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
! 397:
! 398: if (gcf->org == NULL) {
! 399: goto not_found;
! 400: }
! 401:
! 402: #if (NGX_HAVE_GEOIP_V6)
! 403: val = gcf->org_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));
! 408: #else
! 409: val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
! 410: #endif
! 411:
! 412: if (val == NULL) {
! 413: goto not_found;
! 414: }
! 415:
! 416: len = ngx_strlen(val);
! 417: v->data = ngx_pnalloc(r->pool, len);
! 418: if (v->data == NULL) {
! 419: ngx_free(val);
! 420: return NGX_ERROR;
! 421: }
! 422:
! 423: ngx_memcpy(v->data, val, len);
! 424:
! 425: v->len = len;
! 426: v->valid = 1;
! 427: v->no_cacheable = 0;
! 428: v->not_found = 0;
! 429:
! 430: ngx_free(val);
! 431:
! 432: return NGX_OK;
! 433:
! 434: not_found:
! 435:
! 436: v->not_found = 1;
! 437:
! 438: return NGX_OK;
! 439: }
! 440:
! 441:
! 442: static ngx_int_t
! 443: ngx_http_geoip_city_variable(ngx_http_request_t *r,
! 444: ngx_http_variable_value_t *v, uintptr_t data)
! 445: {
! 446: char *val;
! 447: size_t len;
! 448: GeoIPRecord *gr;
! 449:
! 450: gr = ngx_http_geoip_get_city_record(r);
! 451: if (gr == NULL) {
! 452: goto not_found;
! 453: }
! 454:
! 455: val = *(char **) ((char *) gr + data);
! 456: if (val == NULL) {
! 457: goto no_value;
! 458: }
! 459:
! 460: len = ngx_strlen(val);
! 461: v->data = ngx_pnalloc(r->pool, len);
! 462: if (v->data == NULL) {
! 463: GeoIPRecord_delete(gr);
! 464: return NGX_ERROR;
! 465: }
! 466:
! 467: ngx_memcpy(v->data, val, len);
! 468:
! 469: v->len = len;
! 470: v->valid = 1;
! 471: v->no_cacheable = 0;
! 472: v->not_found = 0;
! 473:
! 474: GeoIPRecord_delete(gr);
! 475:
! 476: return NGX_OK;
! 477:
! 478: no_value:
! 479:
! 480: GeoIPRecord_delete(gr);
! 481:
! 482: not_found:
! 483:
! 484: v->not_found = 1;
! 485:
! 486: return NGX_OK;
! 487: }
! 488:
! 489:
! 490: static ngx_int_t
! 491: ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
! 492: ngx_http_variable_value_t *v, uintptr_t data)
! 493: {
! 494: size_t len;
! 495: const char *val;
! 496: GeoIPRecord *gr;
! 497:
! 498: gr = ngx_http_geoip_get_city_record(r);
! 499: if (gr == NULL) {
! 500: goto not_found;
! 501: }
! 502:
! 503: val = GeoIP_region_name_by_code(gr->country_code, gr->region);
! 504:
! 505: GeoIPRecord_delete(gr);
! 506:
! 507: if (val == NULL) {
! 508: goto not_found;
! 509: }
! 510:
! 511: len = ngx_strlen(val);
! 512: v->data = ngx_pnalloc(r->pool, len);
! 513: if (v->data == NULL) {
! 514: return NGX_ERROR;
! 515: }
! 516:
! 517: ngx_memcpy(v->data, val, len);
! 518:
! 519: v->len = len;
! 520: v->valid = 1;
! 521: v->no_cacheable = 0;
! 522: v->not_found = 0;
! 523:
! 524: return NGX_OK;
! 525:
! 526: not_found:
! 527:
! 528: v->not_found = 1;
! 529:
! 530: return NGX_OK;
! 531: }
! 532:
! 533:
! 534: static ngx_int_t
! 535: ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
! 536: ngx_http_variable_value_t *v, uintptr_t data)
! 537: {
! 538: float val;
! 539: GeoIPRecord *gr;
! 540:
! 541: gr = ngx_http_geoip_get_city_record(r);
! 542: if (gr == NULL) {
! 543: v->not_found = 1;
! 544: return NGX_OK;
! 545: }
! 546:
! 547: v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
! 548: if (v->data == NULL) {
! 549: GeoIPRecord_delete(gr);
! 550: return NGX_ERROR;
! 551: }
! 552:
! 553: val = *(float *) ((char *) gr + data);
! 554:
! 555: v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
! 556:
! 557: GeoIPRecord_delete(gr);
! 558:
! 559: return NGX_OK;
! 560: }
! 561:
! 562:
! 563: static ngx_int_t
! 564: ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
! 565: ngx_http_variable_value_t *v, uintptr_t data)
! 566: {
! 567: int val;
! 568: GeoIPRecord *gr;
! 569:
! 570: gr = ngx_http_geoip_get_city_record(r);
! 571: if (gr == NULL) {
! 572: v->not_found = 1;
! 573: return NGX_OK;
! 574: }
! 575:
! 576: v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
! 577: if (v->data == NULL) {
! 578: GeoIPRecord_delete(gr);
! 579: return NGX_ERROR;
! 580: }
! 581:
! 582: val = *(int *) ((char *) gr + data);
! 583:
! 584: v->len = ngx_sprintf(v->data, "%d", val) - v->data;
! 585:
! 586: GeoIPRecord_delete(gr);
! 587:
! 588: return NGX_OK;
! 589: }
! 590:
! 591:
! 592: static GeoIPRecord *
! 593: ngx_http_geoip_get_city_record(ngx_http_request_t *r)
! 594: {
! 595: ngx_http_geoip_conf_t *gcf;
! 596:
! 597: gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
! 598:
! 599: if (gcf->city) {
! 600: #if (NGX_HAVE_GEOIP_V6)
! 601: return gcf->city_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));
! 606: #else
! 607: return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
! 608: #endif
! 609: }
! 610:
! 611: return NULL;
! 612: }
! 613:
! 614:
! 615: static ngx_int_t
! 616: ngx_http_geoip_add_variables(ngx_conf_t *cf)
! 617: {
! 618: ngx_http_variable_t *var, *v;
! 619:
! 620: for (v = ngx_http_geoip_vars; v->name.len; v++) {
! 621: var = ngx_http_add_variable(cf, &v->name, v->flags);
! 622: if (var == NULL) {
! 623: return NGX_ERROR;
! 624: }
! 625:
! 626: var->get_handler = v->get_handler;
! 627: var->data = v->data;
! 628: }
! 629:
! 630: return NGX_OK;
! 631: }
! 632:
! 633:
! 634: static void *
! 635: ngx_http_geoip_create_conf(ngx_conf_t *cf)
! 636: {
! 637: ngx_pool_cleanup_t *cln;
! 638: ngx_http_geoip_conf_t *conf;
! 639:
! 640: conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t));
! 641: if (conf == NULL) {
! 642: return NULL;
! 643: }
! 644:
! 645: conf->proxy_recursive = NGX_CONF_UNSET;
! 646:
! 647: cln = ngx_pool_cleanup_add(cf->pool, 0);
! 648: if (cln == NULL) {
! 649: return NULL;
! 650: }
! 651:
! 652: cln->handler = ngx_http_geoip_cleanup;
! 653: cln->data = conf;
! 654:
! 655: return conf;
! 656: }
! 657:
! 658:
! 659: static char *
! 660: ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
! 661: {
! 662: ngx_http_geoip_conf_t *gcf = conf;
! 663:
! 664: ngx_conf_init_value(gcf->proxy_recursive, 0);
! 665:
! 666: return NGX_CONF_OK;
! 667: }
! 668:
! 669:
! 670: static char *
! 671: ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 672: {
! 673: ngx_http_geoip_conf_t *gcf = conf;
! 674:
! 675: ngx_str_t *value;
! 676:
! 677: if (gcf->country) {
! 678: return "is duplicate";
! 679: }
! 680:
! 681: value = cf->args->elts;
! 682:
! 683: gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
! 684:
! 685: if (gcf->country == NULL) {
! 686: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 687: "GeoIP_open(\"%V\") failed", &value[1]);
! 688:
! 689: return NGX_CONF_ERROR;
! 690: }
! 691:
! 692: if (cf->args->nelts == 3) {
! 693: if (ngx_strcmp(value[2].data, "utf8") == 0) {
! 694: GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8);
! 695:
! 696: } else {
! 697: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 698: "invalid parameter \"%V\"", &value[2]);
! 699: return NGX_CONF_ERROR;
! 700: }
! 701: }
! 702:
! 703: switch (gcf->country->databaseType) {
! 704:
! 705: case GEOIP_COUNTRY_EDITION:
! 706:
! 707: return NGX_CONF_OK;
! 708:
! 709: #if (NGX_HAVE_GEOIP_V6)
! 710: case GEOIP_COUNTRY_EDITION_V6:
! 711:
! 712: gcf->country_v6 = 1;
! 713: return NGX_CONF_OK;
! 714: #endif
! 715:
! 716: default:
! 717: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 718: "invalid GeoIP database \"%V\" type:%d",
! 719: &value[1], gcf->country->databaseType);
! 720: return NGX_CONF_ERROR;
! 721: }
! 722: }
! 723:
! 724:
! 725: static char *
! 726: ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 727: {
! 728: ngx_http_geoip_conf_t *gcf = conf;
! 729:
! 730: ngx_str_t *value;
! 731:
! 732: if (gcf->org) {
! 733: return "is duplicate";
! 734: }
! 735:
! 736: value = cf->args->elts;
! 737:
! 738: gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
! 739:
! 740: if (gcf->org == NULL) {
! 741: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 742: "GeoIP_open(\"%V\") failed", &value[1]);
! 743:
! 744: return NGX_CONF_ERROR;
! 745: }
! 746:
! 747: if (cf->args->nelts == 3) {
! 748: if (ngx_strcmp(value[2].data, "utf8") == 0) {
! 749: GeoIP_set_charset (gcf->org, GEOIP_CHARSET_UTF8);
! 750:
! 751: } else {
! 752: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 753: "invalid parameter \"%V\"", &value[2]);
! 754: return NGX_CONF_ERROR;
! 755: }
! 756: }
! 757:
! 758: switch (gcf->org->databaseType) {
! 759:
! 760: case GEOIP_ISP_EDITION:
! 761: case GEOIP_ORG_EDITION:
! 762: case GEOIP_DOMAIN_EDITION:
! 763: case GEOIP_ASNUM_EDITION:
! 764:
! 765: return NGX_CONF_OK;
! 766:
! 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:
! 772:
! 773: gcf->org_v6 = 1;
! 774: return NGX_CONF_OK;
! 775: #endif
! 776:
! 777: default:
! 778: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 779: "invalid GeoIP database \"%V\" type:%d",
! 780: &value[1], gcf->org->databaseType);
! 781: return NGX_CONF_ERROR;
! 782: }
! 783: }
! 784:
! 785:
! 786: static char *
! 787: ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 788: {
! 789: ngx_http_geoip_conf_t *gcf = conf;
! 790:
! 791: ngx_str_t *value;
! 792:
! 793: if (gcf->city) {
! 794: return "is duplicate";
! 795: }
! 796:
! 797: value = cf->args->elts;
! 798:
! 799: gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
! 800:
! 801: if (gcf->city == NULL) {
! 802: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 803: "GeoIP_open(\"%V\") failed", &value[1]);
! 804:
! 805: return NGX_CONF_ERROR;
! 806: }
! 807:
! 808: if (cf->args->nelts == 3) {
! 809: if (ngx_strcmp(value[2].data, "utf8") == 0) {
! 810: GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8);
! 811:
! 812: } else {
! 813: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 814: "invalid parameter \"%V\"", &value[2]);
! 815: return NGX_CONF_ERROR;
! 816: }
! 817: }
! 818:
! 819: switch (gcf->city->databaseType) {
! 820:
! 821: case GEOIP_CITY_EDITION_REV0:
! 822: case GEOIP_CITY_EDITION_REV1:
! 823:
! 824: return NGX_CONF_OK;
! 825:
! 826: #if (NGX_HAVE_GEOIP_V6)
! 827: case GEOIP_CITY_EDITION_REV0_V6:
! 828: case GEOIP_CITY_EDITION_REV1_V6:
! 829:
! 830: gcf->city_v6 = 1;
! 831: return NGX_CONF_OK;
! 832: #endif
! 833:
! 834: default:
! 835: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
! 836: "invalid GeoIP City database \"%V\" type:%d",
! 837: &value[1], gcf->city->databaseType);
! 838: return NGX_CONF_ERROR;
! 839: }
! 840: }
! 841:
! 842:
! 843: static char *
! 844: ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 845: {
! 846: ngx_http_geoip_conf_t *gcf = conf;
! 847:
! 848: ngx_str_t *value;
! 849: ngx_cidr_t cidr, *c;
! 850:
! 851: value = cf->args->elts;
! 852:
! 853: if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
! 854: return NGX_CONF_ERROR;
! 855: }
! 856:
! 857: if (gcf->proxies == NULL) {
! 858: gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
! 859: if (gcf->proxies == NULL) {
! 860: return NGX_CONF_ERROR;
! 861: }
! 862: }
! 863:
! 864: c = ngx_array_push(gcf->proxies);
! 865: if (c == NULL) {
! 866: return NGX_CONF_ERROR;
! 867: }
! 868:
! 869: *c = cidr;
! 870:
! 871: return NGX_CONF_OK;
! 872: }
! 873:
! 874: static ngx_int_t
! 875: ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
! 876: {
! 877: ngx_int_t rc;
! 878:
! 879: if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
! 880: cidr->family = AF_INET;
! 881: cidr->u.in.addr = 0xffffffff;
! 882: cidr->u.in.mask = 0xffffffff;
! 883:
! 884: return NGX_OK;
! 885: }
! 886:
! 887: rc = ngx_ptocidr(net, cidr);
! 888:
! 889: if (rc == NGX_ERROR) {
! 890: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
! 891: return NGX_ERROR;
! 892: }
! 893:
! 894: if (rc == NGX_DONE) {
! 895: ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
! 896: "low address bits of %V are meaningless", net);
! 897: }
! 898:
! 899: return NGX_OK;
! 900: }
! 901:
! 902:
! 903: static void
! 904: ngx_http_geoip_cleanup(void *data)
! 905: {
! 906: ngx_http_geoip_conf_t *gcf = data;
! 907:
! 908: if (gcf->country) {
! 909: GeoIP_delete(gcf->country);
! 910: }
! 911:
! 912: if (gcf->org) {
! 913: GeoIP_delete(gcf->org);
! 914: }
! 915:
! 916: if (gcf->city) {
! 917: GeoIP_delete(gcf->city);
! 918: }
! 919: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>