# HG changeset patch # User Roman Arutyunyan # Date 1552653956 -10800 # Node ID 4f9b72a229c190f2d25d12f3d4b09299660ceee0 # Parent c74904a1702135f673a275bd0d36f010a3bfb89a Multiple addresses in "listen". Previously only one address was used by the listen directive handler even if host name resolved to multiple addresses. Now a separate listening socket is created for each address. 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 @@ -12,6 +12,8 @@ static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u); +static ngx_int_t ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, + struct sockaddr *sockaddr, socklen_t socklen, ngx_uint_t total); in_addr_t @@ -780,13 +782,10 @@ ngx_parse_unix_domain_url(ngx_pool_t *po static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host, *port, *last, *uri, *args; - size_t len; - ngx_int_t n; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - struct sockaddr_in6 *sin6; -#endif + u_char *host, *port, *last, *uri, *args; + size_t len; + ngx_int_t n; + struct sockaddr_in *sin; u->socklen = sizeof(struct sockaddr_in); sin = (struct sockaddr_in *) &u->sockaddr; @@ -864,13 +863,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->port = (in_port_t) n; sin->sin_port = htons((in_port_t) n); + sin->sin_addr.s_addr = INADDR_ANY; u->port_text.len = last - host; u->port_text.data = host; u->wildcard = 1; - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, + u->socklen, 1); } } } @@ -893,7 +894,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx if (u->listen && len == 1 && *host == '*') { sin->sin_addr.s_addr = INADDR_ANY; u->wildcard = 1; - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); } sin->sin_addr.s_addr = ngx_inet_addr(host, len); @@ -904,33 +905,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->wildcard = 1; } - u->naddrs = 1; - - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(sin, &u->sockaddr, sizeof(struct sockaddr_in)); - - u->addrs[0].sockaddr = (struct sockaddr *) sin; - u->addrs[0].socklen = sizeof(struct sockaddr_in); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, u->port) - p; - u->addrs[0].name.data = p; - - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); } if (u->no_resolve) { @@ -944,29 +919,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx u->family = u->addrs[0].sockaddr->sa_family; u->socklen = u->addrs[0].socklen; ngx_memcpy(&u->sockaddr, u->addrs[0].sockaddr, u->addrs[0].socklen); - - switch (u->family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) &u->sockaddr; - - if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - u->wildcard = 1; - } - - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) &u->sockaddr; - - if (sin->sin_addr.s_addr == INADDR_ANY) { - u->wildcard = 1; - } - - break; - } + u->wildcard = ngx_inet_wildcard(&u->sockaddr.sockaddr); return NGX_OK; } @@ -1061,33 +1014,8 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng } u->family = AF_INET6; - u->naddrs = 1; - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6)); - if (sin6 == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(sin6, &u->sockaddr, sizeof(struct sockaddr_in6)); - - u->addrs[0].sockaddr = (struct sockaddr *) sin6; - u->addrs[0].socklen = sizeof(struct sockaddr_in6); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, u->port) - p; - u->addrs[0].name.data = p; - - return NGX_OK; + return ngx_inet_add_addr(pool, u, &u->sockaddr.sockaddr, u->socklen, 1); #else @@ -1104,15 +1032,9 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host; - size_t len; - in_port_t port; - ngx_uint_t i; - struct addrinfo hints, *res, *rp; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - - port = htons(u->port); + u_char *host; + ngx_uint_t n; + struct addrinfo hints, *res, *rp; host = ngx_alloc(u->host.len + 1, pool->log); if (host == NULL) { @@ -1136,7 +1058,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_free(host); - for (i = 0, rp = res; rp != NULL; rp = rp->ai_next) { + for (n = 0, rp = res; rp != NULL; rp = rp->ai_next) { switch (rp->ai_family) { @@ -1148,25 +1070,16 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - i++; + n++; } - if (i == 0) { + if (n == 0) { u->err = "host not found"; goto failed; } /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - goto failed; - } - - u->naddrs = i; - - i = 0; - /* AF_INET addresses first */ for (rp = res; rp != NULL; rp = rp->ai_next) { @@ -1175,31 +1088,11 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - sin = ngx_pcalloc(pool, rp->ai_addrlen); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) + != NGX_OK) + { goto failed; } - - ngx_memcpy(sin, rp->ai_addr, rp->ai_addrlen); - - sin->sin_port = port; - - u->addrs[i].sockaddr = (struct sockaddr *) sin; - u->addrs[i].socklen = rp->ai_addrlen; - - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - goto failed; - } - - len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; - - i++; } for (rp = res; rp != NULL; rp = rp->ai_next) { @@ -1208,32 +1101,11 @@ ngx_inet_resolve_host(ngx_pool_t *pool, continue; } - sin6 = ngx_pcalloc(pool, rp->ai_addrlen); - if (sin6 == NULL) { + if (ngx_inet_add_addr(pool, u, rp->ai_addr, rp->ai_addrlen, n) + != NGX_OK) + { goto failed; } - - ngx_memcpy(sin6, rp->ai_addr, rp->ai_addrlen); - - sin6->sin6_port = port; - - u->addrs[i].sockaddr = (struct sockaddr *) sin6; - u->addrs[i].socklen = rp->ai_addrlen; - - len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - goto failed; - } - - len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p, - len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; - - i++; } freeaddrinfo(res); @@ -1250,21 +1122,19 @@ failed: ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host; - size_t len; - in_port_t port; - in_addr_t in_addr; - ngx_uint_t i; + u_char *host; + ngx_uint_t i, n; struct hostent *h; - struct sockaddr_in *sin; + struct sockaddr_in sin; /* AF_INET only */ - port = htons(u->port); + ngx_memzero(&sin, sizeof(struct sockaddr_in)); - in_addr = ngx_inet_addr(u->host.data, u->host.len); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = ngx_inet_addr(u->host.data, u->host.len); - if (in_addr == INADDR_NONE) { + if (sin.sin_addr.s_addr == INADDR_NONE) { host = ngx_alloc(u->host.len + 1, pool->log); if (host == NULL) { return NGX_ERROR; @@ -1281,76 +1151,31 @@ ngx_inet_resolve_host(ngx_pool_t *pool, return NGX_ERROR; } - for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } + for (n = 0; h->h_addr_list[n] != NULL; n++) { /* void */ } /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } + for (i = 0; i < n; i++) { + sin.sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); - u->naddrs = i; - - for (i = 0; i < u->naddrs; i++) { - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, + sizeof(struct sockaddr_in), n) + != NGX_OK) + { return NGX_ERROR; } - - sin->sin_family = AF_INET; - sin->sin_port = port; - sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); - - u->addrs[i].sockaddr = (struct sockaddr *) sin; - u->addrs[i].socklen = sizeof(struct sockaddr_in); - - len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; - - p = ngx_pnalloc(pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - len = ngx_sock_ntop((struct sockaddr *) sin, - sizeof(struct sockaddr_in), p, len, 1); - - u->addrs[i].name.len = len; - u->addrs[i].name.data = p; } } else { /* MP: ngx_shared_palloc() */ - u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in)); - if (sin == NULL) { + if (ngx_inet_add_addr(pool, u, (struct sockaddr *) &sin, + sizeof(struct sockaddr_in), 1) + != NGX_OK) + { return NGX_ERROR; } - - u->naddrs = 1; - - sin->sin_family = AF_INET; - sin->sin_port = port; - sin->sin_addr.s_addr = in_addr; - - u->addrs[0].sockaddr = (struct sockaddr *) sin; - u->addrs[0].socklen = sizeof(struct sockaddr_in); - - p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1); - if (p == NULL) { - return NGX_ERROR; - } - - u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", - &u->host, ntohs(port)) - p; - u->addrs[0].name.data = p; } return NGX_OK; @@ -1359,6 +1184,62 @@ ngx_inet_resolve_host(ngx_pool_t *pool, #endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */ +static ngx_int_t +ngx_inet_add_addr(ngx_pool_t *pool, ngx_url_t *u, struct sockaddr *sockaddr, + socklen_t socklen, ngx_uint_t total) +{ + u_char *p; + size_t len; + ngx_addr_t *addr; + struct sockaddr *sa; + + if (u->addrs == NULL) { + u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t)); + if (u->addrs == NULL) { + return NGX_ERROR; + } + } + + sa = ngx_pcalloc(pool, socklen); + if (sa == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(sa, sockaddr, socklen); + + ngx_inet_set_port(sa, u->port); + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1; + break; +#endif + + default: /* AF_INET */ + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + } + + p = ngx_pnalloc(pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + len = ngx_sock_ntop(sa, socklen, p, len, 1); + + addr = &u->addrs[u->naddrs++]; + + addr->sockaddr = sa; + addr->socklen = socklen; + + addr->name.len = len; + addr->name.data = p; + + return NGX_OK; +} + + ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1, struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port) @@ -1495,3 +1376,40 @@ ngx_inet_set_port(struct sockaddr *sa, i break; } } + + +ngx_uint_t +ngx_inet_wildcard(struct sockaddr *sa) +{ + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + switch (sa->sa_family) { + + case AF_INET: + sin = (struct sockaddr_in *) sa; + + if (sin->sin_addr.s_addr == INADDR_ANY) { + return 1; + } + + break; + +#if (NGX_HAVE_INET6) + + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + return 1; + } + + break; + +#endif + } + + return 0; +} 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 @@ -125,6 +125,7 @@ ngx_int_t ngx_cmp_sockaddr(struct sockad struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port); in_port_t ngx_inet_get_port(struct sockaddr *sa); void ngx_inet_set_port(struct sockaddr *sa, in_port_t port); +ngx_uint_t ngx_inet_wildcard(struct sockaddr *sa); #endif /* _NGX_INET_H_INCLUDED_ */ diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1157,7 +1157,7 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ } } - sa = &lsopt->sockaddr.sockaddr; + sa = lsopt->sockaddr; p = ngx_inet_get_port(sa); port = cmcf->ports->elts; @@ -1209,8 +1209,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n for (i = 0; i < port->addrs.nelts; i++) { - if (ngx_cmp_sockaddr(&lsopt->sockaddr.sockaddr, lsopt->socklen, - &addr[i].opt.sockaddr.sockaddr, + if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen, + addr[i].opt.sockaddr, addr[i].opt.socklen, 0) != NGX_OK) { @@ -1239,7 +1239,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n if (addr[i].opt.set) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate listen options for %s", addr[i].opt.addr); + "duplicate listen options for %V", + &addr[i].opt.addr_text); return NGX_ERROR; } @@ -1252,7 +1253,8 @@ ngx_http_add_addresses(ngx_conf_t *cf, n if (default_server) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate default server for %s", addr[i].opt.addr); + "a duplicate default server for %V", + &addr[i].opt.addr_text); return NGX_ERROR; } @@ -1305,8 +1307,8 @@ ngx_http_add_address(ngx_conf_t *cf, ngx if (lsopt->http2 && lsopt->ssl) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "nginx was built with OpenSSL that lacks ALPN " - "and NPN support, HTTP/2 is not enabled for %s", - lsopt->addr); + "and NPN support, HTTP/2 is not enabled for %V", + &lsopt->addr_text); } #endif @@ -1354,7 +1356,8 @@ ngx_http_add_server(ngx_conf_t *cf, ngx_ for (i = 0; i < addr->servers.nelts; i++) { if (server[i] == cscf) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "a duplicate listen %s", addr->opt.addr); + "a duplicate listen %V", + &addr->opt.addr_text); return NGX_ERROR; } } @@ -1471,15 +1474,15 @@ ngx_http_server_names(ngx_conf_t *cf, ng if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid server name or wildcard \"%V\" on %s", - &name[n].name, addr->opt.addr); + "invalid server name or wildcard \"%V\" on %V", + &name[n].name, &addr->opt.addr_text); return NGX_ERROR; } if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "conflicting server name \"%V\" on %s, ignored", - &name[n].name, addr->opt.addr); + "conflicting server name \"%V\" on %V, ignored", + &name[n].name, &addr->opt.addr_text); } } } @@ -1700,8 +1703,7 @@ ngx_http_add_listening(ngx_conf_t *cf, n ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - ls = ngx_create_listening(cf, &addr->opt.sockaddr.sockaddr, - addr->opt.socklen); + ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen); if (ls == NULL) { return NULL; } @@ -1791,7 +1793,7 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h for (i = 0; i < hport->naddrs; i++) { - sin = &addr[i].opt.sockaddr.sockaddr_in; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) @@ -1856,7 +1858,7 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < hport->naddrs; i++) { - sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.default_server = addr[i].default_server; #if (NGX_HTTP_SSL) 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 @@ -2715,6 +2715,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx { char *rv; void *mconf; + size_t len; + u_char *p; ngx_uint_t i; ngx_conf_t pcf; ngx_http_module_t *module; @@ -2802,7 +2804,14 @@ ngx_http_core_server(ngx_conf_t *cf, ngx if (rv == NGX_CONF_OK && !cscf->listen) { ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - sin = &lsopt.sockaddr.sockaddr_in; + p = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lsopt.sockaddr = (struct sockaddr *) p; + + sin = (struct sockaddr_in *) p; sin->sin_family = AF_INET; #if (NGX_WIN32) @@ -2825,8 +2834,16 @@ ngx_http_core_server(ngx_conf_t *cf, ngx #endif lsopt.wildcard = 1; - (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, - lsopt.addr, NGX_SOCKADDR_STRLEN, 1); + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + lsopt.addr_text.data = p; + lsopt.addr_text.len = ngx_sock_ntop(lsopt.sockaddr, lsopt.socklen, p, + len, 1); if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { return NGX_CONF_ERROR; @@ -3779,9 +3796,6 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen); - - lsopt.socklen = u.socklen; lsopt.backlog = NGX_LISTEN_BACKLOG; lsopt.rcvbuf = -1; lsopt.sndbuf = -1; @@ -3791,14 +3805,10 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #if (NGX_HAVE_TCP_FASTOPEN) lsopt.fastopen = -1; #endif - lsopt.wildcard = u.wildcard; #if (NGX_HAVE_INET6) lsopt.ipv6only = 1; #endif - (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); - for (n = 2; n < cf->args->nelts; n++) { if (ngx_strcmp(value[n].data, "default_server") == 0 @@ -3923,34 +3933,22 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - struct sockaddr *sa; - - sa = &lsopt.sockaddr.sockaddr; - - if (sa->sa_family == AF_INET6) { - - if (ngx_strcmp(&value[n].data[10], "n") == 0) { - lsopt.ipv6only = 1; - - } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { - lsopt.ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[n].data[9]); - return NGX_CONF_ERROR; - } - - lsopt.set = 1; - lsopt.bind = 1; + if (ngx_strcmp(&value[n].data[10], "n") == 0) { + lsopt.ipv6only = 1; + + } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) { + lsopt.ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%s\", ignored", lsopt.addr); + "invalid ipv6only flags \"%s\"", + &value[n].data[9]); + return NGX_CONF_ERROR; } + lsopt.set = 1; + lsopt.bind = 1; + continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -4106,11 +4104,18 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) { - return NGX_CONF_OK; - } - - return NGX_CONF_ERROR; + for (n = 0; n < u.naddrs; n++) { + lsopt.sockaddr = u.addrs[n].sockaddr; + lsopt.socklen = u.addrs[n].socklen; + lsopt.addr_text = u.addrs[n].name; + lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr); + + if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -65,8 +65,9 @@ typedef struct ngx_http_core_loc_conf_s typedef struct { - ngx_sockaddr_t sockaddr; + struct sockaddr *sockaddr; socklen_t socklen; + ngx_str_t addr_text; unsigned set:1; unsigned default_server:1; @@ -100,8 +101,6 @@ typedef struct { #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) char *accept_filter; #endif - - u_char addr[NGX_SOCKADDR_STRLEN + 1]; } ngx_http_listen_opt_t; diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -231,7 +231,7 @@ ngx_mail_add_ports(ngx_conf_t *cf, ngx_a ngx_mail_conf_port_t *port; ngx_mail_conf_addr_t *addr; - sa = &listen->sockaddr.sockaddr; + sa = listen->sockaddr; p = ngx_inet_get_port(sa); port = ports->elts; @@ -316,7 +316,7 @@ ngx_mail_optimize_servers(ngx_conf_t *cf continue; } - ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, + ls = ngx_create_listening(cf, addr[i].opt.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -384,12 +384,9 @@ static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, ngx_mail_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; ngx_mail_in_addr_t *addrs; struct sockaddr_in *sin; - u_char buf[NGX_SOCKADDR_STRLEN]; mport->addrs = ngx_pcalloc(cf->pool, mport->naddrs * sizeof(ngx_mail_in_addr_t)); @@ -401,26 +398,14 @@ ngx_mail_add_addrs(ngx_conf_t *cf, ngx_m for (i = 0; i < mport->naddrs; i++) { - sin = &addr[i].opt.sockaddr.sockaddr_in; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) addrs[i].conf.ssl = addr[i].opt.ssl; #endif - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs[i].conf.addr_text.len = len; - addrs[i].conf.addr_text.data = p; + addrs[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; @@ -433,12 +418,9 @@ static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, ngx_mail_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; ngx_mail_in6_addr_t *addrs6; struct sockaddr_in6 *sin6; - u_char buf[NGX_SOCKADDR_STRLEN]; mport->addrs = ngx_pcalloc(cf->pool, mport->naddrs * sizeof(ngx_mail_in6_addr_t)); @@ -450,26 +432,14 @@ ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_ for (i = 0; i < mport->naddrs; i++) { - sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; #if (NGX_MAIL_SSL) addrs6[i].conf.ssl = addr[i].opt.ssl; #endif - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs6[i].conf.addr_text.len = len; - addrs6[i].conf.addr_text.data = p; + addrs6[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -27,8 +27,9 @@ typedef struct { typedef struct { - ngx_sockaddr_t sockaddr; + struct sockaddr *sockaddr; socklen_t socklen; + ngx_str_t addr_text; /* server ctx */ ngx_mail_conf_ctx_t *ctx; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -297,8 +297,8 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_str_t *value, size; ngx_url_t u; - ngx_uint_t i, m; - ngx_mail_listen_t *ls; + ngx_uint_t i, n, m; + ngx_mail_listen_t *ls, *als; ngx_mail_module_t *module; ngx_mail_core_main_conf_t *cmcf; @@ -323,36 +323,16 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); - ls = cmcf->listen.elts; - - for (i = 0; i < cmcf->listen.nelts; i++) { - - if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, - (struct sockaddr *) &u.sockaddr, u.socklen, 1) - != NGX_OK) - { - continue; - } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"%V\" address and port pair", &u.url); - return NGX_CONF_ERROR; - } - - ls = ngx_array_push(&cmcf->listen); + ls = ngx_array_push_n(&cmcf->listen, u.naddrs); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); - - ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; - ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if (NGX_HAVE_INET6) @@ -434,35 +414,20 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - size_t len; - u_char buf[NGX_SOCKADDR_STRLEN]; - - if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { - - if (ngx_strcmp(&value[i].data[10], "n") == 0) { - ls->ipv6only = 1; + if (ngx_strcmp(&value[i].data[10], "n") == 0) { + ls->ipv6only = 1; - } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { - ls->ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[i].data[9]); - return NGX_CONF_ERROR; - } - - ls->bind = 1; + } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { + ls->ipv6only = 0; } else { - len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, - NGX_SOCKADDR_STRLEN, 1); - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%*s\", ignored", len, buf); + "invalid ipv6only flags \"%s\"", + &value[i].data[9]); + return NGX_CONF_ERROR; } + ls->bind = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -588,6 +553,32 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } + als = cmcf->listen.elts; + + for (n = 0; n < u.naddrs; n++) { + ls[n] = ls[0]; + + ls[n].sockaddr = u.addrs[n].sockaddr; + ls[n].socklen = u.addrs[n].socklen; + ls[n].addr_text = u.addrs[n].name; + ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); + + for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { + + if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, + ls[n].sockaddr, ls[n].socklen, 1) + != NGX_OK) + { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", + &ls[n].addr_text); + return NGX_CONF_ERROR; + } + } + return NGX_CONF_OK; } diff --git a/src/stream/ngx_stream.c b/src/stream/ngx_stream.c --- a/src/stream/ngx_stream.c +++ b/src/stream/ngx_stream.c @@ -387,7 +387,7 @@ ngx_stream_add_ports(ngx_conf_t *cf, ngx ngx_stream_conf_port_t *port; ngx_stream_conf_addr_t *addr; - sa = &listen->sockaddr.sockaddr; + sa = listen->sockaddr; p = ngx_inet_get_port(sa); port = ports->elts; @@ -476,7 +476,7 @@ ngx_stream_optimize_servers(ngx_conf_t * continue; } - ls = ngx_create_listening(cf, &addr[i].opt.sockaddr.sockaddr, + ls = ngx_create_listening(cf, addr[i].opt.sockaddr, addr[i].opt.socklen); if (ls == NULL) { return NGX_CONF_ERROR; @@ -551,12 +551,9 @@ static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; struct sockaddr_in *sin; ngx_stream_in_addr_t *addrs; - u_char buf[NGX_SOCKADDR_STRLEN]; stport->addrs = ngx_pcalloc(cf->pool, stport->naddrs * sizeof(ngx_stream_in_addr_t)); @@ -568,7 +565,7 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx for (i = 0; i < stport->naddrs; i++) { - sin = &addr[i].opt.sockaddr.sockaddr_in; + sin = (struct sockaddr_in *) addr[i].opt.sockaddr; addrs[i].addr = sin->sin_addr.s_addr; addrs[i].conf.ctx = addr[i].opt.ctx; @@ -576,19 +573,7 @@ ngx_stream_add_addrs(ngx_conf_t *cf, ngx addrs[i].conf.ssl = addr[i].opt.ssl; #endif addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs[i].conf.addr_text.len = len; - addrs[i].conf.addr_text.data = p; + addrs[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; @@ -601,12 +586,9 @@ static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr) { - u_char *p; - size_t len; ngx_uint_t i; struct sockaddr_in6 *sin6; ngx_stream_in6_addr_t *addrs6; - u_char buf[NGX_SOCKADDR_STRLEN]; stport->addrs = ngx_pcalloc(cf->pool, stport->naddrs * sizeof(ngx_stream_in6_addr_t)); @@ -618,7 +600,7 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ng for (i = 0; i < stport->naddrs; i++) { - sin6 = &addr[i].opt.sockaddr.sockaddr_in6; + sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr; addrs6[i].addr6 = sin6->sin6_addr; addrs6[i].conf.ctx = addr[i].opt.ctx; @@ -626,19 +608,7 @@ ngx_stream_add_addrs6(ngx_conf_t *cf, ng addrs6[i].conf.ssl = addr[i].opt.ssl; #endif addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol; - - len = ngx_sock_ntop(&addr[i].opt.sockaddr.sockaddr, addr[i].opt.socklen, - buf, NGX_SOCKADDR_STRLEN, 1); - - p = ngx_pnalloc(cf->pool, len); - if (p == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(p, buf, len); - - addrs6[i].conf.addr_text.len = len; - addrs6[i].conf.addr_text.data = p; + addrs6[i].conf.addr_text = addr[i].opt.addr_text; } return NGX_OK; diff --git a/src/stream/ngx_stream.h b/src/stream/ngx_stream.h --- a/src/stream/ngx_stream.h +++ b/src/stream/ngx_stream.h @@ -41,8 +41,9 @@ typedef struct { typedef struct { - ngx_sockaddr_t sockaddr; + struct sockaddr *sockaddr; socklen_t socklen; + ngx_str_t addr_text; /* server ctx */ ngx_stream_conf_ctx_t *ctx; diff --git a/src/stream/ngx_stream_core_module.c b/src/stream/ngx_stream_core_module.c --- a/src/stream/ngx_stream_core_module.c +++ b/src/stream/ngx_stream_core_module.c @@ -577,7 +577,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n ngx_str_t *value, size; ngx_url_t u; - ngx_uint_t i, backlog; + ngx_uint_t i, n, backlog; ngx_stream_listen_t *ls, *als; ngx_stream_core_main_conf_t *cmcf; @@ -602,21 +602,17 @@ ngx_stream_core_listen(ngx_conf_t *cf, n cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); - ls = ngx_array_push(&cmcf->listen); + ls = ngx_array_push_n(&cmcf->listen, u.naddrs); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_stream_listen_t)); - ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); - - ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; ls->type = SOCK_STREAM; - ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if (NGX_HAVE_INET6) @@ -688,35 +684,20 @@ ngx_stream_core_listen(ngx_conf_t *cf, n if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) - size_t len; - u_char buf[NGX_SOCKADDR_STRLEN]; - - if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { - - if (ngx_strcmp(&value[i].data[10], "n") == 0) { - ls->ipv6only = 1; + if (ngx_strcmp(&value[i].data[10], "n") == 0) { + ls->ipv6only = 1; - } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { - ls->ipv6only = 0; - - } else { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid ipv6only flags \"%s\"", - &value[i].data[9]); - return NGX_CONF_ERROR; - } - - ls->bind = 1; + } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { + ls->ipv6only = 0; } else { - len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, - NGX_SOCKADDR_STRLEN, 1); - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "ipv6only is not supported " - "on addr \"%*s\", ignored", len, buf); + "invalid ipv6only flags \"%s\"", + &value[i].data[9]); + return NGX_CONF_ERROR; } + ls->bind = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -882,21 +863,31 @@ ngx_stream_core_listen(ngx_conf_t *cf, n als = cmcf->listen.elts; - for (i = 0; i < cmcf->listen.nelts - 1; i++) { - if (ls->type != als[i].type) { - continue; - } + for (n = 0; n < u.naddrs; n++) { + ls[n] = ls[0]; + + ls[n].sockaddr = u.addrs[n].sockaddr; + ls[n].socklen = u.addrs[n].socklen; + ls[n].addr_text = u.addrs[n].name; + ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); + + for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { + if (ls[n].type != als[i].type) { + continue; + } - if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen, - &ls->sockaddr.sockaddr, ls->socklen, 1) - != NGX_OK) - { - continue; + if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, + ls[n].sockaddr, ls[n].socklen, 1) + != NGX_OK) + { + continue; + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate \"%V\" address and port pair", + &ls[n].addr_text); + return NGX_CONF_ERROR; } - - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "duplicate \"%V\" address and port pair", &u.url); - return NGX_CONF_ERROR; } return NGX_CONF_OK;