[PATCH] parse URL to ipv6
Speed First
speedfirst at gmail.com
Tue Mar 1 15:22:59 MSK 2011
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).
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.
At last I add a function "ngx_inet_sock_addr" to convert "ipv4:port" and
"[ipv6]:port" to sockaddr_in and sockaddr_in6.
The following test has been done to verify the functionality of url parse
(Here ip = ipv4 and ipv6).
1. only port ==> only accept IPv4
2. *:port ==> same as 1
3. [::]:port ==> accept both ipv4 and ipv6 if not set ipv6only=on
4. ip:port
5. ip:port/uri
6. ip:port/uri?arg
7: ip/uri?arg
8. text:port (text url can be resolved to 1 IPv6 addr)
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)
--------------------------------------------------------ngx_inet.c-------------------------------------------
--- nginx-0.9.3/src/core/ngx_inet.c 2009-12-07 07:13:46.000000000 -0800
+++
/home/speedfirst/p4/zimbra/main/ThirdParty/nginx/nginx-0.9-zimbra/src/core/ngx_inet.c
2011-02-28
02:17:31.187902103 -0800
@@ -9,8 +9,7 @@
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_parse_host(ngx_pool_t *pool, ngx_url_t *u);
in_addr_t
@@ -446,7 +445,6 @@
}
}
-
ngx_int_t
ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t
len)
{
@@ -506,11 +504,18 @@
return NGX_OK;
}
-
ngx_int_t
ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
{
- u_char *p;
+ 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;
+ ngx_flag_t ipv6 = 0;
+#endif
p = u->url.data;
@@ -523,129 +528,44 @@
return NGX_ERROR;
}
- if (p[0] == '[') {
- return ngx_parse_inet6_url(pool, u);
- }
+ host = u->url.data;
- return ngx_parse_inet_url(pool, u);
-}
+ last = host + u->url.len;
+ len = 0;
-static ngx_int_t
-ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
-{
-#if (NGX_HAVE_UNIX_DOMAIN)
- u_char *path, *uri, *last;
- size_t len;
- struct sockaddr_un *saun;
-
- len = u->url.len;
- path = u->url.data;
+#if (NGX_HAVE_INET6)
+ if (host[0] == '[') {
- path += 5;
- len -= 5;
+ ipv6 = 1;
- if (u->uri_part) {
+ host = u->url.data + 1;
- last = path + len;
- uri = ngx_strlchr(path, last, ':');
+ p = ngx_strlchr(host, last, ']');
- if (uri) {
- len = uri - path;
- uri++;
- u->uri.len = last - uri;
- u->uri.data = uri;
+ if (p == NULL) {
+ u->err = "invalid host";
+ return NGX_ERROR;
}
- }
-
- if (len == 0) {
- u->err = "no path in the unix domain socket";
- return NGX_ERROR;
- }
-
- u->host.len = len++;
- u->host.data = path;
-
- if (len > sizeof(saun->sun_path)) {
- u->err = "too long path in the unix domain socket";
- return NGX_ERROR;
- }
-
- u->socklen = sizeof(struct sockaddr_un);
- saun = (struct sockaddr_un *) &u->sockaddr;
- saun->sun_family = AF_UNIX;
- (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
- u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
- if (u->addrs == NULL) {
- return NGX_ERROR;
- }
+ u->family = AF_INET6;
- saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
- if (saun == NULL) {
- return NGX_ERROR;
}
-
- u->family = AF_UNIX;
- u->naddrs = 1;
-
- saun->sun_family = AF_UNIX;
- (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
-
- u->addrs[0].sockaddr = (struct sockaddr *) saun;
- u->addrs[0].socklen = sizeof(struct sockaddr_un);
- u->addrs[0].name.len = len + 4;
- u->addrs[0].name.data = u->url.data;
-
- return NGX_OK;
-
-#else
-
- u->err = "the unix domain sockets are not supported on this platform";
-
- return NGX_ERROR;
-
#endif
-}
-
-
-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 hostent *h;
- struct sockaddr_in *sin;
-
- u->socklen = sizeof(struct sockaddr_in);
- sin = (struct sockaddr_in *) &u->sockaddr;
- sin->sin_family = AF_INET;
-
- u->family = AF_INET;
-
- host = u->url.data;
-
- last = host + u->url.len;
-
- port = ngx_strlchr(host, last, ':');
- uri = ngx_strlchr(host, last, '/');
+ port = ngx_strlchr(p, last, ':');
- args = ngx_strlchr(host, last, '?');
+ uri = ngx_strlchr(p, last, '/');
- if (args) {
- if (uri == NULL) {
- uri = args;
+ args = ngx_strlchr(p, last, '?');
- } else if (args < uri) {
- uri = args;
- }
+ if (args && (uri == NULL || args < uri)) {
+ uri = args;
}
if (uri) {
if (u->listen || !u->uri_part) {
- u->err = "invalid host";
+ u->err = "invalid url to listen";
return NGX_ERROR;
}
@@ -677,54 +597,61 @@
}
u->port = (in_port_t) n;
- sin->sin_port = htons((in_port_t) n);
-
u->port_text.len = len;
u->port_text.data = port;
last = port - 1;
} else {
- if (uri == NULL) {
-
- if (u->listen) {
-
- /* test value as port only */
+ if (uri == NULL && u->listen) {
+ /* test value as port only */
- n = ngx_atoi(host, last - host);
+ n = ngx_atoi(u->url.data, u->url.len);
- if (n != NGX_ERROR) {
-
- if (n < 1 || n > 65536) {
- u->err = "invalid port";
- return NGX_ERROR;
- }
-
- u->port = (in_port_t) n;
- sin->sin_port = htons((in_port_t) n);
+ if (n < 1 || n > 65536) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
- u->port_text.len = last - host;
- u->port_text.data = host;
+ u->family = AF_INET;
+ u->port = (in_port_t) n;
+ sin = (struct sockaddr_in *)u->sockaddr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = htons((in_port_t) n);
+ u->port_text.len = len;
+ u->port_text.data = port;
+ u->socklen = sizeof (struct sockaddr_in);
+ u->wildcard = 1;
- u->wildcard = 1;
+ return NGX_OK;
- return NGX_OK;
- }
- }
+ } else {
+ u->no_port = 1;
}
+ }
- u->no_port = 1;
+#if (NGX_HAVE_INET6)
+ if (ipv6) {
+ if (*(last - 1) == ']' && last > host) {
+ last--;
+ } else {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
}
+#endif
len = last - host;
- if (len == 0) {
- u->err = "no host";
- return NGX_ERROR;
- }
-
if (len == 1 && *host == '*') {
len = 0;
+ u->family = AF_INET;
+ u->socklen = sizeof (struct sockaddr_in);
+ u->wildcard = 1;
+ sin = (struct sockaddr_in *)u->sockaddr;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
}
u->host.len = len;
@@ -734,41 +661,26 @@
return NGX_OK;
}
- if (len) {
- sin->sin_addr.s_addr = ngx_inet_addr(host, len);
-
- if (sin->sin_addr.s_addr == INADDR_NONE) {
- p = ngx_alloc(++len, pool->log);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- (void) ngx_cpystrn(p, host, len);
-
- h = gethostbyname((const char *) p);
-
- ngx_free(p);
-
- if (h == NULL || h->h_addr_list[0] == NULL) {
- u->err = "host not found";
- return NGX_ERROR;
- }
-
- sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
- }
-
- if (sin->sin_addr.s_addr == INADDR_ANY) {
- u->wildcard = 1;
- }
-
- } else {
- sin->sin_addr.s_addr = INADDR_ANY;
- u->wildcard = 1;
+ if(u->host.len > 0 && ngx_parse_host(pool, u) == NGX_ERROR) {
+ u->err = "invalid host";
+ return NGX_ERROR;
}
if (u->no_port) {
u->port = u->default_port;
- sin->sin_port = htons(u->default_port);
+ }
+
+#if (NGX_HAVE_INET6)
+ if (u->family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)u->sockaddr;
+ sin6->sin6_port = htons (u->port);
+
+ }
+ else
+#endif
+ {
+ sin = (struct sockaddr_in *)u->sockaddr;
+ sin->sin_port = htons (u->port);
}
if (u->listen) {
@@ -784,114 +696,199 @@
static ngx_int_t
-ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
+ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
{
-#if (NGX_HAVE_INET6)
- u_char *p, *host, *port, *last, *uri;
- size_t len;
- ngx_int_t n;
- struct sockaddr_in6 *sin6;
-
- u->socklen = sizeof(struct sockaddr_in6);
- sin6 = (struct sockaddr_in6 *) &u->sockaddr;
- sin6->sin6_family = AF_INET6;
-
- host = u->url.data + 1;
-
- last = u->url.data + u->url.len;
-
- p = ngx_strlchr(host, last, ']');
+#if (NGX_HAVE_UNIX_DOMAIN)
+ u_char *path, *uri, *last;
+ size_t len;
+ struct sockaddr_un *saun;
- if (p == NULL) {
- u->err = "invalid host";
- return NGX_ERROR;
- }
+ len = u->url.len;
+ path = u->url.data;
- if (last - p) {
+ path += 5;
+ len -= 5;
- port = p + 1;
+ if (u->uri_part) {
- uri = ngx_strlchr(port, last, '/');
+ last = path + len;
+ uri = ngx_strlchr(path, last, ':');
if (uri) {
- if (u->listen || !u->uri_part) {
- u->err = "invalid host";
- return NGX_ERROR;
- }
-
+ len = uri - path;
+ uri++;
u->uri.len = last - uri;
u->uri.data = uri;
}
+ }
- if (*port == ':') {
- port++;
-
- len = last - port;
-
- if (len == 0) {
- u->err = "invalid port";
- return NGX_ERROR;
- }
-
- n = ngx_atoi(port, len);
-
- if (n < 1 || n > 65536) {
- u->err = "invalid port";
- return NGX_ERROR;
- }
-
- u->port = (in_port_t) n;
- sin6->sin6_port = htons((in_port_t) n);
-
- u->port_text.len = len;
- u->port_text.data = port;
-
- } else {
- u->no_port = 1;
- }
+ if (len == 0) {
+ u->err = "no path in the unix domain socket";
+ return NGX_ERROR;
}
- len = p - host;
+ u->host.len = len++;
+ u->host.data = path;
- if (len == 0) {
- u->err = "no host";
+ if (len > sizeof(saun->sun_path)) {
+ u->err = "too long path in the unix domain socket";
return NGX_ERROR;
}
- u->host.len = len;
- u->host.data = host;
+ u->socklen = sizeof(struct sockaddr_un);
+ saun = (struct sockaddr_un *) &u->sockaddr;
+ saun->sun_family = AF_UNIX;
+ (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
- if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
- u->err = "invalid IPv6 address";
+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
return NGX_ERROR;
}
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
- u->wildcard = 1;
+ saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
+ if (saun == NULL) {
+ return NGX_ERROR;
}
- u->family = AF_INET6;
+ u->family = AF_UNIX;
+ u->naddrs = 1;
- if (u->no_resolve) {
- return NGX_OK;
- }
+ saun->sun_family = AF_UNIX;
+ (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
- if (u->no_port) {
- u->port = u->default_port;
- sin6->sin6_port = htons(u->default_port);
- }
+ u->addrs[0].sockaddr = (struct sockaddr *) saun;
+ u->addrs[0].socklen = sizeof(struct sockaddr_un);
+ u->addrs[0].name.len = len + 4;
+ u->addrs[0].name.data = u->url.data;
return NGX_OK;
#else
- u->err = "the INET6 sockets are not supported on this platform";
+ u->err = "the unix domain sockets are not supported on this platform";
return NGX_ERROR;
#endif
}
+static ngx_int_t
+ngx_parse_host(ngx_pool_t *pool, ngx_url_t *u) {
+ u_char *p;
+ ngx_uint_t family, n;
+ in_addr_t inaddr;
+ struct sockaddr_in *sin;
+ struct addrinfo hints, *addrinfo;
+
+#if (NGX_HAVE_INET6)
+ struct in6_addr inaddr6;
+ struct sockaddr_in6 *sin6;
+
+ if (u->family == AF_INET6) {
+ /* u->family has been set to AF_INET6 means the host
+ * to be parsed should be IPv6 address so no need to parse
+ * it as IPv4 or resolve host
+ */
+ ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
+ if (ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) ==
NGX_OK) {
+ family = AF_INET6;
+ goto done;
+ } else {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
+ }
+#endif
+
+ inaddr = ngx_inet_addr(u->host.data, u->host.len);
+
+ if (inaddr != INADDR_NONE) {
+ family = AF_INET;
+
+#if (NGX_HAVE_INET6)
+ } else if (ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) ==
NGX_OK) {
+ family = AF_INET6;
+
+#endif
+ } else {
+ /* resolve the IP address through host name
+ only the first IP address will be used */
+ p = ngx_alloc(u->host.len + 1, pool->log);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_cpystrn(p, u->host.data, u->host.len + 1);
+
+ ngx_memzero (&hints, sizeof (struct addrinfo));
+
+ if (u->listen) {
+ hints.ai_flags = AI_PASSIVE;
+ } else {
+ hints.ai_flags = AI_CANONNAME;
+ }
+
+ hints.ai_protocol = IPPROTO_TCP;
+
+ n = getaddrinfo((const char *) p,
+ NULL, &hints, &addrinfo);
+
+ ngx_free (p);
+
+ if (n != NGX_OK) {
+ u->err = "error in host resolve";
+ return NGX_ERROR;
+ }
+
+ if (addrinfo->ai_family == AF_INET) {
+ family = AF_INET;
+ inaddr = ((struct sockaddr_in *)
addrinfo->ai_addr)->sin_addr.s_addr;
+
+#if (NGX_HAVE_INET6)
+ } else if (addrinfo->ai_family == AF_INET6) {
+ family = AF_INET6;
+ inaddr6 = ((struct sockaddr_in6 *)
addrinfo->ai_addr)->sin6_addr;
+
+#endif
+ } else {
+ u->err = "unknown address family";
+ return NGX_ERROR;
+ }
+ }
+
+#if (NGX_HAVE_INET6)
+ done:
+#endif
+
+ switch (family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) u->sockaddr;
+ sin6->sin6_family = AF_INET6;
+ u->family = AF_INET6;
+ u->socklen = sizeof (struct sockaddr_in6);
+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ u->wildcard = 1;
+ }
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) u->sockaddr;
+ sin->sin_family = AF_INET;
+ u->family = AF_INET;
+ u->socklen = sizeof (struct sockaddr_in);
+ sin->sin_addr.s_addr = inaddr;
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ u->wildcard = 1;
+ }
+ break;
+ }
+
+ return NGX_OK;
+}
ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
@@ -899,52 +896,138 @@
u_char *p, *host;
size_t len;
in_port_t port;
- in_addr_t in_addr;
- ngx_uint_t i;
- struct hostent *h;
+ in_addr_t inaddr;
+ ngx_uint_t i, n;
+ struct addrinfo hints, *addrinfo, *item;
struct sockaddr_in *sin;
- /* AF_INET only */
+#if (NGX_HAVE_INET6)
+ struct in6_addr inaddr6;
+ struct sockaddr_in6 *sin6;
+
+ /*
+ * prevent MSVC8 waring:
+ * potentially uninitialized local variable 'inaddr6' used
+ */
+ ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
+#endif
port = htons(u->port);
- in_addr = ngx_inet_addr(u->host.data, u->host.len);
+ inaddr = ngx_inet_addr(u->host.data, u->host.len);
- if (in_addr == INADDR_NONE) {
- host = ngx_alloc(u->host.len + 1, pool->log);
- if (host == NULL) {
+ if (inaddr != INADDR_NONE) {
+ /* MP: ngx_shared_palloc() */
+
+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
return NGX_ERROR;
}
- (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
+ sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NGX_ERROR;
+ }
- h = gethostbyname((char *) host);
+ u->naddrs = 1;
- ngx_free(host);
+ sin->sin_family = AF_INET;
+ sin->sin_port = port;
+ sin->sin_addr.s_addr = inaddr;
- if (h == NULL || h->h_addr_list[0] == NULL) {
- u->err = "host not found";
+ 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;
}
- if (u->one_addr == 0) {
- for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
+ u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
+ &u->host, ntohs(port)) - p;
+ u->addrs[0].name.data = p;
- } else {
- i = 1;
+ return NGX_OK;
+ }
+
+#if (NGX_HAVE_INET6)
+ if(ngx_inet6_addr(u->host.data, u->host.len, inaddr6.s6_addr) ==
NGX_OK) {
+ u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
+ return NGX_ERROR;
}
- /* MP: ngx_shared_palloc() */
+ sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
+ if (sin6 == NULL) {
+ return NGX_ERROR;
+ }
- u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
- if (u->addrs == NULL) {
+ u->naddrs = 1;
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = port;
+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
+ 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->naddrs = i;
+ u->addrs[0].name.len = ngx_sprintf(p, "[%V]:%d",
+ &u->host, ntohs(port)) - p;
+ u->addrs[0].name.data = p;
+
+ return NGX_OK;
+ }
+#endif
+
+ /* resolve all the IP address for this host */
+ host = ngx_alloc(u->host.len + 1, pool->log);
+ if (host == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_cpystrn(host, u->host.data, u->host.len + 1);
+
+ ngx_memzero (&hints, sizeof (struct addrinfo));
+
+ /* if the address is for listen, it won't enter this reslove function
*/
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ n = getaddrinfo((const char *) host,
+ NULL, &hints, &addrinfo);
+
+ ngx_free (host);
+
+ if (n != NGX_OK) {
+ u->err = "error in host resolve";
+ return NGX_ERROR;
+ }
- for (i = 0; h->h_addr_list[i] != NULL; i++) {
+ i = 0;
+ if (u->one_addr == 0) {
+ item = addrinfo;
+ for (i = 0; item != NULL; i++, item = item->ai_next) { /* void */ }
+
+ } else {
+ i = 1;
+ }
+
+ /* MP: ngx_shared_palloc() */
+
+ u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
+ if (u->addrs == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->naddrs = i;
+
+ for (i = 0; i < u->naddrs; i++, addrinfo = addrinfo->ai_next) {
+
+ if (addrinfo->ai_family == AF_INET) {
sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
if (sin == NULL) {
return NGX_ERROR;
@@ -952,55 +1035,140 @@
sin->sin_family = AF_INET;
sin->sin_port = port;
- sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
-
+ inaddr = ((struct sockaddr_in *)
addrinfo->ai_addr)->sin_addr.s_addr;
+ sin->sin_addr.s_addr = inaddr;
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, p, len,
sin->sin_port);
+
+ u->addrs[i].name.len = len;
+ u->addrs[i].name.data = p;
+#if (NGX_HAVE_INET6)
+ } else if (addrinfo->ai_family == AF_INET6) {
+ sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
+ if (sin6 == NULL) {
+ return NGX_ERROR;
+ }
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = port;
+ inaddr6 = ((struct sockaddr_in6 *)
addrinfo->ai_addr)->sin6_addr;
+ ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
+ u->addrs[i].sockaddr = (struct sockaddr *) sin6;
+ u->addrs[i].socklen = sizeof(struct sockaddr_in6);
+
+ len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
p = ngx_pnalloc(pool, len);
if (p == NULL) {
return NGX_ERROR;
}
- len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
+ len = ngx_sock_ntop((struct sockaddr *) sin6, p, len,
sin6->sin6_port);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
+#endif
+ } else {
+ u->err = "unknown address family";
+ return NGX_ERROR;
}
+ }
- } else {
+ return NGX_OK;
+}
- /* MP: ngx_shared_palloc() */
+ngx_int_t
+ngx_inet_sock_addr (u_char * p, size_t len, struct sockaddr * sockaddr)
+{
+ u_char *port, *last;
+ ngx_int_t n;
+ struct sockaddr_in *sin;
- u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
- if (u->addrs == NULL) {
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+ u_char *q;
+#endif
+
+ if (len == 0) {
+ return NGX_ERROR;
+ }
+
+ last = p + len;
+
+ port = NULL;
+
+#if (NGX_HAVE_INET6)
+
+ if (*p == '[') {
+
+ p++;
+
+ q = ngx_strlchr(p, last, ']');
+
+ if (q == NULL) {
return NGX_ERROR;
}
- sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
- if (sin == NULL) {
+ if (q < last - 2 && *(q + 1) == ':') {
+ port = q + 2;
+ } else {
return NGX_ERROR;
}
- u->naddrs = 1;
+ sin6 = (struct sockaddr_in6 *)sockaddr;
+
+ sin6->sin6_family = AF_INET6;
+
+ if (ngx_inet6_addr(p, q - p, sin6->sin6_addr.s6_addr) == NGX_ERROR)
{
+ return NGX_ERROR;
+ }
+
+ n = ngx_atoi(port, last - port);
+
+ if (n == NGX_ERROR || n < 1 || n > 65535) {
+ return NGX_ERROR;
+ }
+
+ sin6->sin6_port = htons(n);
+
+ }
+ else
+#endif
+ {
+ port = ngx_strlchr(p, last, ':');
+
+ if (port == NULL) {
+ return NGX_ERROR;
+ }
+
+ sin = (struct sockaddr_in *)sockaddr;
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);
+ sin->sin_addr.s_addr = ngx_inet_addr (p, port - p);
- p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
- if (p == NULL) {
+ if (sin->sin_addr.s_addr == INADDR_NONE) {
return NGX_ERROR;
}
- u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
- &u->host, ntohs(port)) - p;
- u->addrs[0].name.data = p;
+ port++;
+
+ n = ngx_atoi(port, last - port);
+
+ if (n == NGX_ERROR || n < 1 || n > 65535) {
+ return NGX_ERROR;
+ }
+
+ sin->sin_port = htons(n);
+
}
return NGX_OK;
--------------------------------------------------------ngx_inet.h-------------------------------------------
--- nginx-0.9.3/src/core/ngx_inet.h 2009-11-03 04:44:55.000000000 -0800
+++
/home/speedfirst/p4/zimbra/main/ThirdParty/nginx/nginx-0.9-zimbra/src/core/ngx_inet.h
2011-02-25
01:45:37.133302528 -0800
@@ -108,6 +108,8 @@
#endif
size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
ngx_uint_t port);
+ngx_int_t ngx_inet_sock_addr (u_char * p, size_t len,
+ struct sockaddr * sockaddr);
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_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://nginx.org/pipermail/nginx-devel/attachments/20110301/81715d80/attachment-0001.html>
More information about the nginx-devel
mailing list