# HG changeset patch # User Igor Sysoev # Date 1242649222 0 # Node ID a96a8c916b0cb564cfaf2698c6fa269608058450 # Parent d788477f5a679a13c817443ee98029845e1d9ef4 mail proxy listen IPv6 support diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -11,7 +11,16 @@ static char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_mail_cmp_conf_in_addrs(const void *one, const void *two); +static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen); +static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports); +static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#if (NGX_HAVE_INET6) +static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#endif +static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two); ngx_uint_t ngx_mail_max_module; @@ -64,19 +73,12 @@ static char * ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; - u_char *text; - size_t len; - ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done; + ngx_uint_t i, m, mi, s; ngx_conf_t pcf; - ngx_array_t in_ports; - ngx_listening_t *ls; - ngx_mail_listen_t *mls; + ngx_array_t ports; + ngx_mail_listen_t *listen; ngx_mail_module_t *module; - struct sockaddr_in sin; - ngx_mail_in_port_t *mip; ngx_mail_conf_ctx_t *ctx; - ngx_mail_conf_in_port_t *in_port; - ngx_mail_conf_in_addr_t *in_addr; ngx_mail_core_srv_conf_t **cscfp; ngx_mail_core_main_conf_t *cmcf; @@ -217,98 +219,149 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma *cf = pcf; - if (ngx_array_init(&in_ports, cf->temp_pool, 4, - sizeof(ngx_mail_conf_in_port_t)) + if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } - mls = cmcf->listen.elts; - - for (l = 0; l < cmcf->listen.nelts; l++) { - - /* AF_INET only */ + listen = cmcf->listen.elts; - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { - if (in_port[p].port == mls[l].port) { - in_port = &in_port[p]; - goto found; - } - } - - in_port = ngx_array_push(&in_ports); - if (in_port == NULL) { - return NGX_CONF_ERROR; - } - - in_port->port = mls[l].port; - - if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2, - sizeof(ngx_mail_conf_in_addr_t)) - != NGX_OK) - { + for (i = 0; i < cmcf->listen.nelts; i++) { + if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } + } - found: + return ngx_mail_optimize_servers(cf, &ports); +} + + +static ngx_int_t +ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen) +{ + in_port_t p; + ngx_uint_t i; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + sa = (struct sockaddr *) &listen->sockaddr; - in_addr = ngx_array_push(&in_port->addrs); - if (in_addr == NULL) { - return NGX_CONF_ERROR; + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + p = sin6->sin6_port; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + p = sin->sin_port; + break; + } + + port = ports->elts; + for (i = 0; i < ports->nelts; i++) { + if (p == port[i].port && sa->sa_family == port[i].family) { + + /* a port is already in the port list */ + + port = &port[i]; + goto found; } - - in_addr->addr = mls[l].addr; - in_addr->ctx = mls[l].ctx; - in_addr->bind = mls[l].bind; -#if (NGX_MAIL_SSL) - in_addr->ssl = mls[l].ssl; -#endif } - /* optimize the lists of ports and addresses */ + /* add a port to the port list */ + + port = ngx_array_push(ports); + if (port == NULL) { + return NGX_ERROR; + } + + port->family = sa->sa_family; + port->port = p; - /* AF_INET only */ + if (ngx_array_init(&port->addrs, cf->temp_pool, 2, + sizeof(ngx_mail_conf_addr_t)) + != NGX_OK) + { + return NGX_ERROR; + } + +found: + + addr = ngx_array_push(&port->addrs); + if (addr == NULL) { + return NGX_ERROR; + } - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { + addr->sockaddr = (struct sockaddr *) &listen->sockaddr; + addr->socklen = listen->socklen; + addr->ctx = listen->ctx; + addr->bind = listen->bind; + addr->wildcard = listen->wildcard; +#if (NGX_MAIL_SSL) + addr->ssl = listen->ssl; +#endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + addr->ipv6only = listen->ipv6only; +#endif + + return NGX_OK; +} + - ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, - sizeof(ngx_mail_conf_in_addr_t), ngx_mail_cmp_conf_in_addrs); +static char * +ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) +{ + ngx_uint_t i, p, last, bind_wildcard; + ngx_listening_t *ls; + ngx_mail_port_t *mport; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; - in_addr = in_port[p].addrs.elts; - last = in_port[p].addrs.nelts; + port = ports->elts; + for (p = 0; p < ports->nelts; p++) { + + ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, + sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs); + + addr = port[p].addrs.elts; + last = port[p].addrs.nelts; /* * if there is the binding to the "*:port" then we need to bind() * to the "*:port" only and ignore the other bindings */ - if (in_addr[last - 1].addr == INADDR_ANY) { - in_addr[last - 1].bind = 1; - bind_all = 0; + if (addr[last - 1].wildcard) { + addr[last - 1].bind = 1; + bind_wildcard = 1; } else { - bind_all = 1; + bind_wildcard = 0; } - for (a = 0; a < last; /* void */ ) { + i = 0; - if (!bind_all && !in_addr[a].bind) { - a++; + while (i < last) { + + if (bind_wildcard && !addr[i].bind) { + i++; continue; } - ngx_memzero(&sin, sizeof(struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = in_addr[a].addr; - sin.sin_port = htons(in_port[p].port); - - ls = ngx_create_listening(cf, &sin, sizeof(struct sockaddr_in)); + ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); if (ls == NULL) { - return NULL; + return NGX_CONF_ERROR; } ls->addr_ntop = 1; @@ -320,75 +373,42 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; - mip = ngx_palloc(cf->pool, sizeof(ngx_mail_in_port_t)); - if (mip == NULL) { +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + ls->ipv6only = addr[i].ipv6only; +#endif + + mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t)); + if (mport == NULL) { return NGX_CONF_ERROR; } - ls->servers = mip; - - in_addr = in_port[p].addrs.elts; + ls->servers = mport; - if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { - mip->naddrs = 1; - done = 0; - - } else if (in_port[p].addrs.nelts > 1 - && in_addr[last - 1].addr == INADDR_ANY) - { - mip->naddrs = last; - done = 1; + if (i == last - 1) { + mport->naddrs = last; } else { - mip->naddrs = 1; - done = 0; + mport->naddrs = 1; + i = 0; } -#if 0 - ngx_log_error(NGX_LOG_ALERT, cf->log, 0, - "%ui: %V %d %ui %ui", - a, &ls->addr_text, in_addr[a].bind, - mip->naddrs, last); -#endif - - mip->addrs = ngx_pcalloc(cf->pool, - mip->naddrs * sizeof(ngx_mail_in_addr_t)); - if (mip->addrs == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; i < mip->naddrs; i++) { - mip->addrs[i].addr = in_addr[i].addr; - mip->addrs[i].ctx = in_addr[i].ctx; - - text = ngx_pnalloc(cf->pool, - NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1); - if (text == NULL) { + switch (ls->sockaddr->sa_family) { +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) { return NGX_CONF_ERROR; } - - len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text, - NGX_INET_ADDRSTRLEN); - - len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text; - - mip->addrs[i].addr_text.len = len; - mip->addrs[i].addr_text.data = text; - -#if (NGX_MAIL_SSL) - mip->addrs[i].ssl = in_addr[i].ssl; + break; #endif - } - - if (done) { + default: /* AF_INET */ + if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) { + return NGX_CONF_ERROR; + } break; } - in_addr++; - in_port[p].addrs.elts = in_addr; + addr++; last--; - - a = 0; } } @@ -397,15 +417,111 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma static ngx_int_t -ngx_mail_cmp_conf_in_addrs(const void *one, const void *two) +ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) { - ngx_mail_conf_in_addr_t *first, *second; + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in_addr_t *addrs; + struct sockaddr_in *sin; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin = (struct sockaddr_in *) addr[i].sockaddr; + addrs[i].addr = sin->sin_addr.s_addr; + + addrs[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs[i].conf.ssl = addr[i].ssl; +#endif + + len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs[i].conf.addr_text.len = len; + addrs[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + + +#if (NGX_HAVE_INET6) - first = (ngx_mail_conf_in_addr_t *) one; - second = (ngx_mail_conf_in_addr_t *) two; +static ngx_int_t +ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in6_addr_t *addrs6; + struct sockaddr_in6 *sin6; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in6_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs6 = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + addrs6[i].addr6 = sin6->sin6_addr; + + addrs6[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs6[i].conf.ssl = addr[i].ssl; +#endif - if (first->addr == INADDR_ANY) { - /* the INADDR_ANY must be the last resort, shift it to the end */ + len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs6[i].conf.addr_text.len = len; + addrs6[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_mail_cmp_conf_addrs(const void *one, const void *two) +{ + ngx_mail_conf_addr_t *first, *second; + + first = (ngx_mail_conf_addr_t *) one; + second = (ngx_mail_conf_addr_t *) two; + + if (first->wildcard) { + /* a wildcard must be the last resort, shift it to the end */ return 1; } diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -26,50 +26,76 @@ typedef struct { typedef struct { - in_addr_t addr; - in_port_t port; - int family; + u_char sockaddr[NGX_SOCKADDRLEN]; + socklen_t socklen; /* server ctx */ ngx_mail_conf_ctx_t *ctx; unsigned bind:1; + unsigned wildcard:1; #if (NGX_MAIL_SSL) unsigned ssl:1; #endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:2; +#endif } ngx_mail_listen_t; typedef struct { - in_addr_t addr; ngx_mail_conf_ctx_t *ctx; ngx_str_t addr_text; #if (NGX_MAIL_SSL) ngx_uint_t ssl; /* unsigned ssl:1; */ #endif +} ngx_mail_addr_conf_t; + +typedef struct { + in_addr_t addr; + ngx_mail_addr_conf_t conf; } ngx_mail_in_addr_t; +#if (NGX_HAVE_INET6) + typedef struct { - ngx_mail_in_addr_t *addrs; /* array of ngx_mail_in_addr_t */ - ngx_uint_t naddrs; -} ngx_mail_in_port_t; + struct in6_addr addr6; + ngx_mail_addr_conf_t conf; +} ngx_mail_in6_addr_t; + +#endif typedef struct { + /* ngx_mail_in_addr_t or ngx_mail_in6_addr_t */ + void *addrs; + ngx_uint_t naddrs; +} ngx_mail_port_t; + + +typedef struct { + int family; in_port_t port; - ngx_array_t addrs; /* array of ngx_mail_conf_in_addr_t */ -} ngx_mail_conf_in_port_t; + ngx_array_t addrs; /* array of ngx_mail_conf_addr_t */ +} ngx_mail_conf_port_t; typedef struct { - in_addr_t addr; + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_mail_conf_ctx_t *ctx; + unsigned bind:1; + unsigned wildcard:1; #if (NGX_MAIL_SSL) unsigned ssl:1; #endif -} ngx_mail_conf_in_addr_t; +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:2; +#endif +} ngx_mail_conf_addr_t; typedef struct { diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -771,6 +771,8 @@ ngx_mail_auth_http_process_headers(ngx_m return; } + /* AF_INET only */ + sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in)); if (sin == NULL) { ngx_destroy_pool(ctx->pool); diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- 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; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -21,25 +21,27 @@ static void ngx_mail_ssl_handshake_handl void ngx_mail_init_connection(ngx_connection_t *c) { - in_addr_t in_addr; - socklen_t len; - ngx_uint_t i; - struct sockaddr_in sin; - ngx_mail_log_ctx_t *ctx; - ngx_mail_in_port_t *mip; - ngx_mail_in_addr_t *mia; - ngx_mail_session_t *s; + ngx_uint_t i; + ngx_mail_port_t *port; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_log_ctx_t *ctx; + ngx_mail_in_addr_t *addr; + ngx_mail_session_t *s; + ngx_mail_addr_conf_t *addr_conf; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; + ngx_mail_in6_addr_t *addr6; +#endif + /* find the server configuration for the address:port */ /* AF_INET only */ - mip = c->listening->servers; - mia = mip->addrs; + port = c->listening->servers; - i = 0; - - if (mip->naddrs > 1) { + if (port->naddrs > 1) { /* * There are several addresses on this port and one of them @@ -49,45 +51,79 @@ ngx_mail_init_connection(ngx_connection_ * AcceptEx() already gave this address. */ -#if (NGX_WIN32) - if (c->local_sockaddr) { - in_addr = - ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr; + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + + sa = c->local_sockaddr; + + switch (sa->sa_family) { - } else -#endif - { - len = sizeof(struct sockaddr_in); - if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { - ngx_connection_error(c, ngx_socket_errno, - "getsockname() failed"); - ngx_mail_close_connection(c); - return; +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + + addr6 = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { + break; + } } - in_addr = sin.sin_addr.s_addr; + addr_conf = &addr6[i].conf; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + + addr = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (addr[i].addr == sin->sin_addr.s_addr) { + break; + } + } + + addr_conf = &addr[i].conf; + + break; } - /* the last address is "*" */ + } else { + switch (c->local_sockaddr->sa_family) { - for ( /* void */ ; i < mip->naddrs - 1; i++) { - if (in_addr == mia[i].addr) { - break; - } +#if (NGX_HAVE_INET6) + case AF_INET6: + addr6 = port->addrs; + addr_conf = &addr6[0].conf; + break; +#endif + + default: /* AF_INET */ + addr = port->addrs; + addr_conf = &addr[0].conf; + break; } } - s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); if (s == NULL) { ngx_mail_close_connection(c); return; } - s->main_conf = mia[i].ctx->main_conf; - s->srv_conf = mia[i].ctx->srv_conf; + s->main_conf = addr_conf->ctx->main_conf; + s->srv_conf = addr_conf->ctx->srv_conf; - s->addr_text = &mia[i].addr_text; + s->addr_text = &addr_conf->addr_text; c->data = s; s->connection = c; @@ -124,7 +160,7 @@ ngx_mail_init_connection(ngx_connection_ return; } - if (mia[i].ssl) { + if (addr_conf->ssl) { c->log->action = "SSL handshaking"; diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -66,6 +66,12 @@ ngx_mail_smtp_init_session(ngx_mail_sess return; } + if (c->sockaddr->sa_family != AF_INET) { + s->host = smtp_tempunavail; + ngx_mail_smtp_greeting(s, c); + return; + } + c->log->action = "in resolving client address"; ctx = ngx_resolve_start(cscf->resolver, NULL);