comparison src/http/modules/ngx_http_realip_module.c @ 540:c04fa65fe604 NGINX_0_8_22

nginx 0.8.22 *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" directives. *) Feature: the "access" and the "deny" directives support IPv6. *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in request headers. *) Feature: the "unix:" parameter of the "set_real_ip_from" directive. *) Bugfix: nginx did not delete unix domain socket after configuration testing. *) Bugfix: nginx deleted unix domain socket while online upgrade. *) Bugfix: the "!-x" operator did not work. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if limit_rate was used in HTTPS server. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process while $limit_rate logging. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if there was no "listen" directive in "server" block; the bug had appeared in 0.8.21.
author Igor Sysoev <http://sysoev.ru>
date Tue, 03 Nov 2009 00:00:00 +0300
parents f39b9e29530d
children 2b9e388c61f1
comparison
equal deleted inserted replaced
539:c88014f74832 540:c04fa65fe604
23 typedef struct { 23 typedef struct {
24 ngx_array_t *from; /* array of ngx_http_realip_from_t */ 24 ngx_array_t *from; /* array of ngx_http_realip_from_t */
25 ngx_uint_t type; 25 ngx_uint_t type;
26 ngx_uint_t hash; 26 ngx_uint_t hash;
27 ngx_str_t header; 27 ngx_str_t header;
28 #if (NGX_HAVE_UNIX_DOMAIN)
29 ngx_uint_t unixsock; /* unsigned unixsock:1; */
30 #endif
28 } ngx_http_realip_loc_conf_t; 31 } ngx_http_realip_loc_conf_t;
29 32
30 33
31 typedef struct { 34 typedef struct {
32 ngx_connection_t *connection; 35 ngx_connection_t *connection;
33 in_addr_t addr; 36 struct sockaddr *sockaddr;
37 socklen_t socklen;
34 ngx_str_t addr_text; 38 ngx_str_t addr_text;
35 } ngx_http_realip_ctx_t; 39 } ngx_http_realip_ctx_t;
36 40
37 41
38 static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r); 42 static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
43 static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip,
44 size_t len);
39 static void ngx_http_realip_cleanup(void *data); 45 static void ngx_http_realip_cleanup(void *data);
40 static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, 46 static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
41 void *conf); 47 void *conf);
42 static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 48 static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
43 static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf); 49 static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf);
101 static ngx_int_t 107 static ngx_int_t
102 ngx_http_realip_handler(ngx_http_request_t *r) 108 ngx_http_realip_handler(ngx_http_request_t *r)
103 { 109 {
104 u_char *ip, *p; 110 u_char *ip, *p;
105 size_t len; 111 size_t len;
106 in_addr_t addr;
107 ngx_uint_t i, hash; 112 ngx_uint_t i, hash;
108 ngx_list_part_t *part; 113 ngx_list_part_t *part;
109 ngx_table_elt_t *header; 114 ngx_table_elt_t *header;
110 struct sockaddr_in *sin; 115 struct sockaddr_in *sin;
111 ngx_connection_t *c; 116 ngx_connection_t *c;
112 ngx_pool_cleanup_t *cln;
113 ngx_http_realip_ctx_t *ctx; 117 ngx_http_realip_ctx_t *ctx;
114 ngx_http_realip_from_t *from; 118 ngx_http_realip_from_t *from;
115 ngx_http_realip_loc_conf_t *rlcf; 119 ngx_http_realip_loc_conf_t *rlcf;
116 120
117 ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module); 121 ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
118 122
119 if (ctx) { 123 if (ctx) {
120 return NGX_DECLINED; 124 return NGX_DECLINED;
121 }
122
123 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
124 if (cln == NULL) {
125 return NGX_HTTP_INTERNAL_SERVER_ERROR;
126 } 125 }
127 126
128 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module); 127 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
129 128
130 if (rlcf->from == NULL) { 129 if (rlcf->from == NULL) {
205 204
206 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip); 205 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
207 206
208 /* AF_INET only */ 207 /* AF_INET only */
209 208
210 if (r->connection->sockaddr->sa_family != AF_INET) { 209 if (c->sockaddr->sa_family == AF_INET) {
210 sin = (struct sockaddr_in *) c->sockaddr;
211
212 from = rlcf->from->elts;
213 for (i = 0; i < rlcf->from->nelts; i++) {
214
215 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
216 "realip: %08XD %08XD %08XD",
217 sin->sin_addr.s_addr, from[i].mask, from[i].addr);
218
219 if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
220 return ngx_http_realip_set_addr(r, ip, len);
221 }
222 }
223 }
224
225 #if (NGX_HAVE_UNIX_DOMAIN)
226
227 if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
228 return ngx_http_realip_set_addr(r, ip, len);
229 }
230
231 #endif
232
233 return NGX_DECLINED;
234 }
235
236
237 static ngx_int_t
238 ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
239 {
240 u_char *p;
241 ngx_int_t rc;
242 ngx_addr_t addr;
243 ngx_connection_t *c;
244 ngx_pool_cleanup_t *cln;
245 ngx_http_realip_ctx_t *ctx;
246
247 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
248 if (cln == NULL) {
249 return NGX_HTTP_INTERNAL_SERVER_ERROR;
250 }
251
252 ctx = cln->data;
253 ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
254
255 c = r->connection;
256
257 rc = ngx_parse_addr(c->pool, &addr, ip, len);
258
259 switch (rc) {
260 case NGX_DECLINED:
211 return NGX_DECLINED; 261 return NGX_DECLINED;
212 } 262 case NGX_ERROR:
213 263 return NGX_HTTP_INTERNAL_SERVER_ERROR;
214 sin = (struct sockaddr_in *) c->sockaddr; 264 default: /* NGX_OK */
215 265 break;
216 from = rlcf->from->elts; 266 }
217 for (i = 0; i < rlcf->from->nelts; i++) { 267
218 268 p = ngx_pnalloc(c->pool, len);
219 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, 269 if (p == NULL) {
220 "realip: %08XD %08XD %08XD", 270 return NGX_HTTP_INTERNAL_SERVER_ERROR;
221 sin->sin_addr.s_addr, from[i].mask, from[i].addr); 271 }
222 272
223 if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) { 273 ngx_memcpy(p, ip, len);
224 274
225 ctx = cln->data; 275 cln->handler = ngx_http_realip_cleanup;
226 276
227 ngx_http_set_ctx(r, ctx, ngx_http_realip_module); 277 ctx->connection = c;
228 278 ctx->sockaddr = c->sockaddr;
229 addr = inet_addr((char *) ip); 279 ctx->socklen = c->socklen;
230 280 ctx->addr_text = c->addr_text;
231 if (addr == INADDR_NONE) { 281
232 return NGX_DECLINED; 282 c->sockaddr = addr.sockaddr;
233 } 283 c->socklen = addr.socklen;
234 284 c->addr_text.len = len;
235 p = ngx_pnalloc(c->pool, len); 285 c->addr_text.data = p;
236 if (p == NULL) {
237 return NGX_HTTP_INTERNAL_SERVER_ERROR;
238 }
239
240 ngx_memcpy(p, ip, len);
241
242 cln->handler = ngx_http_realip_cleanup;
243
244 ctx->connection = c;
245 ctx->addr = sin->sin_addr.s_addr;
246 ctx->addr_text = c->addr_text;
247
248 sin->sin_addr.s_addr = addr;
249
250 c->addr_text.len = len;
251 c->addr_text.data = p;
252
253 return NGX_DECLINED;
254 }
255 }
256 286
257 return NGX_DECLINED; 287 return NGX_DECLINED;
258 } 288 }
259 289
260 290
261 static void 291 static void
262 ngx_http_realip_cleanup(void *data) 292 ngx_http_realip_cleanup(void *data)
263 { 293 {
264 ngx_http_realip_ctx_t *ctx = data; 294 ngx_http_realip_ctx_t *ctx = data;
265 295
266 ngx_connection_t *c; 296 ngx_connection_t *c;
267 struct sockaddr_in *sin;
268 297
269 c = ctx->connection; 298 c = ctx->connection;
270 299
271 sin = (struct sockaddr_in *) c->sockaddr; 300 c->sockaddr = ctx->sockaddr;
272 sin->sin_addr.s_addr = ctx->addr; 301 c->socklen = ctx->socklen;
273
274 c->addr_text = ctx->addr_text; 302 c->addr_text = ctx->addr_text;
275 } 303 }
276 304
277 305
278 static char * 306 static char *
282 310
283 ngx_int_t rc; 311 ngx_int_t rc;
284 ngx_str_t *value; 312 ngx_str_t *value;
285 ngx_cidr_t cidr; 313 ngx_cidr_t cidr;
286 ngx_http_realip_from_t *from; 314 ngx_http_realip_from_t *from;
315
316 value = cf->args->elts;
317
318 #if (NGX_HAVE_UNIX_DOMAIN)
319
320 if (ngx_strcmp(value[1].data, "unix:") == 0) {
321 rlcf->unixsock = 1;
322 return NGX_CONF_OK;
323 }
324
325 #endif
287 326
288 if (rlcf->from == NULL) { 327 if (rlcf->from == NULL) {
289 rlcf->from = ngx_array_create(cf->pool, 2, 328 rlcf->from = ngx_array_create(cf->pool, 2,
290 sizeof(ngx_http_realip_from_t)); 329 sizeof(ngx_http_realip_from_t));
291 if (rlcf->from == NULL) { 330 if (rlcf->from == NULL) {
296 from = ngx_array_push(rlcf->from); 335 from = ngx_array_push(rlcf->from);
297 if (from == NULL) { 336 if (from == NULL) {
298 return NGX_CONF_ERROR; 337 return NGX_CONF_ERROR;
299 } 338 }
300 339
301 value = cf->args->elts;
302
303 rc = ngx_ptocidr(&value[1], &cidr); 340 rc = ngx_ptocidr(&value[1], &cidr);
304 341
305 if (rc == NGX_ERROR) { 342 if (rc == NGX_ERROR) {
306 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", 343 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
307 &value[1]); 344 &value[1]);
308 return NGX_CONF_ERROR; 345 return NGX_CONF_ERROR;
309 } 346 }
310 347
311 if (cidr.family != AF_INET) { 348 if (cidr.family != AF_INET) {
312 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 349 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
313 "\"realip_from\" supports IPv4 only"); 350 "\"set_real_ip_from\" supports IPv4 only");
314 return NGX_CONF_ERROR; 351 return NGX_CONF_ERROR;
315 } 352 }
316 353
317 if (rc == NGX_DONE) { 354 if (rc == NGX_DONE) {
318 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, 355 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
367 * set by ngx_pcalloc(): 404 * set by ngx_pcalloc():
368 * 405 *
369 * conf->from = NULL; 406 * conf->from = NULL;
370 * conf->hash = 0; 407 * conf->hash = 0;
371 * conf->header = { 0, NULL }; 408 * conf->header = { 0, NULL };
409 * conf->unixsock = 0;
372 */ 410 */
373 411
374 conf->type = NGX_CONF_UNSET_UINT; 412 conf->type = NGX_CONF_UNSET_UINT;
375 413
376 return conf; 414 return conf;
383 ngx_http_realip_loc_conf_t *prev = parent; 421 ngx_http_realip_loc_conf_t *prev = parent;
384 ngx_http_realip_loc_conf_t *conf = child; 422 ngx_http_realip_loc_conf_t *conf = child;
385 423
386 if (conf->from == NULL) { 424 if (conf->from == NULL) {
387 conf->from = prev->from; 425 conf->from = prev->from;
426 #if (NGX_HAVE_UNIX_DOMAIN)
427 conf->unixsock = prev->unixsock;
428 #endif
388 } 429 }
389 430
390 ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP); 431 ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
391 432
392 if (conf->header.len == 0) { 433 if (conf->header.len == 0) {