Mercurial > hg > nginx
annotate src/http/modules/ngx_http_geoip_module.c @ 3741:0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 03 Aug 2010 18:27:56 +0000 |
parents | 18ae5f09a53d |
children | 01691af60f94 |
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 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
235 if (v->data == NULL) { |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
236 GeoIPRecord_delete(gr); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
237 return NGX_ERROR; |
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 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
240 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
|
241 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
242 v->len = len; |
2985 | 243 v->valid = 1; |
244 v->no_cacheable = 0; | |
245 v->not_found = 0; | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
246 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
247 GeoIPRecord_delete(gr); |
2985 | 248 |
249 return NGX_OK; | |
250 | |
3031
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
251 no_value: |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
252 |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
253 GeoIPRecord_delete(gr); |
98a8336c5b7c
fix memory leak if GeoIP City database was used
Igor Sysoev <igor@sysoev.ru>
parents:
2985
diff
changeset
|
254 |
2985 | 255 not_found: |
256 | |
257 v->not_found = 1; | |
258 | |
259 return NGX_OK; | |
260 } | |
261 | |
262 | |
263 static ngx_int_t | |
3737 | 264 ngx_http_geoip_region_name_variable(ngx_http_request_t *r, |
265 ngx_http_variable_value_t *v, uintptr_t data) | |
266 { | |
267 size_t len; | |
268 const char *val; | |
269 GeoIPRecord *gr; | |
270 | |
271 gr = ngx_http_geoip_get_city_record(r); | |
272 if (gr == NULL) { | |
273 goto not_found; | |
274 } | |
275 | |
276 val = GeoIP_region_name_by_code(gr->country_code, gr->region); | |
3741
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
277 if (val == NULL) { |
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
278 goto no_value; |
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
279 } |
3737 | 280 |
281 len = ngx_strlen(val); | |
282 v->data = ngx_pnalloc(r->pool, len); | |
283 | |
284 if (v->data == NULL) { | |
285 GeoIPRecord_delete(gr); | |
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 GeoIPRecord_delete(gr); | |
297 | |
298 return NGX_OK; | |
299 | |
3741
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
300 no_value: |
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
301 |
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
302 GeoIPRecord_delete(gr); |
0f9b2d285bfc
fix segfault, the bug has been introduced in r3738
Igor Sysoev <igor@sysoev.ru>
parents:
3737
diff
changeset
|
303 |
3737 | 304 not_found: |
305 | |
306 v->not_found = 1; | |
307 | |
308 return NGX_OK; | |
309 } | |
310 | |
311 | |
312 static ngx_int_t | |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
313 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
|
314 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
|
315 { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
316 float val; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
317 GeoIPRecord *gr; |
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 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
|
320 if (gr == NULL) { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
321 v->not_found = 1; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
322 return NGX_OK; |
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 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
|
326 if (v->data == NULL) { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
327 GeoIPRecord_delete(gr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
328 return NGX_ERROR; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
329 } |
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 val = *(float *) ((char *) gr + data); |
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 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
|
334 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
335 GeoIPRecord_delete(gr); |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
336 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
337 return NGX_OK; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
338 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
339 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
340 |
3736
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
341 static ngx_int_t |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
342 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
|
343 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
|
344 { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
345 int val; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
346 GeoIPRecord *gr; |
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 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
|
349 if (gr == NULL) { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
350 v->not_found = 1; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
351 return NGX_OK; |
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 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
|
355 if (v->data == NULL) { |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
356 GeoIPRecord_delete(gr); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
357 return NGX_ERROR; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
358 } |
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 val = *(int *) ((char *) gr + data); |
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 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
|
363 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
364 GeoIPRecord_delete(gr); |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
365 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
366 return NGX_OK; |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
367 } |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
368 |
257785918797
$geoip_dma_code and $geoip_area_code
Igor Sysoev <igor@sysoev.ru>
parents:
3398
diff
changeset
|
369 |
3398
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
370 static GeoIPRecord * |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
371 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
|
372 { |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
373 u_long addr; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
374 struct sockaddr_in *sin; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
375 ngx_http_geoip_conf_t *gcf; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
376 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
377 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
|
378 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
379 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
|
380 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
381 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
|
382 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
|
383 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
384 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
|
385 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
386 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
387 return NULL; |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
388 } |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
389 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
390 |
236634d2b603
$geoip_city_continent_code, $geoip_latitude, $geoip_longitude
Igor Sysoev <igor@sysoev.ru>
parents:
3031
diff
changeset
|
391 static ngx_int_t |
2985 | 392 ngx_http_geoip_add_variables(ngx_conf_t *cf) |
393 { | |
394 ngx_http_variable_t *var, *v; | |
395 | |
396 for (v = ngx_http_geoip_vars; v->name.len; v++) { | |
397 var = ngx_http_add_variable(cf, &v->name, v->flags); | |
398 if (var == NULL) { | |
399 return NGX_ERROR; | |
400 } | |
401 | |
402 var->get_handler = v->get_handler; | |
403 var->data = v->data; | |
404 } | |
405 | |
406 return NGX_OK; | |
407 } | |
408 | |
409 | |
410 static void * | |
411 ngx_http_geoip_create_conf(ngx_conf_t *cf) | |
412 { | |
413 ngx_pool_cleanup_t *cln; | |
414 ngx_http_geoip_conf_t *conf; | |
415 | |
416 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t)); | |
417 if (conf == NULL) { | |
418 return NULL; | |
419 } | |
420 | |
421 cln = ngx_pool_cleanup_add(cf->pool, 0); | |
422 if (cln == NULL) { | |
423 return NULL; | |
424 } | |
425 | |
426 cln->handler = ngx_http_geoip_cleanup; | |
427 cln->data = conf; | |
428 | |
429 return conf; | |
430 } | |
431 | |
432 | |
433 static char * | |
434 ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
435 { | |
436 ngx_http_geoip_conf_t *gcf = conf; | |
437 | |
438 ngx_str_t *value; | |
439 | |
440 if (gcf->country) { | |
441 return "is duplicate"; | |
442 } | |
443 | |
444 value = cf->args->elts; | |
445 | |
446 gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); | |
447 | |
448 if (gcf->country == NULL) { | |
449 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
450 "GeoIO_open(\"%V\") failed", &value[1]); | |
451 | |
452 return NGX_CONF_ERROR; | |
453 } | |
454 | |
455 switch (gcf->country->databaseType) { | |
456 | |
457 case GEOIP_COUNTRY_EDITION: | |
458 case GEOIP_PROXY_EDITION: | |
459 case GEOIP_NETSPEED_EDITION: | |
460 | |
461 return NGX_CONF_OK; | |
462 | |
463 default: | |
464 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
465 "invalid GeoIP database \"%V\" type:%d", | |
466 &value[1], gcf->country->databaseType); | |
467 return NGX_CONF_ERROR; | |
468 } | |
469 } | |
470 | |
471 | |
472 static char * | |
473 ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
474 { | |
475 ngx_http_geoip_conf_t *gcf = conf; | |
476 | |
477 ngx_str_t *value; | |
478 | |
479 if (gcf->city) { | |
480 return "is duplicate"; | |
481 } | |
482 | |
483 value = cf->args->elts; | |
484 | |
485 gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE); | |
486 | |
487 if (gcf->city == NULL) { | |
488 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
489 "GeoIO_open(\"%V\") failed", &value[1]); | |
490 | |
491 return NGX_CONF_ERROR; | |
492 } | |
493 | |
494 switch (gcf->city->databaseType) { | |
495 | |
496 case GEOIP_CITY_EDITION_REV0: | |
497 case GEOIP_CITY_EDITION_REV1: | |
498 | |
499 return NGX_CONF_OK; | |
500 | |
501 default: | |
502 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
503 "invalid GeoIP City database \"%V\" type:%d", | |
504 &value[1], gcf->city->databaseType); | |
505 return NGX_CONF_ERROR; | |
506 } | |
507 } | |
508 | |
509 | |
510 static void | |
511 ngx_http_geoip_cleanup(void *data) | |
512 { | |
513 ngx_http_geoip_conf_t *gcf = data; | |
514 | |
515 if (gcf->country) { | |
516 GeoIP_delete(gcf->country); | |
517 } | |
518 | |
519 if (gcf->city) { | |
520 GeoIP_delete(gcf->city); | |
521 } | |
522 } |