<div>Two files are affected "ngx_inet.c" and "ngx_inet.h". I remove the original "ngx_parse_inet_url" and "ngx_parse_inet6_url" because they have many duplicated code and "ngx_pare_inet_url" this name won't describe what it does comprehensively (it may generate IPv6 too).</div>
<div><br></div><div>So I use "ngx_parse_url" to split the url to "host", "port", "uri" and create a function "ngx_parse_host" to convert host to IP address. Besides, I also change "ngx_inet_resolve_host" to make it accept IPv6.</div>
<div><br></div><div>At last I add a function "ngx_inet_sock_addr" to convert "ipv4:port" and "[ipv6]:port" to sockaddr_in and sockaddr_in6.</div><div><br></div><div>The following test has been done to verify the functionality of url parse (Here ip = ipv4 and ipv6).</div>
<div><br></div><div>1. only port ==> only accept IPv4</div><div>2. *:port ==> same as 1</div><div>3. [::]:port ==> accept both ipv4 and ipv6 if not set ipv6only=on</div><div>4. ip:port</div><div>5. ip:port/uri</div>
<div>6. ip:port/uri?arg</div><div>7: ip/uri?arg</div><div>8. text:port (text url can be resolved to 1 IPv6 addr)</div><div>9. text:port (text url can be resolved to many addr, some are IPv4 and some IPv6. The url->sockaddr always be the first IP address) </div>
<div><br></div><div><meta charset="utf-8">--------------------------------------------------------ngx_inet.c-------------------------------------------</div><div><br></div><div>--- nginx-0.9.3/src/core/ngx_inet.c<span style="white-space:pre-wrap">        </span>2009-12-07 07:13:46.000000000 -0800</div>
<div>+++ /home/speedfirst/p4/zimbra/main/ThirdParty/nginx/nginx-0.9-zimbra/src/core/ngx_inet.c<span style="white-space:pre-wrap">        </span>2011-02-28 02:17:31.187902103 -0800</div>
<div>@@ -9,8 +9,7 @@</div><div> </div><div> </div><div> static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);</div><div>-static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);</div><div>
-static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);</div><div>+static ngx_int_t ngx_parse_host(ngx_pool_t *pool, ngx_url_t *u);</div><div> </div><div> </div><div> in_addr_t</div><div>@@ -446,7 +445,6 @@</div>
<div> }</div><div> }</div><div> </div><div>-</div><div> ngx_int_t</div><div> ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)</div><div> {</div><div>@@ -506,11 +504,18 @@</div><div> return NGX_OK;</div>
<div> }</div><div> </div><div>-</div><div> ngx_int_t</div><div> ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)</div><div> {</div><div>- u_char *p;</div><div>+ u_char *p, *host, *port, *last, *uri, *args;</div><div>
+ size_t len;</div><div>+ ngx_int_t n;</div><div>+ struct sockaddr_in *sin;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct sockaddr_in6 *sin6;</div><div>+ ngx_flag_t ipv6 = 0;</div>
<div>+#endif</div><div> </div><div> p = u->url.data;</div><div> </div><div>@@ -523,129 +528,44 @@</div><div> return NGX_ERROR;</div><div> }</div><div> </div><div>- if (p[0] == '[') {</div><div>
- return ngx_parse_inet6_url(pool, u);</div><div>- }</div><div>+ host = u->url.data;</div><div> </div><div>- return ngx_parse_inet_url(pool, u);</div><div>-}</div><div>+ last = host + u->url.len;</div>
<div> </div><div>+ len = 0;</div><div> </div><div>-static ngx_int_t</div><div>-ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)</div><div>-{</div><div>-#if (NGX_HAVE_UNIX_DOMAIN)</div><div>- u_char *path, *uri, *last;</div>
<div>- size_t len;</div><div>- struct sockaddr_un *saun;</div><div>-</div><div>- len = u->url.len;</div><div>- path = u->url.data;</div><div>+#if (NGX_HAVE_INET6)</div><div>+ if (host[0] == '[') {</div>
<div> </div><div>- path += 5;</div><div>- len -= 5;</div><div>+ ipv6 = 1;</div><div> </div><div>- if (u->uri_part) {</div><div>+ host = u->url.data + 1;</div><div> </div><div>- last = path + len;</div>
<div>- uri = ngx_strlchr(path, last, ':');</div><div>+ p = ngx_strlchr(host, last, ']');</div><div> </div><div>- if (uri) {</div><div>- len = uri - path;</div><div>- uri++;</div>
<div>- u->uri.len = last - uri;</div><div>- u->uri.data = uri;</div><div>+ if (p == NULL) {</div><div>+ u->err = "invalid host";</div><div>+ return NGX_ERROR;</div>
<div> }</div><div>- }</div><div>-</div><div>- if (len == 0) {</div><div>- u->err = "no path in the unix domain socket";</div><div>- return NGX_ERROR;</div><div>- }</div><div>-</div>
<div>- u->host.len = len++;</div><div>- u->host.data = path;</div><div>-</div><div>- if (len > sizeof(saun->sun_path)) {</div><div>- u->err = "too long path in the unix domain socket";</div>
<div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div>- u->socklen = sizeof(struct sockaddr_un);</div><div>- saun = (struct sockaddr_un *) &u->sockaddr;</div><div>- saun->sun_family = AF_UNIX;</div>
<div>- (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);</div><div> </div><div>- u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));</div><div>- if (u->addrs == NULL) {</div><div>- return NGX_ERROR;</div>
<div>- }</div><div>+ u->family = AF_INET6;</div><div> </div><div>- saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));</div><div>- if (saun == NULL) {</div><div>- return NGX_ERROR;</div><div> }</div>
<div>-</div><div>- u->family = AF_UNIX;</div><div>- u->naddrs = 1;</div><div>-</div><div>- saun->sun_family = AF_UNIX;</div><div>- (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);</div><div>
-</div><div>- u->addrs[0].sockaddr = (struct sockaddr *) saun;</div><div>- u->addrs[0].socklen = sizeof(struct sockaddr_un);</div><div>- u->addrs[0].name.len = len + 4;</div><div>- u->addrs[0].name.data = u->url.data;</div>
<div>-</div><div>- return NGX_OK;</div><div>-</div><div>-#else</div><div>-</div><div>- u->err = "the unix domain sockets are not supported on this platform";</div><div>-</div><div>- return NGX_ERROR;</div>
<div>-</div><div> #endif</div><div>-}</div><div>-</div><div>-</div><div>-static ngx_int_t</div><div>-ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)</div><div>-{</div><div>- u_char *p, *host, *port, *last, *uri, *args;</div>
<div>- size_t len;</div><div>- ngx_int_t n;</div><div>- struct hostent *h;</div><div>- struct sockaddr_in *sin;</div><div>-</div><div>- u->socklen = sizeof(struct sockaddr_in);</div>
<div>- sin = (struct sockaddr_in *) &u->sockaddr;</div><div>- sin->sin_family = AF_INET;</div><div>-</div><div>- u->family = AF_INET;</div><div>-</div><div>- host = u->url.data;</div><div>-</div>
<div>- last = host + u->url.len;</div><div>-</div><div>- port = ngx_strlchr(host, last, ':');</div><div> </div><div>- uri = ngx_strlchr(host, last, '/');</div><div>+ port = ngx_strlchr(p, last, ':');</div>
<div> </div><div>- args = ngx_strlchr(host, last, '?');</div><div>+ uri = ngx_strlchr(p, last, '/');</div><div> </div><div>- if (args) {</div><div>- if (uri == NULL) {</div><div>- uri = args;</div>
<div>+ args = ngx_strlchr(p, last, '?');</div><div> </div><div>- } else if (args < uri) {</div><div>- uri = args;</div><div>- }</div><div>+ if (args && (uri == NULL || args < uri)) {</div>
<div>+ uri = args;</div><div> }</div><div> </div><div> if (uri) {</div><div> if (u->listen || !u->uri_part) {</div><div>- u->err = "invalid host";</div><div>+ u->err = "invalid url to listen";</div>
<div> return NGX_ERROR;</div><div> }</div><div> </div><div>@@ -677,54 +597,61 @@</div><div> }</div><div> </div><div> u->port = (in_port_t) n;</div><div>- sin->sin_port = htons((in_port_t) n);</div>
<div>-</div><div> u->port_text.len = len;</div><div> u->port_text.data = port;</div><div> </div><div> last = port - 1;</div><div> </div><div> } else {</div><div>- if (uri == NULL) {</div>
<div>-</div><div>- if (u->listen) {</div><div>-</div><div>- /* test value as port only */</div><div>+ if (uri == NULL && u->listen) {</div><div>+ /* test value as port only */</div>
<div> </div><div>- n = ngx_atoi(host, last - host);</div><div>+ n = ngx_atoi(u->url.data, u->url.len);</div><div> </div><div>- if (n != NGX_ERROR) {</div><div>-</div><div>- if (n < 1 || n > 65536) {</div>
<div>- u->err = "invalid port";</div><div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div>- u->port = (in_port_t) n;</div>
<div>- sin->sin_port = htons((in_port_t) n);</div><div>+ if (n < 1 || n > 65536) {</div><div>+ u->err = "invalid port";</div><div>+ return NGX_ERROR;</div>
<div>+ }</div><div> </div><div>- u->port_text.len = last - host;</div><div>- u->port_text.data = host;</div><div>+ u->family = AF_INET;</div><div>+ u->port = (in_port_t) n;</div>
<div>+ sin = (struct sockaddr_in *)u->sockaddr;</div><div>+ sin->sin_family = AF_INET;</div><div>+ sin->sin_addr.s_addr = INADDR_ANY;</div><div>+ sin->sin_port = htons((in_port_t) n);</div>
<div>+ u->port_text.len = len;</div><div>+ u->port_text.data = port;</div><div>+ u->socklen = sizeof (struct sockaddr_in);</div><div>+ u->wildcard = 1;</div><div> </div>
<div>- u->wildcard = 1;</div><div>+ return NGX_OK;</div><div> </div><div>- return NGX_OK;</div><div>- }</div><div>- }</div><div>+ } else {</div>
<div>+ u->no_port = 1;</div><div> }</div><div>+ }</div><div> </div><div>- u->no_port = 1;</div><div>+#if (NGX_HAVE_INET6)</div><div>+ if (ipv6) {</div><div>+ if (*(last - 1) == ']' && last > host) {</div>
<div>+ last--;</div><div>+ } else {</div><div>+ u->err = "invalid host";</div><div>+ return NGX_ERROR;</div><div>+ }</div><div> }</div><div>+#endif</div><div>
</div><div> len = last - host;</div><div> </div><div>- if (len == 0) {</div><div>- u->err = "no host";</div><div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div> if (len == 1 && *host == '*') {</div>
<div> len = 0;</div><div>+ u->family = AF_INET;</div><div>+ u->socklen = sizeof (struct sockaddr_in);</div><div>+ u->wildcard = 1;</div><div>+ sin = (struct sockaddr_in *)u->sockaddr;</div>
<div>+ sin->sin_family = AF_INET;</div><div>+ sin->sin_addr.s_addr = INADDR_ANY;</div><div> }</div><div> </div><div> u->host.len = len;</div><div>@@ -734,41 +661,26 @@</div><div> return NGX_OK;</div>
<div> }</div><div> </div><div>- if (len) {</div><div>- sin->sin_addr.s_addr = ngx_inet_addr(host, len);</div><div>-</div><div>- if (sin->sin_addr.s_addr == INADDR_NONE) {</div><div>- p = ngx_alloc(++len, pool->log);</div>
<div>- if (p == NULL) {</div><div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div>- (void) ngx_cpystrn(p, host, len);</div><div>-</div><div>- h = gethostbyname((const char *) p);</div>
<div>-</div><div>- ngx_free(p);</div><div>-</div><div>- if (h == NULL || h->h_addr_list[0] == NULL) {</div><div>- u->err = "host not found";</div><div>- return NGX_ERROR;</div>
<div>- }</div><div>-</div><div>- sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);</div><div>- }</div><div>-</div><div>- if (sin->sin_addr.s_addr == INADDR_ANY) {</div>
<div>- u->wildcard = 1;</div><div>- }</div><div>-</div><div>- } else {</div><div>- sin->sin_addr.s_addr = INADDR_ANY;</div><div>- u->wildcard = 1;</div><div>+ if(u->host.len > 0 && ngx_parse_host(pool, u) == NGX_ERROR) {</div>
<div>+ u->err = "invalid host";</div><div>+ return NGX_ERROR;</div><div> }</div><div> </div><div> if (u->no_port) {</div><div> u->port = u->default_port;</div><div>- sin->sin_port = htons(u->default_port);</div>
<div>+ }</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ if (u->family == AF_INET6) {</div><div>+ sin6 = (struct sockaddr_in6 *)u->sockaddr;</div><div>+ sin6->sin6_port = htons (u->port);</div>
<div>+</div><div>+ }</div><div>+ else</div><div>+#endif</div><div>+ {</div><div>+ sin = (struct sockaddr_in *)u->sockaddr;</div><div>+ sin->sin_port = htons (u->port);</div><div> }</div>
<div> </div><div> if (u->listen) {</div><div>@@ -784,114 +696,199 @@</div><div> </div><div> </div><div> static ngx_int_t</div><div>-ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)</div><div>+ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)</div>
<div> {</div><div>-#if (NGX_HAVE_INET6)</div><div>- u_char *p, *host, *port, *last, *uri;</div><div>- size_t len;</div><div>- ngx_int_t n;</div><div>- struct sockaddr_in6 *sin6;</div>
<div>-</div><div>- u->socklen = sizeof(struct sockaddr_in6);</div><div>- sin6 = (struct sockaddr_in6 *) &u->sockaddr;</div><div>- sin6->sin6_family = AF_INET6;</div><div>-</div><div>- host = u->url.data + 1;</div>
<div>-</div><div>- last = u->url.data + u->url.len;</div><div>-</div><div>- p = ngx_strlchr(host, last, ']');</div><div>+#if (NGX_HAVE_UNIX_DOMAIN)</div><div>+ u_char *path, *uri, *last;</div>
<div>+ size_t len;</div><div>+ struct sockaddr_un *saun;</div><div> </div><div>- if (p == NULL) {</div><div>- u->err = "invalid host";</div><div>- return NGX_ERROR;</div>
<div>- }</div><div>+ len = u->url.len;</div><div>+ path = u->url.data;</div><div> </div><div>- if (last - p) {</div><div>+ path += 5;</div><div>+ len -= 5;</div><div> </div><div>- port = p + 1;</div>
<div>+ if (u->uri_part) {</div><div> </div><div>- uri = ngx_strlchr(port, last, '/');</div><div>+ last = path + len;</div><div>+ uri = ngx_strlchr(path, last, ':');</div><div> </div>
<div> if (uri) {</div><div>- if (u->listen || !u->uri_part) {</div><div>- u->err = "invalid host";</div><div>- return NGX_ERROR;</div><div>- }</div>
<div>-</div><div>+ len = uri - path;</div><div>+ uri++;</div><div> u->uri.len = last - uri;</div><div> u->uri.data = uri;</div><div> }</div><div>+ }</div><div>
</div><div>- if (*port == ':') {</div><div>- port++;</div><div>-</div><div>- len = last - port;</div><div>-</div><div>- if (len == 0) {</div><div>- u->err = "invalid port";</div>
<div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div>- n = ngx_atoi(port, len);</div><div>-</div><div>- if (n < 1 || n > 65536) {</div><div>- u->err = "invalid port";</div>
<div>- return NGX_ERROR;</div><div>- }</div><div>-</div><div>- u->port = (in_port_t) n;</div><div>- sin6->sin6_port = htons((in_port_t) n);</div><div>-</div><div>- u->port_text.len = len;</div>
<div>- u->port_text.data = port;</div><div>-</div><div>- } else {</div><div>- u->no_port = 1;</div><div>- }</div><div>+ if (len == 0) {</div><div>+ u->err = "no path in the unix domain socket";</div>
<div>+ return NGX_ERROR;</div><div> }</div><div> </div><div>- len = p - host;</div><div>+ u->host.len = len++;</div><div>+ u->host.data = path;</div><div> </div><div>- if (len == 0) {</div><div>
- u->err = "no host";</div><div>+ if (len > sizeof(saun->sun_path)) {</div><div>+ u->err = "too long path in the unix domain socket";</div><div> return NGX_ERROR;</div>
<div> }</div><div> </div><div>- u->host.len = len;</div><div>- u->host.data = host;</div><div>+ u->socklen = sizeof(struct sockaddr_un);</div><div>+ saun = (struct sockaddr_un *) &u->sockaddr;</div>
<div>+ saun->sun_family = AF_UNIX;</div><div>+ (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);</div><div> </div><div>- if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {</div>
<div>
- u->err = "invalid IPv6 address";</div><div>+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));</div><div>+ if (u->addrs == NULL) {</div><div> return NGX_ERROR;</div><div> }</div>
<div> </div><div>- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {</div><div>- u->wildcard = 1;</div><div>+ saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));</div><div>+ if (saun == NULL) {</div>
<div>+ return NGX_ERROR;</div><div> }</div><div> </div><div>- u->family = AF_INET6;</div><div>+ u->family = AF_UNIX;</div><div>+ u->naddrs = 1;</div><div> </div><div>- if (u->no_resolve) {</div>
<div>- return NGX_OK;</div><div>- }</div><div>+ saun->sun_family = AF_UNIX;</div><div>+ (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);</div><div> </div><div>- if (u->no_port) {</div>
<div>- u->port = u->default_port;</div><div>- sin6->sin6_port = htons(u->default_port);</div><div>- }</div><div>+ u->addrs[0].sockaddr = (struct sockaddr *) saun;</div><div>+ u->addrs[0].socklen = sizeof(struct sockaddr_un);</div>
<div>+ u->addrs[0].name.len = len + 4;</div><div>+ u->addrs[0].name.data = u->url.data;</div><div> </div><div> return NGX_OK;</div><div> </div><div> #else</div><div> </div><div>- u->err = "the INET6 sockets are not supported on this platform";</div>
<div>+ u->err = "the unix domain sockets are not supported on this platform";</div><div> </div><div> return NGX_ERROR;</div><div> </div><div> #endif</div><div> }</div><div> </div><div>+static ngx_int_t</div>
<div>+ngx_parse_host(ngx_pool_t *pool, ngx_url_t *u) {</div><div>+ u_char *p;</div><div>+ ngx_uint_t family, n;</div><div>+ in_addr_t inaddr;</div><div>+ struct sockaddr_in *sin;</div>
<div>+ struct addrinfo hints, *addrinfo;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct in6_addr inaddr6;</div><div>+ struct sockaddr_in6 *sin6;</div><div>+</div><div>+ if (u->family == AF_INET6) {</div>
<div>+ /* u->family has been set to AF_INET6 means the host</div><div>+ * to be parsed should be IPv6 address so no need to parse</div><div>+ * it as IPv4 or resolve host</div><div>+ */</div>
<div>+ ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));</div><div>+ if (ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) == NGX_OK) {</div><div>+ family = AF_INET6;</div><div>+ goto done;</div>
<div>+ } else {</div><div>+ u->err = "invalid host";</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+ }</div><div>+#endif</div><div>+</div><div>+ inaddr = ngx_inet_addr(u->host.data, u->host.len);</div>
<div>+</div><div>+ if (inaddr != INADDR_NONE) {</div><div>+ family = AF_INET;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ } else if (ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) == NGX_OK) {</div>
<div>+ family = AF_INET6;</div><div>+</div><div>+#endif</div><div>+ } else {</div><div>+ /* resolve the IP address through host name</div><div>+ only the first IP address will be used */</div><div>
+ p = ngx_alloc(u->host.len + 1, pool->log);</div><div>+ if (p == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+ ngx_cpystrn(p, u->host.data, u->host.len + 1);</div>
<div>+</div><div>+ ngx_memzero (&hints, sizeof (struct addrinfo));</div><div>+</div><div>+ if (u->listen) {</div><div>+ hints.ai_flags = AI_PASSIVE;</div><div>+ } else {</div><div>+ hints.ai_flags = AI_CANONNAME;</div>
<div>+ }</div><div>+</div><div>+ hints.ai_protocol = IPPROTO_TCP;</div><div>+</div><div>+ n = getaddrinfo((const char *) p,</div><div>+ NULL, &hints, &addrinfo);</div><div>+</div><div>
+ ngx_free (p);</div><div>+</div><div>+ if (n != NGX_OK) {</div><div>+ u->err = "error in host resolve";</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>
+ if (addrinfo->ai_family == AF_INET) {</div><div>+ family = AF_INET;</div><div>+ inaddr = ((struct sockaddr_in *) addrinfo->ai_addr)->sin_addr.s_addr;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div>
<div>+ } else if (addrinfo->ai_family == AF_INET6) {</div><div>+ family = AF_INET6;</div><div>+ inaddr6 = ((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_addr;</div><div>+</div><div>+#endif</div>
<div>+ } else {</div><div>+ u->err = "unknown address family";</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+ }</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>
+ done:</div><div>+#endif</div><div>+</div><div>+ switch (family) {</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ case AF_INET6:</div><div>+ sin6 = (struct sockaddr_in6 *) u->sockaddr;</div><div>
+ sin6->sin6_family = AF_INET6;</div>
<div>+ u->family = AF_INET6;</div><div>+ u->socklen = sizeof (struct sockaddr_in6);</div><div>+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);</div><div>+</div><div>+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {</div>
<div>+ u->wildcard = 1;</div><div>+ }</div><div>+ break;</div><div>+#endif</div><div>+</div><div>+ default: /* AF_INET */</div><div>+ sin = (struct sockaddr_in *) u->sockaddr;</div><div>
+ sin->sin_family = AF_INET;</div><div>+ u->family = AF_INET;</div><div>+ u->socklen = sizeof (struct sockaddr_in);</div><div>+ sin->sin_addr.s_addr = inaddr;</div><div>+ if (sin->sin_addr.s_addr == INADDR_ANY) {</div>
<div>+ u->wildcard = 1;</div><div>+ }</div><div>+ break;</div><div>+ }</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div> </div><div> ngx_int_t</div><div> ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)</div>
<div>@@ -899,52 +896,138 @@</div><div> u_char *p, *host;</div><div> size_t len;</div><div> in_port_t port;</div><div>- in_addr_t in_addr;</div><div>- ngx_uint_t i;</div>
<div>- struct hostent *h;</div><div>+ in_addr_t inaddr;</div><div>+ ngx_uint_t i, n;</div><div>+ struct addrinfo hints, *addrinfo, *item;</div><div> struct sockaddr_in *sin;</div>
<div> </div><div>- /* AF_INET only */</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct in6_addr inaddr6;</div><div>+ struct sockaddr_in6 *sin6;</div><div>+</div><div>+ /*</div><div>+ * prevent MSVC8 waring:</div>
<div>+ * potentially uninitialized local variable 'inaddr6' used</div><div>+ */</div><div>+ ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));</div><div>+#endif</div><div> </div><div> port = htons(u->port);</div>
<div> </div><div>- in_addr = ngx_inet_addr(u->host.data, u->host.len);</div><div>+ inaddr = ngx_inet_addr(u->host.data, u->host.len);</div><div> </div><div>- if (in_addr == INADDR_NONE) {</div><div>- host = ngx_alloc(u->host.len + 1, pool->log);</div>
<div>- if (host == NULL) {</div><div>+ if (inaddr != INADDR_NONE) {</div><div>+ /* MP: ngx_shared_palloc() */</div><div>+</div><div>+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));</div><div>
+ if (u->addrs == NULL) {</div><div> return NGX_ERROR;</div><div> }</div><div> </div><div>- (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);</div><div>+ sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));</div>
<div>+ if (sin == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div> </div><div>- h = gethostbyname((char *) host);</div><div>+ u->naddrs = 1;</div><div> </div><div>- ngx_free(host);</div>
<div>+ sin->sin_family = AF_INET;</div><div>+ sin->sin_port = port;</div><div>+ sin->sin_addr.s_addr = inaddr;</div><div> </div><div>- if (h == NULL || h->h_addr_list[0] == NULL) {</div>
<div>- u->err = "host not found";</div><div>+ u->addrs[0].sockaddr = (struct sockaddr *) sin;</div><div>+ u->addrs[0].socklen = sizeof(struct sockaddr_in);</div><div>+</div><div>
+ p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);</div><div>+ if (p == NULL) {</div><div> return NGX_ERROR;</div><div> }</div><div> </div><div>- if (u->one_addr == 0) {</div>
<div>- for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }</div><div>+ u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",</div><div>+ &u->host, ntohs(port)) - p;</div>
<div>+ u->addrs[0].name.data = p;</div><div> </div><div>- } else {</div><div>- i = 1;</div><div>+ return NGX_OK;</div><div>+ }</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div><div>+ if(ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) == NGX_OK) {</div>
<div>+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));</div><div>+ if (u->addrs == NULL) {</div><div>+ return NGX_ERROR;</div><div> }</div><div> </div><div>- /* MP: ngx_shared_palloc() */</div>
<div>+ sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));</div><div>+ if (sin6 == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div> </div><div>- u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));</div>
<div>- if (u->addrs == NULL) {</div><div>+ u->naddrs = 1;</div><div>+</div><div>+ sin6->sin6_family = AF_INET6;</div><div>+ sin6->sin6_port = port;</div><div>+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);</div>
<div>+ u->addrs[0].sockaddr = (struct sockaddr *) sin6;</div><div>+ u->addrs[0].socklen = sizeof(struct sockaddr_in6);</div><div>+</div><div>+ p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);</div>
<div>+ if (p == NULL) {</div><div> return NGX_ERROR;</div><div> }</div><div> </div><div>- u->naddrs = i;</div><div>+ u->addrs[0].name.len = ngx_sprintf(p, "[%V]:%d",</div>
<div>+ &u->host, ntohs(port)) - p;</div><div>+ u->addrs[0].name.data = p;</div><div>+</div><div>+ return NGX_OK;</div><div>+ }</div><div>+#endif</div><div>
+</div><div>+ /* resolve all the IP address for this host */</div><div>+ host = ngx_alloc(u->host.len + 1, pool->log);</div><div>+ if (host == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div>
<div>+ ngx_cpystrn(host, u->host.data, u->host.len + 1);</div><div>+</div><div>+ ngx_memzero (&hints, sizeof (struct addrinfo));</div><div>+</div><div>+ /* if the address is for listen, it won't enter this reslove function */</div>
<div>+ hints.ai_flags = AI_CANONNAME;</div><div>+ hints.ai_protocol = IPPROTO_TCP;</div><div>+</div><div>+ n = getaddrinfo((const char *) host,</div><div>+ NULL, &hints, &addrinfo);</div><div>+</div>
<div>+ ngx_free (host);</div><div>+</div><div>+ if (n != NGX_OK) {</div><div>+ u->err = "error in host resolve";</div><div>+ return NGX_ERROR;</div><div>+ }</div><div> </div><div>- for (i = 0; h->h_addr_list[i] != NULL; i++) {</div>
<div>+ i = 0;</div><div> </div><div>+ if (u->one_addr == 0) {</div><div>+ item = addrinfo;</div><div>+ for (i = 0; item != NULL; i++, item = item->ai_next) { /* void */ }</div><div>+</div><div>+ } else {</div>
<div>+ i = 1;</div><div>+ }</div><div>+</div><div>+ /* MP: ngx_shared_palloc() */</div><div>+</div><div>+ u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));</div><div>+ if (u->addrs == NULL) {</div>
<div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ u->naddrs = i;</div><div>+</div><div>+ for (i = 0; i < u->naddrs; i++, addrinfo = addrinfo->ai_next) {</div><div>+</div><div>+ if (addrinfo->ai_family == AF_INET) {</div>
<div> sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));</div><div> if (sin == NULL) {</div><div> return NGX_ERROR;</div><div>@@ -952,55 +1035,140 @@</div><div> </div><div> sin->sin_family = AF_INET;</div>
<div> sin->sin_port = port;</div><div>- sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);</div><div>-</div><div>+ inaddr = ((struct sockaddr_in *) addrinfo->ai_addr)->sin_addr.s_addr;</div>
<div>+ sin->sin_addr.s_addr = inaddr;</div><div> u->addrs[i].sockaddr = (struct sockaddr *) sin;</div><div> u->addrs[i].socklen = sizeof(struct sockaddr_in);</div><div> </div><div>
len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;</div><div>+ p = ngx_pnalloc(pool, len);</div><div>+ if (p == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div>
<div>+</div><div>+ len = ngx_sock_ntop((struct sockaddr *) sin, p, len, sin->sin_port);</div><div>+</div><div>+ u->addrs[i].name.len = len;</div><div>+ u->addrs[i].name.data = p;</div>
<div> </div><div>+#if (NGX_HAVE_INET6)</div><div>+ } else if (addrinfo->ai_family == AF_INET6) {</div><div>+ sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));</div><div>+ if (sin6 == NULL) {</div>
<div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ sin6->sin6_family = AF_INET6;</div><div>+ sin6->sin6_port = port;</div><div>+ inaddr6 = ((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_addr;</div>
<div>+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);</div><div>+ u->addrs[i].sockaddr = (struct sockaddr *) sin6;</div><div>+ u->addrs[i].socklen = sizeof(struct sockaddr_in6);</div>
<div>+</div><div>+ len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;</div><div> p = ngx_pnalloc(pool, len);</div><div> if (p == NULL) {</div><div> return NGX_ERROR;</div>
<div> }</div><div> </div><div>- len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);</div><div>+ len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, sin6->sin6_port);</div><div>
</div>
<div> u->addrs[i].name.len = len;</div><div> u->addrs[i].name.data = p;</div><div>+#endif</div><div>+ } else {</div><div>+ u->err = "unknown address family";</div>
<div>+ return NGX_ERROR;</div><div> }</div><div>+ }</div><div> </div><div>- } else {</div><div>+ return NGX_OK;</div><div>+}</div><div> </div><div>- /* MP: ngx_shared_palloc() */</div><div>
+ngx_int_t</div><div>+ngx_inet_sock_addr (u_char * p, size_t len, struct sockaddr * sockaddr)</div><div>+{</div><div>+ u_char *port, *last;</div><div>+ ngx_int_t n;</div><div>+ struct sockaddr_in *sin;</div>
<div> </div><div>- u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));</div><div>- if (u->addrs == NULL) {</div><div>+#if (NGX_HAVE_INET6)</div><div>+ struct sockaddr_in6 *sin6;</div><div>+ u_char *q;</div>
<div>+#endif</div><div>+</div><div>+ if (len == 0) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ last = p + len;</div><div>+</div><div>+ port = NULL;</div><div>+</div><div>+#if (NGX_HAVE_INET6)</div>
<div>+</div><div>+ if (*p == '[') {</div><div>+</div><div>+ p++;</div><div>+</div><div>+ q = ngx_strlchr(p, last, ']');</div><div>+</div><div>+ if (q == NULL) {</div><div> return NGX_ERROR;</div>
<div> }</div><div> </div><div>- sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));</div><div>- if (sin == NULL) {</div><div>+ if (q < last - 2 && *(q + 1) == ':') {</div>
<div>
+ port = q + 2;</div><div>+ } else {</div><div> return NGX_ERROR;</div><div> }</div><div> </div><div>- u->naddrs = 1;</div><div>+ sin6 = (struct sockaddr_in6 *)sockaddr;</div>
<div>+</div><div>+ sin6->sin6_family = AF_INET6;</div><div>+</div><div>+ if (ngx_inet6_addr(p, q - p, sin6->sin6_addr.s6_addr) == NGX_ERROR) {</div><div>+ return NGX_ERROR;</div><div>+ }</div>
<div>+</div><div>+ n = ngx_atoi(port, last - port);</div><div>+</div><div>+ if (n == NGX_ERROR || n < 1 || n > 65535) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>
+ sin6->sin6_port = htons(n);</div><div>+</div><div>+ }</div><div>+ else</div><div>+#endif</div><div>+ {</div><div>+ port = ngx_strlchr(p, last, ':');</div><div>+</div><div>+ if (port == NULL) {</div>
<div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ sin = (struct sockaddr_in *)sockaddr;</div><div> </div><div> sin->sin_family = AF_INET;</div><div>- sin->sin_port = port;</div>
<div>- sin->sin_addr.s_addr = in_addr;</div><div> </div><div>- u->addrs[0].sockaddr = (struct sockaddr *) sin;</div><div>- u->addrs[0].socklen = sizeof(struct sockaddr_in);</div><div>+ sin->sin_addr.s_addr = ngx_inet_addr (p, port - p);</div>
<div> </div><div>- p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);</div><div>- if (p == NULL) {</div><div>+ if (sin->sin_addr.s_addr == INADDR_NONE) {</div><div> return NGX_ERROR;</div>
<div> }</div><div> </div><div>- u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",</div><div>- &u->host, ntohs(port)) - p;</div><div>- u->addrs[0].name.data = p;</div>
<div>+ port++;</div><div>+</div><div>+ n = ngx_atoi(port, last - port);</div><div>+</div><div>+ if (n == NGX_ERROR || n < 1 || n > 65535) {</div><div>+ return NGX_ERROR;</div><div>+ }</div>
<div>+</div><div>+ sin->sin_port = htons(n);</div><div>+</div><div> }</div><div> </div><div> return NGX_OK;</div><div>--------------------------------------------------------ngx_inet.h-------------------------------------------</div>
<div><br></div><div><div>--- nginx-0.9.3/src/core/ngx_inet.h<span style="white-space:pre-wrap">        </span>2009-11-03 04:44:55.000000000 -0800</div><div>+++ /home/speedfirst/p4/zimbra/main/ThirdParty/nginx/nginx-0.9-zimbra/src/core/ngx_inet.h<span style="white-space:pre-wrap">        </span>2011-02-25 01:45:37.133302528 -0800</div>
<div>@@ -108,6 +108,8 @@</div><div> #endif</div><div> size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,</div><div> ngx_uint_t port);</div><div>+ngx_int_t ngx_inet_sock_addr (u_char * p, size_t len,</div>
<div>+ struct sockaddr * sockaddr);</div><div> size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);</div><div> ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);</div><div> ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,</div>
</div>