Annotation of embedaddon/nginx/src/http/modules/ngx_http_geoip_module.c, revision 1.1.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>