diff src/mail/ngx_mail_core_module.c @ 492:98143f74eb3d NGINX_0_7_58

nginx 0.7.58 *) Feature: a "listen" directive of the mail proxy module supports IPv6. *) Feature: the "image_filter_jpeg_quality" directive. *) Feature: the "client_body_in_single_buffer" directive. *) Feature: the $request_body variable. *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" symbol in the name. *) Bugfix: "make upgrade" procedure did not work; the bug had appeared in 0.7.53. Thanks to Denis F. Latypoff.
author Igor Sysoev <http://sysoev.ru>
date Mon, 18 May 2009 00:00:00 +0400
parents 6484cbba0222
children f39b9e29530d
line wrap: on
line diff
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -274,19 +274,24 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx
 }
 
 
-/* AF_INET only */
-
 static char *
 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_mail_core_srv_conf_t  *cscf = conf;
 
+    size_t                      len, off;
+    in_port_t                   port;
     ngx_str_t                  *value;
     ngx_url_t                   u;
     ngx_uint_t                  i, m;
+    struct sockaddr            *sa;
     ngx_mail_listen_t          *ls;
     ngx_mail_module_t          *module;
+    struct sockaddr_in         *sin;
     ngx_mail_core_main_conf_t  *cmcf;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6        *sin6;
+#endif
 
     value = cf->args->elts;
 
@@ -305,18 +310,42 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
-    if (u.family != AF_INET) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "listen supports IPv4 only");
-        return NGX_CONF_ERROR;
-    }
-
     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 (ls[i].addr != u.addr.in_addr || ls[i].port != u.port) {
+        sa = (struct sockaddr *) ls[i].sockaddr;
+
+        if (sa->sa_family != u.family) {
+            continue;
+        }
+
+        switch (sa->sa_family) {
+
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            off = offsetof(struct sockaddr_in6, sin6_addr);
+            len = 16;
+            sin6 = (struct sockaddr_in6 *) sa;
+            port = sin6->sin6_port;
+            break;
+#endif
+
+        default: /* AF_INET */
+            off = offsetof(struct sockaddr_in, sin_addr);
+            len = 4;
+            sin = (struct sockaddr_in *) sa;
+            port = sin->sin_port;
+            break;
+        }
+
+        if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
+            continue;
+        }
+
+        if (port != u.port) {
             continue;
         }
 
@@ -332,9 +361,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
 
     ngx_memzero(ls, sizeof(ngx_mail_listen_t));
 
-    ls->addr = u.addr.in_addr;
-    ls->port = u.port;
-    ls->family = u.family;
+    ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
+
+    ls->socklen = u.socklen;
+    ls->wildcard = u.wildcard;
     ls->ctx = cf->ctx;
 
     for (m = 0; ngx_modules[m]; m++) {
@@ -363,6 +393,47 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
             continue;
         }
 
+        if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+            struct sockaddr  *sa;
+            u_char            buf[NGX_SOCKADDR_STRLEN];
+
+            sa = (struct sockaddr *) ls->sockaddr;
+
+            if (sa->sa_family == AF_INET6) {
+
+                if (ngx_strcmp(&value[i].data[10], "n") == 0) {
+                    ls->ipv6only = 1;
+
+                } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
+                    ls->ipv6only = 2;
+
+                } 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 {
+                len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
+
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "ipv6only is not supported "
+                                   "on addr \"%*s\", ignored", len, buf);
+            }
+
+            continue;
+#else
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "bind ipv6only is not supported "
+                               "on this platform");
+            return NGX_CONF_ERROR;
+#endif
+        }
+
         if (ngx_strcmp(value[i].data, "ssl") == 0) {
 #if (NGX_MAIL_SSL)
             ls->ssl = 1;