comparison src/http/modules/ngx_http_geo_module.c @ 510:24b676623d4f NGINX_0_8_7

nginx 0.8.7 *) Change: minimum supported OpenSSL version is 0.9.7. *) Change: the "ask" parameter of the "ssl_verify_client" directive was changed to the "optional" parameter and now it checks a client certificate if it was offered. Thanks to Brice Figureau. *) Feature: the $ssl_client_verify variable. Thanks to Brice Figureau. *) Feature: the "ssl_crl" directive. Thanks to Brice Figureau. *) Feature: the "proxy" parameter of the "geo" directive. *) Feature: the "image_filter" directive supports variables for setting size. *) Bugfix: the $ssl_client_cert variable usage corrupted memory; the bug had appeared in 0.7.7. Thanks to Sergey Zhuravlev. *) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate", "X-Accel-Buffering", and "X-Accel-Charset" lines from backend response header. Thanks to Maxim Dounin. *) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend response header lines; the bug had appeared in 0.7.44. Thanks to Maxim Dounin. *) Bugfix: the "[alert] zero size buf" error if subrequest returns an empty response; the bug had appeared in 0.8.5.
author Igor Sysoev <http://sysoev.ru>
date Mon, 27 Jul 2009 00:00:00 +0400
parents a8424ffa495c
children 0161f3197817
comparison
equal deleted inserted replaced
509:41f4e459ace8 510:24b676623d4f
33 ngx_str_t *net; 33 ngx_str_t *net;
34 ngx_http_geo_high_ranges_t *high; 34 ngx_http_geo_high_ranges_t *high;
35 ngx_radix_tree_t *tree; 35 ngx_radix_tree_t *tree;
36 ngx_rbtree_t rbtree; 36 ngx_rbtree_t rbtree;
37 ngx_rbtree_node_t sentinel; 37 ngx_rbtree_node_t sentinel;
38 ngx_array_t *proxies;
38 ngx_pool_t *pool; 39 ngx_pool_t *pool;
39 ngx_pool_t *temp_pool; 40 ngx_pool_t *temp_pool;
40 } ngx_http_geo_conf_ctx_t; 41 } ngx_http_geo_conf_ctx_t;
41 42
42 43
44 union { 45 union {
45 ngx_radix_tree_t *tree; 46 ngx_radix_tree_t *tree;
46 ngx_http_geo_high_ranges_t *high; 47 ngx_http_geo_high_ranges_t *high;
47 } u; 48 } u;
48 49
50 ngx_array_t *proxies;
51
49 ngx_int_t index; 52 ngx_int_t index;
50 } ngx_http_geo_ctx_t; 53 } ngx_http_geo_ctx_t;
51 54
52 55
53 static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r, 56 static in_addr_t ngx_http_geo_addr(ngx_http_request_t *r,
57 ngx_http_geo_ctx_t *ctx);
58 static in_addr_t ngx_http_geo_real_addr(ngx_http_request_t *r,
54 ngx_http_geo_ctx_t *ctx); 59 ngx_http_geo_ctx_t *ctx);
55 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 60 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
56 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); 61 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
57 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, 62 static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
58 ngx_str_t *value); 63 ngx_str_t *value);
62 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end); 67 ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
63 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx, 68 static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
64 ngx_str_t *value); 69 ngx_str_t *value);
65 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf, 70 static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
66 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value); 71 ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value);
72 static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
73 ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr);
74 static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
75 ngx_cidr_t *cidr);
67 76
68 77
69 static ngx_command_t ngx_http_geo_commands[] = { 78 static ngx_command_t ngx_http_geo_commands[] = {
70 79
71 { ngx_string("geo"), 80 { ngx_string("geo"),
166 175
167 176
168 static in_addr_t 177 static in_addr_t
169 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx) 178 ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
170 { 179 {
180 u_char *p, *ip;
181 size_t len;
182 in_addr_t addr;
183 ngx_uint_t i, n;
184 ngx_in_cidr_t *proxies;
185 ngx_table_elt_t *xfwd;
186
187 addr = ngx_http_geo_real_addr(r, ctx);
188
189 xfwd = r->headers_in.x_forwarded_for;
190
191 if (xfwd == NULL || ctx->proxies == NULL) {
192 return addr;
193 }
194
195 proxies = ctx->proxies->elts;
196 n = ctx->proxies->nelts;
197
198 for (i = 0; i < n; i++) {
199 if ((addr & proxies[i].mask) == proxies[i].addr) {
200
201 len = xfwd->value.len;
202 ip = xfwd->value.data;
203
204 for (p = ip + len - 1; p > ip; p--) {
205 if (*p == ' ' || *p == ',') {
206 p++;
207 len -= p - ip;
208 ip = p;
209 break;
210 }
211 }
212
213 return ntohl(ngx_inet_addr(ip, len));
214 }
215 }
216
217 return addr;
218 }
219
220
221 static in_addr_t
222 ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
223 {
171 struct sockaddr_in *sin; 224 struct sockaddr_in *sin;
172 ngx_http_variable_value_t *v; 225 ngx_http_variable_value_t *v;
173 226
174 if (ctx->index == -1) { 227 if (ctx->index == -1) {
175 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 228 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
257 ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, 310 ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel,
258 ngx_http_variable_value_rbtree_insert); 311 ngx_http_variable_value_rbtree_insert);
259 312
260 ctx.high = NULL; 313 ctx.high = NULL;
261 ctx.tree = NULL; 314 ctx.tree = NULL;
315 ctx.proxies = NULL;
262 ctx.pool = cf->pool; 316 ctx.pool = cf->pool;
263 317
264 save = *cf; 318 save = *cf;
265 cf->pool = pool; 319 cf->pool = pool;
266 cf->ctx = &ctx; 320 cf->ctx = &ctx;
269 323
270 rv = ngx_conf_parse(cf, NULL); 324 rv = ngx_conf_parse(cf, NULL);
271 325
272 *cf = save; 326 *cf = save;
273 327
328 geo->proxies = ctx.proxies;
329
274 if (ctx.high) { 330 if (ctx.high) {
275 331
276 for (i = 0; i < 0x10000; i++) { 332 for (i = 0; i < 0x10000; i++) {
277 a = (ngx_array_t *) ctx.high->low[i].ranges; 333 a = (ngx_array_t *) ctx.high->low[i].ranges;
278 334
339 static char * 395 static char *
340 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) 396 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
341 { 397 {
342 char *rv; 398 char *rv;
343 ngx_str_t *value, file; 399 ngx_str_t *value, file;
400 ngx_cidr_t cidr;
344 ngx_http_geo_conf_ctx_t *ctx; 401 ngx_http_geo_conf_ctx_t *ctx;
345 402
346 ctx = cf->ctx; 403 ctx = cf->ctx;
347 404
348 value = cf->args->elts; 405 value = cf->args->elts;
390 } 447 }
391 448
392 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data); 449 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
393 450
394 rv = ngx_conf_parse(cf, &file); 451 rv = ngx_conf_parse(cf, &file);
452
453 goto done;
454
455 } else if (ngx_strcmp(value[0].data, "proxy") == 0) {
456
457 if (ngx_http_geo_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
458 goto failed;
459 }
460
461 rv = ngx_http_geo_add_proxy(cf, ctx, &cidr);
395 462
396 goto done; 463 goto done;
397 } 464 }
398 465
399 if (ctx->high) { 466 if (ctx->high) {
801 } else { 868 } else {
802 net = &value[0]; 869 net = &value[0];
803 del = 0; 870 del = 0;
804 } 871 }
805 872
806 if (ngx_strcmp(net->data, "255.255.255.255") == 0) { 873 if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
807 cidr.u.in.addr = 0xffffffff; 874 return NGX_CONF_ERROR;
808 cidr.u.in.mask = 0xffffffff;
809
810 } else {
811 rc = ngx_ptocidr(net, &cidr);
812
813 if (rc == NGX_ERROR) {
814 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
815 "invalid network \"%V\"", net);
816 return NGX_CONF_ERROR;
817 }
818
819 if (cidr.family != AF_INET) {
820 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
821 "\"geo\" supports IPv4 only");
822 return NGX_CONF_ERROR;
823 }
824
825 if (rc == NGX_DONE) {
826 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
827 "low address bits of %V are meaningless",
828 net);
829 }
830
831 cidr.u.in.addr = ntohl(cidr.u.in.addr);
832 cidr.u.in.mask = ntohl(cidr.u.in.mask);
833 } 875 }
834 876
835 if (del) { 877 if (del) {
836 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, 878 if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
837 cidr.u.in.mask) 879 cidr.u.in.mask)
925 967
926 ngx_rbtree_insert(&ctx->rbtree, &vvn->node); 968 ngx_rbtree_insert(&ctx->rbtree, &vvn->node);
927 969
928 return val; 970 return val;
929 } 971 }
972
973
974 static char *
975 ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
976 ngx_cidr_t *cidr)
977 {
978 ngx_in_cidr_t *c;
979
980 if (ctx->proxies == NULL) {
981 ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_in_cidr_t));
982 if (ctx->proxies == NULL) {
983 return NGX_CONF_ERROR;
984 }
985 }
986
987 c = ngx_array_push(ctx->proxies);
988 if (c == NULL) {
989 return NGX_CONF_ERROR;
990 }
991
992 c->addr = cidr->u.in.addr;
993 c->mask = cidr->u.in.mask;
994
995 return NGX_CONF_OK;
996 }
997
998
999 static ngx_int_t
1000 ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
1001 {
1002 ngx_int_t rc;
1003
1004 if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
1005 cidr->u.in.addr = 0xffffffff;
1006 cidr->u.in.mask = 0xffffffff;
1007
1008 return NGX_OK;
1009 }
1010
1011 rc = ngx_ptocidr(net, cidr);
1012
1013 if (rc == NGX_ERROR) {
1014 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
1015 return NGX_ERROR;
1016 }
1017
1018 if (cidr->family != AF_INET) {
1019 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"geo\" supports IPv4 only");
1020 return NGX_ERROR;
1021 }
1022
1023 if (rc == NGX_DONE) {
1024 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1025 "low address bits of %V are meaningless", net);
1026 }
1027
1028 cidr->u.in.addr = ntohl(cidr->u.in.addr);
1029 cidr->u.in.mask = ntohl(cidr->u.in.mask);
1030
1031 return NGX_OK;
1032 }