summaryrefslogtreecommitdiffhomepage
path: root/src/mail/ngx_mail_core_module.c
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-05-18 12:20:22 +0000
committerIgor Sysoev <igor@sysoev.ru>2009-05-18 12:20:22 +0000
commit610cbd4223262a473e3513b1c6a6ff4f8c83a0d5 (patch)
treebb2a240b9180127cc1612c685b6bcc2df4d3b3fa /src/mail/ngx_mail_core_module.c
parentc985ee7a61ce0beb12890da46971a71babdbb215 (diff)
downloadnginx-610cbd4223262a473e3513b1c6a6ff4f8c83a0d5.tar.gz
nginx-610cbd4223262a473e3513b1c6a6ff4f8c83a0d5.tar.bz2
mail proxy listen IPv6 support
Diffstat (limited to 'src/mail/ngx_mail_core_module.c')
-rw-r--r--src/mail/ngx_mail_core_module.c93
1 files changed, 82 insertions, 11 deletions
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 976066284..d0addb059 100644
--- 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_command_t *cmd, void *conf)
}
-/* 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_command_t *cmd, void *conf)
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_command_t *cmd, void *conf)
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_command_t *cmd, void *conf)
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;