[PATCH] Make Nginx Parse URL to IPv6 [Please ignore the last mail]

Speed First speedfirst at gmail.com
Fri Mar 4 09:01:04 MSK 2011


Here is a new diff. I remove most unrelated changes. Please review it. I
very hope to merge this in the main branch so please give the detailed
suggestions.

For the style problems, do u have any guide or doc for that? I can't
precisely guess the style from the existing code.

Many thanks.

--- nginx-0.9.5/src/core/ngx_inet.c    2011-02-17 07:01:16.000000000 -0800
+++ nginx-0.9.5/src/core/ngx_inet2.c    2011-03-03 09:34:54.423367009 -0800
@@ -11,6 +11,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_resolve_hostname(ngx_pool_t *pool, ngx_url_t *u);


 in_addr_t
@@ -612,10 +613,9 @@
 static ngx_int_t
 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
 {
-    u_char              *p, *host, *port, *last, *uri, *args;
+    u_char              *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);
@@ -738,23 +738,7 @@
         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]);
+            return ngx_resolve_hostname(pool, u);
         }

         if (sin->sin_addr.s_addr == INADDR_ANY) {
@@ -782,6 +766,111 @@
     return NGX_OK;
 }

+static ngx_int_t
+ngx_resolve_hostname(ngx_pool_t *pool, ngx_url_t *u) {
+    u_char               *p;
+    ngx_uint_t            family;
+    in_addr_t             in_addr;
+    struct sockaddr_in   *sin;
+
+#if (NGX_HAVE_INET6)
+    struct addrinfo       hints, *addrinfo;
+    struct in6_addr       in6_addr;
+    struct sockaddr_in6  *sin6;
+    int                   n;
+#else
+    struct hostent       *h;
+#endif
+
+    /* 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);
+
+#if (NGX_HAVE_INET6)
+
+    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);
+
+    if (n != NGX_OK) {
+       u->err = "host not found";
+       return NGX_ERROR;
+    }
+
+    if (addrinfo->ai_family == AF_INET) {
+       family = AF_INET;
+       in_addr = ((struct sockaddr_in *)
addrinfo->ai_addr)->sin_addr.s_addr;
+
+    } else { /* AF_INET6 */
+       family = AF_INET6;
+       in6_addr = ((struct sockaddr_in6 *) addrinfo->ai_addr)->sin6_addr;
+
+    }
+#else
+    h = gethostbyname((const char *) p);
+
+    if (h == NULL || h->h_addr_list[0] == NULL) {
+        u->err = "host not found";
+        return NGX_ERROR;
+    }
+
+    in_addr = *(in_addr_t *) (h->h_addr_list[0]);
+#endif
+
+    ngx_free(p);
+
+    switch (family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+       sin6 = (struct sockaddr_in6 *) u->sockaddr;
+       sin6->sin6_family = AF_INET6;
+       sin6->sin6_port = htons(u->port);
+       u->family = AF_INET6;
+       u->socklen = sizeof (struct sockaddr_in6);
+       ngx_memcpy(sin6->sin6_addr.s6_addr, in6_addr.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;
+       sin->sin_port = htons(u->port);
+       u->family = AF_INET;
+       u->socklen = sizeof (struct sockaddr_in);
+       sin->sin_addr.s_addr = in_addr;
+       if (sin->sin_addr.s_addr == INADDR_ANY) {
+           u->wildcard = 1;
+       }
+       break;
+    }
+
+    if (u->listen) {
+        return NGX_OK;
+    }
+
+    return ngx_inet_resolve_host(pool, u);
+}
+

 static ngx_int_t
 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
@@ -901,10 +990,19 @@
     in_port_t            port;
     in_addr_t            in_addr;
     ngx_uint_t           i;
-    struct hostent      *h;
     struct sockaddr_in  *sin;
+    struct sockaddr     *sa;
+
+#if (NGX_HAVE_INET6)
+    int                  family = -1;
+    struct addrinfo      hints, *addrinfo, *item;
+    struct in6_addr      in6_addr;
+    struct sockaddr_in6 *sin6;
+    int                  n;

-    /* AF_INET only */
+#else
+    struct hostent      *h;
+#endif

     port = htons(u->port);

@@ -918,9 +1016,33 @@

         (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);

-        h = gethostbyname((char *) host);
+#if (NGX_HAVE_INET6)
+
+        ngx_memzero (&hints, sizeof (struct addrinfo));

-        ngx_free(host);
+        /* 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);
+
+        if (n != NGX_OK) {
+            u->err = "host not found";
+            return NGX_ERROR;
+        }
+
+        if (u->one_addr == 0) {
+            item = addrinfo;
+            for (i = 0; item != NULL; i++, item = item->ai_next) { /* void
*/ }
+
+        } else {
+            i = 1;
+        }
+
+#else
+
+        h = gethostbyname((char *) host);

         if (h == NULL || h->h_addr_list[0] == NULL) {
             u->err = "host not found";
@@ -933,6 +1055,9 @@
         } else {
             i = 1;
         }
+#endif
+
+        ngx_free (host);

         /* MP: ngx_shared_palloc() */

@@ -945,26 +1070,59 @@

         for (i = 0; i < u->naddrs; i++) {

-            sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
-            if (sin == NULL) {
-                return NGX_ERROR;
+#if (NGX_HAVE_INET6)
+            if (addrinfo->ai_family == AF_INET) {
+                family = AF_INET;
+                sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
+                if (sin == NULL) {
+                    return NGX_ERROR;
+                }
+                in_addr = ((struct sockaddr_in *)
addrinfo->ai_addr)->sin_addr.s_addr;
+                sin->sin_addr.s_addr = in_addr;
+            } else {
+                family = AF_INET6;
+                sin6 = ngx_pcalloc(pool, sizeof(struct sockaddr_in6));
+                if (sin6 == NULL) {
+                    return NGX_ERROR;
+                }
+                in6_addr = ((struct sockaddr_in6 *)
addrinfo->ai_addr)->sin6_addr;
+                ngx_memcpy(sin6->sin6_addr.s6_addr, in6_addr.s6_addr, 16);
             }

-            sin->sin_family = AF_INET;
-            sin->sin_port = port;
+            addrinfo = addrinfo->ai_next;
+
+#else
+            sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
             sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
+#endif

-            u->addrs[i].sockaddr = (struct sockaddr *) sin;
-            u->addrs[i].socklen = sizeof(struct sockaddr_in);
+#if (NGX_HAVE_INET6)
+            if (family == AF_INET6) {

-            len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
+                sin6->sin6_family = AF_INET6;
+                sin6->sin6_port = port;
+                sa = (struct sockaddr *)sin6;
+                u->addrs[i].sockaddr = sa;
+                u->addrs[i].socklen = sizeof(struct sockaddr_in6);
+                len = NGX_INET6_ADDRSTRLEN + sizeof("[]") - 1 +
sizeof(":65535") - 1;
+            }
+            else
+#endif
+            {
+                sin->sin_family = AF_INET;
+                sin->sin_port = port;
+                sa = (struct sockaddr *)sin;
+                u->addrs[i].sockaddr = sa;
+                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, 1);
+            len = ngx_sock_ntop(sa, p, len, 1);

             u->addrs[i].name.len = len;
             u->addrs[i].name.data = p;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://nginx.org/pipermail/nginx-devel/attachments/20110303/7ef79425/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ngx_inet.c.diff
Type: text/x-patch
Size: 8510 bytes
Desc: not available
URL: <http://nginx.org/pipermail/nginx-devel/attachments/20110303/7ef79425/attachment-0001.bin>


More information about the nginx-devel mailing list