# HG changeset patch # User Ruslan Ermilov # Date 1494857821 -10800 # Node ID df1a62c83b1b62ec1b99463cf9e5c4b661c3e57e # Parent 72188d1bcab5026f1842e73a83b9c91e83cfe786 Realip: allow hostnames in set_real_ip_from (ticket #1180). diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -317,9 +317,15 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx { ngx_http_realip_loc_conf_t *rlcf = conf; - ngx_int_t rc; - ngx_str_t *value; - ngx_cidr_t *cidr; + ngx_int_t rc; + ngx_str_t *value; + ngx_url_t u; + ngx_cidr_t c, *cidr; + ngx_uint_t i; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif value = cf->args->elts; @@ -331,31 +337,78 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx } } - cidr = ngx_array_push(rlcf->from); - if (cidr == NULL) { - return NGX_CONF_ERROR; - } - #if (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { + cidr = ngx_array_push(rlcf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + cidr->family = AF_UNIX; return NGX_CONF_OK; } #endif - rc = ngx_ptocidr(&value[1], cidr); + rc = ngx_ptocidr(&value[1], &c); + + if (rc != NGX_ERROR) { + if (rc == NGX_DONE) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "low address bits of %V are meaningless", + &value[1]); + } + + cidr = ngx_array_push(rlcf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } - if (rc == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", - &value[1]); + *cidr = c; + + return NGX_CONF_OK; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + u.host = value[1]; + + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in set_real_ip_from \"%V\"", + u.err, &u.host); + } + return NGX_CONF_ERROR; } - if (rc == NGX_DONE) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "low address bits of %V are meaningless", &value[1]); + cidr = ngx_array_push_n(rlcf->from, u.naddrs); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); + + for (i = 0; i < u.naddrs; i++) { + cidr[i].family = u.addrs[i].sockaddr->sa_family; + + switch (cidr[i].family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; + cidr[i].u.in6.addr = sin6->sin6_addr; + ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) u.addrs[i].sockaddr; + cidr[i].u.in.addr = sin->sin_addr.s_addr; + cidr[i].u.in.mask = 0xffffffff; + break; + } } return NGX_CONF_OK; diff --git a/src/stream/ngx_stream_realip_module.c b/src/stream/ngx_stream_realip_module.c --- a/src/stream/ngx_stream_realip_module.c +++ b/src/stream/ngx_stream_realip_module.c @@ -178,9 +178,15 @@ ngx_stream_realip_from(ngx_conf_t *cf, n { ngx_stream_realip_srv_conf_t *rscf = conf; - ngx_int_t rc; - ngx_str_t *value; - ngx_cidr_t *cidr; + ngx_int_t rc; + ngx_str_t *value; + ngx_url_t u; + ngx_cidr_t c, *cidr; + ngx_uint_t i; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif value = cf->args->elts; @@ -192,31 +198,78 @@ ngx_stream_realip_from(ngx_conf_t *cf, n } } - cidr = ngx_array_push(rscf->from); - if (cidr == NULL) { - return NGX_CONF_ERROR; - } - #if (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { + cidr = ngx_array_push(rscf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + cidr->family = AF_UNIX; return NGX_CONF_OK; } #endif - rc = ngx_ptocidr(&value[1], cidr); + rc = ngx_ptocidr(&value[1], &c); + + if (rc != NGX_ERROR) { + if (rc == NGX_DONE) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "low address bits of %V are meaningless", + &value[1]); + } + + cidr = ngx_array_push(rscf->from); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } - if (rc == NGX_ERROR) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", - &value[1]); + *cidr = c; + + return NGX_CONF_OK; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + u.host = value[1]; + + if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in set_real_ip_from \"%V\"", + u.err, &u.host); + } + return NGX_CONF_ERROR; } - if (rc == NGX_DONE) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "low address bits of %V are meaningless", &value[1]); + cidr = ngx_array_push_n(rscf->from, u.naddrs); + if (cidr == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t)); + + for (i = 0; i < u.naddrs; i++) { + cidr[i].family = u.addrs[i].sockaddr->sa_family; + + switch (cidr[i].family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr; + cidr[i].u.in6.addr = sin6->sin6_addr; + ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16); + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) u.addrs[i].sockaddr; + cidr[i].u.in.addr = sin->sin_addr.s_addr; + cidr[i].u.in.mask = 0xffffffff; + break; + } } return NGX_CONF_OK;