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>