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 }
920
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.