Mercurial > hg > nginx
annotate src/http/modules/ngx_http_geoip_module.c @ 3834:f1498c0488a6 stable-0.8
release-0.8.54 tag
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 14 Dec 2010 10:55:49 +0000 |
parents | 01691af60f94 |
children | 30d4d6187316 |
rev | line source |
---|---|
2985 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 #include <GeoIP.h> | |
12 #include <GeoIPCity.h> | |
13 | |
14 | |
15 typedef struct { | |
16 GeoIP *country; | |
17 GeoIP *city; | |
18 } ngx_http_geoip_conf_t; | |
19 | |
20 | |
21 typedef struct { | |
22 ngx_str_t *name; | |
23 uintptr_t data; | |
24 } ngx_http_geoip_var_t; | |
25 | |
26 | |
27 typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr); | |
28 | |
29 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r, | |
30 ngx_http_variable_value_t *v, uintptr_t data); | |
31 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r, | |
32 ngx_http_variable_value_t *v, uintptr_t data); | |
3737 | 33 static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r, |
34 ngx_http_variable_value_t *v, uintptr_t data); | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
35 static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
36 ngx_http_variable_value_t *v, uintptr_t data); |
3736
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
37 static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
38 ngx_http_variable_value_t *v, uintptr_t data); |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
39 static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r); |
2985 | 40 |
41 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf); | |
42 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf); | |
43 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, | |
44 void *conf); | |
45 static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, | |
46 void *conf); | |
47 static void ngx_http_geoip_cleanup(void *data); | |
48 | |
49 | |
50 static ngx_command_t ngx_http_geoip_commands[] = { | |
51 | |
52 { ngx_string("geoip_country"), | |
53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | |
54 ngx_http_geoip_country, | |
55 NGX_HTTP_MAIN_CONF_OFFSET, | |
56 0, | |
57 NULL }, | |
58 | |
59 { ngx_string("geoip_city"), | |
60 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | |
61 ngx_http_geoip_city, | |
62 NGX_HTTP_MAIN_CONF_OFFSET, | |
63 0, | |
64 NULL }, | |
65 | |
66 ngx_null_command | |
67 }; | |
68 | |
69 | |
70 static ngx_http_module_t ngx_http_geoip_module_ctx = { | |
71 ngx_http_geoip_add_variables, /* preconfiguration */ | |
72 NULL, /* postconfiguration */ | |
73 | |
74 ngx_http_geoip_create_conf, /* create main configuration */ | |
75 NULL, /* init main configuration */ | |
76 | |
77 NULL, /* create server configuration */ | |
78 NULL, /* merge server configuration */ | |
79 | |
80 NULL, /* create location configuration */ | |
81 NULL /* merge location configuration */ | |
82 }; | |
83 | |
84 | |
85 ngx_module_t ngx_http_geoip_module = { | |
86 NGX_MODULE_V1, | |
87 &ngx_http_geoip_module_ctx, /* module context */ | |
88 ngx_http_geoip_commands, /* module directives */ | |
89 NGX_HTTP_MODULE, /* module type */ | |
90 NULL, /* init master */ | |
91 NULL, /* init module */ | |
92 NULL, /* init process */ | |
93 NULL, /* init thread */ | |
94 NULL, /* exit thread */ | |
95 NULL, /* exit process */ | |
96 NULL, /* exit master */ | |
97 NGX_MODULE_V1_PADDING | |
98 }; | |
99 | |
100 | |
101 static ngx_http_variable_t ngx_http_geoip_vars[] = { | |
102 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
103 { ngx_string("geoip_country_code"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
104 ngx_http_geoip_country_variable, |
2985 | 105 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 }, |
106 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
107 { ngx_string("geoip_country_code3"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
108 ngx_http_geoip_country_variable, |
2985 | 109 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 }, |
110 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
111 { ngx_string("geoip_country_name"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
112 ngx_http_geoip_country_variable, |
2985 | 113 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 }, |
114 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
115 { ngx_string("geoip_city_continent_code"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
116 ngx_http_geoip_city_variable, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
117 offsetof(GeoIPRecord, continent_code), 0, 0 }, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
118 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
119 { ngx_string("geoip_city_country_code"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
120 ngx_http_geoip_city_variable, |
2985 | 121 offsetof(GeoIPRecord, country_code), 0, 0 }, |
122 | |
123 { ngx_string("geoip_city_country_code3"), NULL, | |
124 ngx_http_geoip_city_variable, | |
125 offsetof(GeoIPRecord, country_code3), 0, 0 }, | |
126 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
127 { ngx_string("geoip_city_country_name"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
128 ngx_http_geoip_city_variable, |
2985 | 129 offsetof(GeoIPRecord, country_name), 0, 0 }, |
130 | |
131 { ngx_string("geoip_region"), NULL, | |
132 ngx_http_geoip_city_variable, | |
133 offsetof(GeoIPRecord, region), 0, 0 }, | |
134 | |
3737 | 135 { ngx_string("geoip_region_name"), NULL, |
136 ngx_http_geoip_region_name_variable, | |
137 0, 0, 0 }, | |
138 | |
2985 | 139 { ngx_string("geoip_city"), NULL, |
140 ngx_http_geoip_city_variable, | |
141 offsetof(GeoIPRecord, city), 0, 0 }, | |
142 | |
143 { ngx_string("geoip_postal_code"), NULL, | |
144 ngx_http_geoip_city_variable, | |
145 offsetof(GeoIPRecord, postal_code), 0, 0 }, | |
146 | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
147 { ngx_string("geoip_latitude"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
148 ngx_http_geoip_city_float_variable, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
149 offsetof(GeoIPRecord, latitude), 0, 0 }, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
150 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
151 { ngx_string("geoip_longitude"), NULL, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
152 ngx_http_geoip_city_float_variable, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
153 offsetof(GeoIPRecord, longitude), 0, 0 }, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
154 |
3736
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
155 { ngx_string("geoip_dma_code"), NULL, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
156 ngx_http_geoip_city_int_variable, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
157 offsetof(GeoIPRecord, dma_code), 0, 0 }, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
158 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
159 { ngx_string("geoip_area_code"), NULL, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
160 ngx_http_geoip_city_int_variable, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
161 offsetof(GeoIPRecord, area_code), 0, 0 }, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
162 |
2985 | 163 { ngx_null_string, NULL, NULL, 0, 0, 0 } |
164 }; | |
165 | |
166 | |
167 static ngx_int_t | |
168 ngx_http_geoip_country_variable(ngx_http_request_t *r, | |
169 ngx_http_variable_value_t *v, uintptr_t data) | |
170 { | |
171 ngx_http_geoip_variable_handler_pt handler = | |
172 (ngx_http_geoip_variable_handler_pt) data; | |
173 | |
174 u_long addr; | |
175 const char *val; | |
176 struct sockaddr_in *sin; | |
177 ngx_http_geoip_conf_t *gcf; | |
178 | |
179 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module); | |
180 | |
181 if (gcf->country == NULL) { | |
182 goto not_found; | |
183 } | |
184 | |
185 if (r->connection->sockaddr->sa_family != AF_INET) { | |
186 goto not_found; | |
187 } | |
188 | |
189 sin = (struct sockaddr_in *) r->connection->sockaddr; | |
190 addr = ntohl(sin->sin_addr.s_addr); | |
191 | |
192 val = handler(gcf->country, addr); | |
193 | |
194 if (val == NULL) { | |
195 goto not_found; | |
196 } | |
197 | |
198 v->len = ngx_strlen(val); | |
199 v->valid = 1; | |
200 v->no_cacheable = 0; | |
201 v->not_found = 0; | |
202 v->data = (u_char *) val; | |
203 | |
204 return NGX_OK; | |
205 | |
206 not_found: | |
207 | |
208 v->not_found = 1; | |
209 | |
210 return NGX_OK; | |
211 } | |
212 | |
213 | |
214 static ngx_int_t | |
215 ngx_http_geoip_city_variable(ngx_http_request_t *r, | |
216 ngx_http_variable_value_t *v, uintptr_t data) | |
217 { | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
218 char *val; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
219 size_t len; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
220 GeoIPRecord *gr; |
2985 | 221 |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
222 gr = ngx_http_geoip_get_city_record(r); |
2985 | 223 if (gr == NULL) { |
224 goto not_found; | |
225 } | |
226 | |
227 val = *(char **) ((char *) gr + data); | |
228 if (val == NULL) { | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
229 goto no_value; |
2985 | 230 } |
231 | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
232 len = ngx_strlen(val); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
233 v->data = ngx_pnalloc(r->pool, len); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
234 if (v->data == NULL) { |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
235 GeoIPRecord_delete(gr); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
236 return NGX_ERROR; |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
237 } |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
238 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
239 ngx_memcpy(v->data, val, len); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
240 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
241 v->len = len; |
2985 | 242 v->valid = 1; |
243 v->no_cacheable = 0; | |
244 v->not_found = 0; | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
245 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
246 GeoIPRecord_delete(gr); |
2985 | 247 |
248 return NGX_OK; | |
249 | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
250 no_value: |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
251 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
252 GeoIPRecord_delete(gr); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
253 |
2985 | 254 not_found: |
255 | |
256 v->not_found = 1; | |
257 | |
258 return NGX_OK; | |
259 } | |
260 | |
261 | |
262 static ngx_int_t | |
3737 | 263 ngx_http_geoip_region_name_variable(ngx_http_request_t *r, |
264 ngx_http_variable_value_t *v, uintptr_t data) | |
265 { | |
266 size_t len; | |
267 const char *val; | |
268 GeoIPRecord *gr; | |
269 | |
270 gr = ngx_http_geoip_get_city_record(r); | |
271 if (gr == NULL) { | |
272 goto not_found; | |
273 } | |
274 | |
275 val = GeoIP_region_name_by_code(gr->country_code, gr->region); | |
3742
01691af60f94
we can free GeoIPRecord just after GeoIP_region_name_by_code(),
Igor Sysoev <igor@sysoev.ru>
parents:
3741
diff
changeset
|
276 |
01691af60f94
we can free GeoIPRecord just after GeoIP_region_name_by_code(),
Igor Sysoev <igor@sysoev.ru>
parents:
3741
diff
changeset
|
277 GeoIPRecord_delete(gr); |
01691af60f94
we can free GeoIPRecord just after GeoIP_region_name_by_code(),
Igor Sysoev <igor@sysoev.ru>
parents:
3741
diff
changeset
|
278 |
3741
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
279 if (val == NULL) { |
3742
01691af60f94
we can free GeoIPRecord just after GeoIP_region_name_by_code(),
Igor Sysoev <igor@sysoev.ru>
parents:
3741
diff
changeset
|
280 goto not_found; |
3741
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
281 } |
3737 | 282 |
283 len = ngx_strlen(val); | |
284 v->data = ngx_pnalloc(r->pool, len); | |
285 if (v->data == NULL) { | |
286 return NGX_ERROR; | |
287 } | |
288 | |
289 ngx_memcpy(v->data, val, len); | |
290 | |
291 v->len = len; | |
292 v->valid = 1; | |
293 v->no_cacheable = 0; | |
294 v->not_found = 0; | |
295 | |
296 return NGX_OK; | |
297 | |
298 not_found: | |
299 | |
300 v->not_found = 1; | |
301 | |
302 return NGX_OK; | |
303 } | |
304 | |
305 | |
306 static ngx_int_t | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
307 ngx_http_geoip_city_float_variable(ngx_http_request_t *r, |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
308 ngx_http_variable_value_t *v, uintptr_t data) |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
309 { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
310 float val; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
311 GeoIPRecord *gr; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
312 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
313 gr = ngx_http_geoip_get_city_record(r); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
314 if (gr == NULL) { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
315 v->not_found = 1; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
316 return NGX_OK; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
317 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
318 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
319 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
320 if (v->data == NULL) { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
321 GeoIPRecord_delete(gr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
322 return NGX_ERROR; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
323 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
324 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
325 val = *(float *) ((char *) gr + data); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
326 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
327 v->len = ngx_sprintf(v->data, "%.4f", val) - v->data; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
328 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
329 GeoIPRecord_delete(gr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
330 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
331 return NGX_OK; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
332 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
333 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
334 |
3736
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
335 static ngx_int_t |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
336 ngx_http_geoip_city_int_variable(ngx_http_request_t *r, |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
337 ngx_http_variable_value_t *v, uintptr_t data) |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
338 { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
339 int val; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
340 GeoIPRecord *gr; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
341 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
342 gr = ngx_http_geoip_get_city_record(r); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
343 if (gr == NULL) { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
344 v->not_found = 1; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
345 return NGX_OK; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
346 } |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
347 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
348 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
349 if (v->data == NULL) { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
350 GeoIPRecord_delete(gr); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
351 return NGX_ERROR; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
352 } |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
353 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
354 val = *(int *) ((char *) gr + data); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
355 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
356 v->len = ngx_sprintf(v->data, "%d", val) - v->data; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
357 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
358 GeoIPRecord_delete(gr); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
359 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
360 return NGX_OK; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
361 } |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
362 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
363 |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
364 static GeoIPRecord * |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
365 ngx_http_geoip_get_city_record(ngx_http_request_t *r) |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
366 { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
367 u_long addr; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
368 struct sockaddr_in *sin; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
369 ngx_http_geoip_conf_t *gcf; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
370 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
371 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
372 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
373 if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
374 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
375 sin = (struct sockaddr_in *) r->connection->sockaddr; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
376 addr = ntohl(sin->sin_addr.s_addr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
377 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
378 return GeoIP_record_by_ipnum(gcf->city, addr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
379 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
380 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
381 return NULL; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
382 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
383 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
384 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
385 static ngx_int_t |
2985 | 386 ngx_http_geoip_add_variables(ngx_conf_t *cf) |
387 { | |
388 ngx_http_variable_t *var, *v; | |
389 | |
390 for (v = ngx_http_geoip_vars; v->name.len; v++) { | |
391 var = ngx_http_add_variable(cf, &v->name, v->flags); | |
392 if (var == NULL) { | |
393 return NGX_ERROR; | |
394 } | |
395 | |
396 var->get_handler = v->get_handler; | |
397 var->data = v->data; | |
398 } | |
399 | |
400 return NGX_OK; | |
401 } | |
402 | |
403 | |
404 static void * | |
405 ngx_http_geoip_create_conf(ngx_conf_t *cf) | |
406 { | |
407 ngx_pool_cleanup_t *cln; | |
408 ngx_http_geoip_conf_t *conf; | |
409 | |
410 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t)); | |
411 if (conf == NULL) { | |
412 return NULL; | |
413 } | |
414 | |
415 cln = ngx_pool_cleanup_add(cf->pool, 0); | |
416 if (cln == NULL) { | |
417 return NULL; | |
418 } | |
419 | |
420 cln->handler = ngx_http_geoip_cleanup; | |
421 cln->data = conf; | |
422 | |
423 return conf; | |
424 } | |
425 | |
426 | |
427 static char * | |
428 ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
429 { | |
430 ngx_http_geoip_conf_t *gcf = conf; | |
431 | |
432 ngx_str_t *value; | |
433 | |
434 if (gcf->country) { | |
435 return "is duplicate"; | |
436 } | |
437 | |
438 value = cf->args->elts; | |
439 | |
440 gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); | |
441 | |
442 if (gcf->country == NULL) { | |
443 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
444 "GeoIO_open(\"%V\") failed", &value[1]); | |
445 | |
446 return NGX_CONF_ERROR; | |
447 } | |
448 | |
449 switch (gcf->country->databaseType) { | |
450 | |
451 case GEOIP_COUNTRY_EDITION: | |
452 case GEOIP_PROXY_EDITION: | |
453 case GEOIP_NETSPEED_EDITION: | |
454 | |
455 return NGX_CONF_OK; | |
456 | |
457 default: | |
458 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
459 "invalid GeoIP database \"%V\" type:%d", | |
460 &value[1], gcf->country->databaseType); | |
461 return NGX_CONF_ERROR; | |
462 } | |
463 } | |
464 | |
465 | |
466 static char * | |
467 ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
468 { | |
469 ngx_http_geoip_conf_t *gcf = conf; | |
470 | |
471 ngx_str_t *value; | |
472 | |
473 if (gcf->city) { | |
474 return "is duplicate"; | |
475 } | |
476 | |
477 value = cf->args->elts; | |
478 | |
479 gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); | |
480 | |
481 if (gcf->city == NULL) { | |
482 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
483 "GeoIO_open(\"%V\") failed", &value[1]); | |
484 | |
485 return NGX_CONF_ERROR; | |
486 } | |
487 | |
488 switch (gcf->city->databaseType) { | |
489 | |
490 case GEOIP_CITY_EDITION_REV0: | |
491 case GEOIP_CITY_EDITION_REV1: | |
492 | |
493 return NGX_CONF_OK; | |
494 | |
495 default: | |
496 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
497 "invalid GeoIP City database \"%V\" type:%d", | |
498 &value[1], gcf->city->databaseType); | |
499 return NGX_CONF_ERROR; | |
500 } | |
501 } | |
502 | |
503 | |
504 static void | |
505 ngx_http_geoip_cleanup(void *data) | |
506 { | |
507 ngx_http_geoip_conf_t *gcf = data; | |
508 | |
509 if (gcf->country) { | |
510 GeoIP_delete(gcf->country); | |
511 } | |
512 | |
513 if (gcf->city) { | |
514 GeoIP_delete(gcf->city); | |
515 } | |
516 } |