prepare ngx_ptocidr() for IPv6

This commit is contained in:
Igor Sysoev 2009-02-24 14:01:40 +00:00
parent 1f4220ee86
commit 36860101ec
6 changed files with 115 additions and 66 deletions

View File

@ -226,26 +226,25 @@ ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
/* AF_INET only */ /* AF_INET only */
ngx_int_t ngx_int_t
ngx_ptocidr(ngx_str_t *text, void *cidr) ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
{ {
u_char *addr, *mask, *last; u_char *addr, *mask, *last;
ngx_int_t shift; ngx_int_t shift;
ngx_inet_cidr_t *in_cidr;
in_cidr = cidr;
addr = text->data; addr = text->data;
last = addr + text->len; last = addr + text->len;
mask = ngx_strlchr(addr, last, '/'); mask = ngx_strlchr(addr, last, '/');
in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
if (in_cidr->addr == INADDR_NONE) { if (cidr->u.in.addr == INADDR_NONE) {
return NGX_ERROR; return NGX_ERROR;
} }
if (mask == NULL) { if (mask == NULL) {
in_cidr->mask = 0xffffffff; cidr->family = AF_INET;
cidr->u.in.mask = 0xffffffff;
return NGX_OK; return NGX_OK;
} }
@ -256,26 +255,28 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
return NGX_ERROR; return NGX_ERROR;
} }
cidr->family = AF_INET;
if (shift == 0) { if (shift == 0) {
/* the x86 compilers use the shl instruction that shifts by modulo 32 */ /* the x86 compilers use the shl instruction that shifts by modulo 32 */
in_cidr->mask = 0; cidr->u.in.mask = 0;
if (in_cidr->addr == 0) { if (cidr->u.in.addr == 0) {
return NGX_OK; return NGX_OK;
} }
return NGX_DONE; return NGX_DONE;
} }
in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) { if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
return NGX_OK; return NGX_OK;
} }
in_cidr->addr &= in_cidr->mask; cidr->u.in.addr &= cidr->u.in.mask;
return NGX_DONE; return NGX_DONE;
} }

View File

@ -35,50 +35,71 @@
typedef struct { typedef struct {
in_addr_t addr; struct in6_addr addr;
in_addr_t mask; struct in6_addr mask;
} ngx_inet_cidr_t; } ngx_in6_cidr_t;
#if (NGX_HAVE_INET6)
typedef struct {
in_addr_t addr;
in_addr_t mask;
} ngx_in_cidr_t;
#endif
typedef struct {
ngx_uint_t family;
union {
ngx_in_cidr_t in;
#if (NGX_HAVE_INET6)
ngx_in6_cidr_t in6;
#endif
} u;
} ngx_cidr_t;
typedef union { typedef union {
in_addr_t in_addr; in_addr_t in_addr;
} ngx_url_addr_t; } ngx_url_addr_t;
typedef struct { typedef struct {
struct sockaddr *sockaddr; struct sockaddr *sockaddr;
socklen_t socklen; socklen_t socklen;
ngx_str_t name; ngx_str_t name;
} ngx_peer_addr_t; } ngx_peer_addr_t;
typedef struct { typedef struct {
ngx_str_t url; ngx_str_t url;
ngx_str_t host; ngx_str_t host;
ngx_str_t port_text; ngx_str_t port_text;
ngx_str_t uri; ngx_str_t uri;
in_port_t port; in_port_t port;
in_port_t default_port; in_port_t default_port;
int family; int family;
unsigned listen:1; unsigned listen:1;
unsigned uri_part:1; unsigned uri_part:1;
unsigned no_resolve:1; unsigned no_resolve:1;
unsigned one_addr:1; unsigned one_addr:1;
unsigned no_port:1; unsigned no_port:1;
unsigned wildcard:1; unsigned wildcard:1;
ngx_url_addr_t addr; ngx_url_addr_t addr;
socklen_t socklen; socklen_t socklen;
u_char sockaddr[NGX_SOCKADDRLEN]; u_char sockaddr[NGX_SOCKADDRLEN];
ngx_peer_addr_t *addrs; ngx_peer_addr_t *addrs;
ngx_uint_t naddrs; ngx_uint_t naddrs;
char *err; char *err;
} ngx_url_t; } ngx_url_t;
@ -86,7 +107,7 @@ in_addr_t ngx_inet_addr(u_char *text, size_t len);
size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
ngx_uint_t port); ngx_uint_t port);
size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len); size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr); ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u); ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);

View File

@ -1040,18 +1040,16 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value; ngx_str_t *value;
ngx_event_debug_t *dc; ngx_event_debug_t *dc;
struct hostent *h; struct hostent *h;
ngx_inet_cidr_t in_cidr; ngx_cidr_t cidr;
value = cf->args->elts; value = cf->args->elts;
/* AF_INET only */
dc = ngx_array_push(&ecf->debug_connection); dc = ngx_array_push(&ecf->debug_connection);
if (dc == NULL) { if (dc == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
rc = ngx_ptocidr(&value[1], &in_cidr); rc = ngx_ptocidr(&value[1], &cidr);
if (rc == NGX_DONE) { if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@ -1060,8 +1058,18 @@ ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
} }
if (rc == NGX_OK) { if (rc == NGX_OK) {
dc->mask = in_cidr.mask;
dc->addr = in_cidr.addr; /* AF_INET only */
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"debug_connection\" supports IPv4 only");
return NGX_CONF_ERROR;
}
dc->mask = cidr.u.in.mask;
dc->addr = cidr.u.in.addr;
return NGX_CONF_OK; return NGX_CONF_OK;
} }

