# HG changeset patch # User Dmitry Volyntsev # Date 1473245813 -10800 # Node ID b802b7e1d9bc03048ef1530273920e0bd5d679cb # Parent db422604ceb0b2ec21b8efffc456a6360bd0baff Core: introduced ngx_cidr_match() function. diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -466,6 +466,93 @@ ngx_ptocidr(ngx_str_t *text, ngx_cidr_t 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_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len) { in_addr_t inaddr; diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -113,6 +113,7 @@ size_t ngx_sock_ntop(struct sockaddr *sa size_t len, ngx_uint_t port); 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_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, size_t len); ngx_int_t ngx_parse_addr_port(ngx_pool_t *pool, ngx_addr_t *addr, diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2823,120 +2823,46 @@ static ngx_int_t 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 *p; - in_addr_t inaddr; - ngx_int_t rc; - 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) - inaddr = 0; -#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) - else if (family == AF_INET6) { - inaddr6 = &((struct sockaddr_in6 *) addr->sockaddr)->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); + u_char *p; + ngx_int_t rc; + ngx_addr_t paddr; + + if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) { + return NGX_DECLINED; + } + + for (p = xff + xfflen - 1; p > xff; p--, xfflen--) { + if (*p != ' ' && *p != ',') { + break; } } -#endif - - for (cidr = proxies->elts, i = 0; i < proxies->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; - } + + for ( /* void */ ; p > xff; p--) { + if (*p == ' ' || *p == ',') { + p++; 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; + } + + 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; } - *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; + /* rc == NGX_OK || rc == NGX_DONE */ + return rc; + } + + return NGX_OK; }