Mercurial > hg > nginx
diff src/core/ngx_inet.c @ 7478:4f9b72a229c1
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.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 15 Mar 2019 15:45:56 +0300 |
parents | 935b1902a7dd |
children | 8be88b22fe81 |
line wrap: on
line diff
--- a/src/core/ngx_inet.c Sat Mar 09 03:03:56 2019 +0300 +++ b/src/core/ngx_inet.c Fri Mar 15 15:45:56 2019 +0300 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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_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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ #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 @@ 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; +}