Core: introduced ngx_cidr_match() function.

This commit is contained in:
Dmitry Volyntsev 2016-09-07 13:56:53 +03:00
parent d7df0f5ff3
commit 6377f87d38
3 changed files with 118 additions and 104 deletions

View file

@ -465,6 +465,93 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
} }
ngx_int_t
ngx_cidr_match(struct sockaddr *sa, ngx_array_t *cidrs)
{
#if (NGX_HAVE_INET6)
u_char *p;
#endif
in_addr_t inaddr;
ngx_cidr_t *cidr;
ngx_uint_t family, i;
#if (NGX_HAVE_INET6)
ngx_uint_t n;
struct in6_addr *inaddr6;
#endif
#if (NGX_SUPPRESS_WARN)
inaddr = 0;
#if (NGX_HAVE_INET6)
inaddr6 = NULL;
#endif
#endif
family = sa->sa_family;
if (family == AF_INET) {
inaddr = ((struct sockaddr_in *) sa)->sin_addr.s_addr;
}
#if (NGX_HAVE_INET6)
else if (family == AF_INET6) {
inaddr6 = &((struct sockaddr_in6 *) sa)->sin6_addr;
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
family = AF_INET;
p = inaddr6->s6_addr;
inaddr = p[12] << 24;
inaddr += p[13] << 16;
inaddr += p[14] << 8;
inaddr += p[15];
inaddr = htonl(inaddr);
}
}
#endif
for (cidr = cidrs->elts, i = 0; i < cidrs->nelts; i++) {
if (cidr[i].family != family) {
goto next;
}
switch (family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
for (n = 0; n < 16; n++) {
if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
!= cidr[i].u.in6.addr.s6_addr[n])
{
goto next;
}
}
break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
break;
#endif
default: /* AF_INET */
if ((inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
goto next;
}
break;
}
return NGX_OK;
next:
continue;
}
return NGX_DECLINED;
}
ngx_int_t ngx_int_t
ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len) ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
{ {

View file

@ -113,6 +113,7 @@ size_t ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text,
size_t len, ngx_uint_t port); size_t len, 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, ngx_cidr_t *cidr); ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
ngx_int_t ngx_cidr_match(struct sockaddr *sa, ngx_array_t *cidrs);
ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
size_t len); size_t len);
ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr,

View file

@ -2823,120 +2823,46 @@ static ngx_int_t
ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr, ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive) u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
{ {
u_char *p; u_char *p;
in_addr_t inaddr; ngx_int_t rc;
ngx_int_t rc; ngx_addr_t paddr;
ngx_addr_t paddr;
ngx_cidr_t *cidr;
ngx_uint_t family, i;
#if (NGX_HAVE_INET6)
ngx_uint_t n;
struct in6_addr *inaddr6;
#endif
#if (NGX_SUPPRESS_WARN) if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
inaddr = 0; return NGX_DECLINED;
#if (NGX_HAVE_INET6)
inaddr6 = NULL;
#endif
#endif
family = addr->sockaddr->sa_family;
if (family == AF_INET) {
inaddr = ((struct sockaddr_in *) addr->sockaddr)->sin_addr.s_addr;
} }
#if (NGX_HAVE_INET6) for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
else if (family == AF_INET6) { if (*p != ' ' && *p != ',') {
inaddr6 = &((struct sockaddr_in6 *) addr->sockaddr)->sin6_addr; break;
if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
family = AF_INET;
p = inaddr6->s6_addr;
inaddr = p[12] << 24;
inaddr += p[13] << 16;
inaddr += p[14] << 8;
inaddr += p[15];
inaddr = htonl(inaddr);
} }
} }
#endif
for (cidr = proxies->elts, i = 0; i < proxies->nelts; i++) { for ( /* void */ ; p > xff; p--) {
if (cidr[i].family != family) { if (*p == ' ' || *p == ',') {
goto next; p++;
}
switch (family) {
#if (NGX_HAVE_INET6)
case AF_INET6:
for (n = 0; n < 16; n++) {
if ((inaddr6->s6_addr[n] & cidr[i].u.in6.mask.s6_addr[n])
!= cidr[i].u.in6.addr.s6_addr[n])
{
goto next;
}
}
break;
#endif
#if (NGX_HAVE_UNIX_DOMAIN)
case AF_UNIX:
break;
#endif
default: /* AF_INET */
if ((inaddr & cidr[i].u.in.mask) != cidr[i].u.in.addr) {
goto next;
}
break; break;
} }
for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
if (*p != ' ' && *p != ',') {
break;
}
}
for ( /* void */ ; p > xff; p--) {
if (*p == ' ' || *p == ',') {
p++;
break;
}
}
if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff))
!= NGX_OK)
{
return NGX_DECLINED;
}
*addr = paddr;
if (recursive && p > xff) {
rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
proxies, 1);
if (rc == NGX_DECLINED) {
return NGX_DONE;
}
/* rc == NGX_OK || rc == NGX_DONE */
return rc;
}
return NGX_OK;
next:
continue;
} }
return NGX_DECLINED; if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
return NGX_DECLINED;
}
*addr = paddr;
if (recursive && p > xff) {
rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
proxies, 1);
if (rc == NGX_DECLINED) {
return NGX_DONE;
}
/* rc == NGX_OK || rc == NGX_DONE */
return rc;
}
return NGX_OK;
} }