View File

@ -141,7 +141,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t rc; ngx_int_t rc;
ngx_str_t *value; ngx_str_t *value;
ngx_inet_cidr_t in_cidr; ngx_cidr_t cidr;
ngx_http_access_rule_t *rule; ngx_http_access_rule_t *rule;
if (alcf->rules == NULL) { if (alcf->rules == NULL) {
@ -168,7 +168,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_OK; return NGX_CONF_OK;
} }
rc = ngx_ptocidr(&value[1], &in_cidr); rc = ngx_ptocidr(&value[1], &cidr);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@ -176,13 +176,19 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"allow\" supports IPv4 only");
return NGX_CONF_ERROR;
}
if (rc == NGX_DONE) { if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", &value[1]); "low address bits of %V are meaningless", &value[1]);
} }
rule->mask = in_cidr.mask; rule->mask = cidr.u.in.mask;
rule->addr = in_cidr.addr; rule->addr = cidr.u.in.addr;
return NGX_CONF_OK; return NGX_CONF_OK;
} }

View File

@ -778,7 +778,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
ngx_int_t rc, del; ngx_int_t rc, del;
ngx_str_t *net; ngx_str_t *net;
ngx_uint_t i; ngx_uint_t i;
ngx_inet_cidr_t cidrin; ngx_cidr_t cidr;
ngx_http_variable_value_t *val, *old; ngx_http_variable_value_t *val, *old;
if (ctx->tree == NULL) { if (ctx->tree == NULL) {
@ -789,8 +789,8 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
} }
if (ngx_strcmp(value[0].data, "default") == 0) { if (ngx_strcmp(value[0].data, "default") == 0) {
cidrin.addr = 0; cidr.u.in.addr = 0;
cidrin.mask = 0; cidr.u.in.mask = 0;
net = &value[0]; net = &value[0];
} else { } else {
@ -804,11 +804,11 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
} }
if (ngx_strcmp(net->data, "255.255.255.255") == 0) { if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
cidrin.addr = 0xffffffff; cidr.u.in.addr = 0xffffffff;
cidrin.mask = 0xffffffff; cidr.u.in.mask = 0xffffffff;
} else { } else {
rc = ngx_ptocidr(net, &cidrin); rc = ngx_ptocidr(net, &cidr);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@ -816,18 +816,25 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"geo\" supports IPv4 only");
return NGX_CONF_ERROR;
}
if (rc == NGX_DONE) { if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", "low address bits of %V are meaningless",
net); net);
} }
cidrin.addr = ntohl(cidrin.addr); cidr.u.in.addr = ntohl(cidr.u.in.addr);
cidrin.mask = ntohl(cidrin.mask); cidr.u.in.mask = ntohl(cidr.u.in.mask);
} }
if (del) { if (del) {
if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask) if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
cidr.u.in.mask)
!= NGX_OK) != NGX_OK)
{ {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@ -845,7 +852,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
} }
for (i = 2; i; i--) { for (i = 2; i; i--) {
rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask, rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
(uintptr_t) val); (uintptr_t) val);
if (rc == NGX_OK) { if (rc == NGX_OK) {
return NGX_CONF_OK; return NGX_CONF_OK;
@ -858,13 +865,13 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
/* rc == NGX_BUSY */ /* rc == NGX_BUSY */
old = (ngx_http_variable_value_t *) old = (ngx_http_variable_value_t *)
ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask); ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"duplicate network \"%V\", value: \"%v\", old value: \"%v\"", "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
net, val, old); net, val, old);
rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask); rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");

View File

@ -282,7 +282,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t rc; ngx_int_t rc;
ngx_str_t *value; ngx_str_t *value;
ngx_inet_cidr_t in_cidr; ngx_cidr_t cidr;
ngx_http_realip_from_t *from; ngx_http_realip_from_t *from;
if (rlcf->from == NULL) { if (rlcf->from == NULL) {
@ -300,7 +300,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts; value = cf->args->elts;
rc = ngx_ptocidr(&value[1], &in_cidr); rc = ngx_ptocidr(&value[1], &cidr);
if (rc == NGX_ERROR) { if (rc == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@ -308,13 +308,19 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
if (cidr.family != AF_INET) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"\"realip_from\" supports IPv4 only");
return NGX_CONF_ERROR;
}
if (rc == NGX_DONE) { if (rc == NGX_DONE) {
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
"low address bits of %V are meaningless", &value[1]); "low address bits of %V are meaningless", &value[1]);
} }
from->mask = in_cidr.mask; from->mask = cidr.u.in.mask;
from->addr = in_cidr.addr; from->addr = cidr.u.in.addr;
return NGX_CONF_OK; return NGX_CONF_OK;
} }