changeset 5475:07dd5bd222ac

Changed resolver API to use ngx_addr_t.
author Ruslan Ermilov <ru@nginx.com>
date Fri, 06 Dec 2013 14:30:27 +0400
parents b43b02bb54db
children 950c9ed3e66f
files src/core/ngx_resolver.c src/core/ngx_resolver.h src/event/ngx_event_openssl_stapling.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_upstream_round_robin.c src/mail/ngx_mail_smtp_handler.c
diffstat 7 files changed, 246 insertions(+), 158 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -88,8 +88,8 @@ static void *ngx_resolver_calloc(ngx_res
 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
-static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
-    ngx_uint_t n);
+static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src,
+    ngx_uint_t n, ngx_uint_t rotate);
 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
@@ -281,7 +281,11 @@ ngx_resolve_start(ngx_resolver_t *r, ngx
             temp->state = NGX_OK;
             temp->naddrs = 1;
             temp->addrs = &temp->addr;
-            temp->addr = addr;
+            temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
+            temp->addr.socklen = sizeof(struct sockaddr_in);
+            ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
+            temp->sin.sin_family = AF_INET;
+            temp->sin.sin_addr.s_addr = addr;
             temp->quick = 1;
 
             return temp;
@@ -417,9 +421,9 @@ static ngx_int_t
 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
 {
     uint32_t              hash;
-    in_addr_t             addr, *addrs;
     ngx_int_t             rc;
     ngx_uint_t            naddrs;
+    ngx_addr_t           *addrs;
     ngx_resolver_ctx_t   *next;
     ngx_resolver_node_t  *rn;
 
@@ -445,16 +449,14 @@ ngx_resolve_name_locked(ngx_resolver_t *
 
                 /* NGX_RESOLVE_A answer */
 
-                if (naddrs != 1) {
-                    addr = 0;
-                    addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
+                if (naddrs == 1) {
+                    addrs = NULL;
+
+                } else {
+                    addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 1);
                     if (addrs == NULL) {
                         return NGX_ERROR;
                     }
-
-                } else {
-                    addr = rn->u.addr;
-                    addrs = NULL;
                 }
 
                 ctx->next = rn->waiting;
@@ -465,8 +467,19 @@ ngx_resolve_name_locked(ngx_resolver_t *
                 do {
                     ctx->state = NGX_OK;
                     ctx->naddrs = naddrs;
-                    ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
-                    ctx->addr = addr;
+
+                    if (addrs == NULL) {
+                        ctx->addrs = &ctx->addr;
+                        ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
+                        ctx->addr.socklen = sizeof(struct sockaddr_in);
+                        ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
+                        ctx->sin.sin_family = AF_INET;
+                        ctx->sin.sin_addr.s_addr = rn->u.addr;
+
+                    } else {
+                        ctx->addrs = addrs;
+                    }
+
                     next = ctx->next;
 
                     ctx->handler(ctx);
@@ -474,7 +487,8 @@ ngx_resolve_name_locked(ngx_resolver_t *
                     ctx = next;
                 } while (ctx);
 
-                if (addrs) {
+                if (addrs != NULL) {
+                    ngx_resolver_free(r, addrs->sockaddr);
                     ngx_resolver_free(r, addrs);
                 }
 
@@ -626,20 +640,29 @@ failed:
 }
 
 
+/* AF_INET only */
+
 ngx_int_t
 ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
 {
     u_char               *name;
+    in_addr_t             addr;
     ngx_resolver_t       *r;
+    struct sockaddr_in   *sin;
     ngx_resolver_node_t  *rn;
 
     r = ctx->resolver;
 
-    ctx->addr = ntohl(ctx->addr);
+    if (ctx->addr.sockaddr->sa_family != AF_INET) {
+        return NGX_ERROR;
+    }
+
+    sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+    addr = ntohl(sin->sin_addr.s_addr);
 
     /* lock addr mutex */
 
-    rn = ngx_resolver_lookup_addr(r, ctx->addr);
+    rn = ngx_resolver_lookup_addr(r, addr);
 
     if (rn) {
 
@@ -694,7 +717,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
             goto failed;
         }
 
-        rn->node.key = ctx->addr;
+        rn->node.key = addr;
         rn->query = NULL;
 
         ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
@@ -765,14 +788,24 @@ failed:
 }
 
 
+/* AF_INET only */
+
 void
 ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
 {
     in_addr_t             addr;
     ngx_resolver_t       *r;
     ngx_resolver_ctx_t   *w, **p;
+    struct sockaddr_in   *sin;
     ngx_resolver_node_t  *rn;
 
+    if (ctx->addr.sockaddr->sa_family != AF_INET) {
+        return;
+    }
+
+    sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+    addr = ntohl(sin->sin_addr.s_addr);
+
     r = ctx->resolver;
 
     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
@@ -786,7 +819,7 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t
 
     if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
 
-        rn = ngx_resolver_lookup_addr(r, ctx->addr);
+        rn = ngx_resolver_lookup_addr(r, addr);
 
         if (rn) {
             p = &rn->waiting;
@@ -804,8 +837,6 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t
             }
         }
 
-        addr = ntohl(ctx->addr);
-
         ngx_log_error(NGX_LOG_ALERT, r->log, 0,
                       "could not cancel %ud.%ud.%ud.%ud resolving",
                       (addr >> 24) & 0xff, (addr >> 16) & 0xff,
@@ -1177,8 +1208,9 @@ ngx_resolver_process_a(ngx_resolver_t *r
     size_t                len;
     int32_t               ttl;
     uint32_t              hash;
-    in_addr_t             addr, *addrs;
+    in_addr_t            *addr;
     ngx_str_t             name;
+    ngx_addr_t           *addrs;
     ngx_uint_t            type, class, qident, naddrs, a, i, n, start;
     ngx_resolver_an_t    *an;
     ngx_resolver_ctx_t   *ctx, *next;
@@ -1247,8 +1279,6 @@ ngx_resolver_process_a(ngx_resolver_t *r
 
     i = ans;
     naddrs = 0;
-    addr = 0;
-    addrs = NULL;
     cname = NULL;
     ttl = 0;
 
@@ -1319,9 +1349,6 @@ ngx_resolver_process_a(ngx_resolver_t *r
                 goto short_response;
             }
 
-            addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
-                         + (buf[i + 2] << 8) + (buf[i + 3]));
-
             naddrs++;
 
             break;
@@ -1352,66 +1379,69 @@ ngx_resolver_process_a(ngx_resolver_t *r
     if (naddrs) {
 
         if (naddrs == 1) {
-            rn->u.addr = addr;
+            addr = &rn->u.addr;
+            rn->naddrs = 1;
 
         } else {
-
-            addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
-            if (addrs == NULL) {
+            addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
+            if (addr == NULL) {
                 goto failed;
             }
 
-            n = 0;
-            i = ans;
-
-            for (a = 0; a < nan; a++) {
-
-                for ( ;; ) {
-
-                    if (buf[i] & 0xc0) {
-                        i += 2;
-                        break;
-                    }
-
-                    if (buf[i] == 0) {
-                        i++;
-                        break;
-                    }
-
-                    i += 1 + buf[i];
+            rn->u.addrs = addr;
+            rn->naddrs = (u_short) naddrs;
+        }
+
+        n = 0;
+        i = ans;
+
+        for (a = 0; a < nan; a++) {
+
+            for ( ;; ) {
+
+                if (buf[i] & 0xc0) {
+                    i += 2;
+                    break;
+                }
+
+                if (buf[i] == 0) {
+                    i++;
+                    break;
                 }
 
-                an = (ngx_resolver_an_t *) &buf[i];
-
-                type = (an->type_hi << 8) + an->type_lo;
-                len = (an->len_hi << 8) + an->len_lo;
-
-                i += sizeof(ngx_resolver_an_t);
-
-                if (type == NGX_RESOLVE_A) {
-
-                    addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
-                                       + (buf[i + 2] << 8) + (buf[i + 3]));
-
-                    if (n == naddrs) {
-                        break;
-                    }
+                i += 1 + buf[i];
+            }
+
+            an = (ngx_resolver_an_t *) &buf[i];
+
+            type = (an->type_hi << 8) + an->type_lo;
+            len = (an->len_hi << 8) + an->len_lo;
+
+            i += sizeof(ngx_resolver_an_t);
+
+            if (type == NGX_RESOLVE_A) {
+
+                addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
+                                + (buf[i + 2] << 8) + (buf[i + 3]));
+
+                if (++n == naddrs) {
+                    break;
                 }
-
-                i += len;
             }
 
-            rn->u.addrs = addrs;
-
-            addrs = ngx_resolver_dup(r, rn->u.addrs,
-                                     naddrs * sizeof(in_addr_t));
+            i += len;
+        }
+
+        if (naddrs == 1) {
+            addrs = NULL;
+
+        } else {
+            addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 0);
             if (addrs == NULL) {
                 goto failed;
             }
         }
 
-        rn->naddrs = (u_short) naddrs;
-
         ngx_queue_remove(&rn->queue);
 
         rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
@@ -1428,14 +1458,26 @@ ngx_resolver_process_a(ngx_resolver_t *r
             ctx = next;
             ctx->state = NGX_OK;
             ctx->naddrs = naddrs;
-            ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
-            ctx->addr = addr;
+
+            if (addrs == NULL) {
+                ctx->addrs = &ctx->addr;
+                ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
+                ctx->addr.socklen = sizeof(struct sockaddr_in);
+                ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
+                ctx->sin.sin_family = AF_INET;
+                ctx->sin.sin_addr.s_addr = rn->u.addr;
+
+            } else {
+                ctx->addrs = addrs;
+            }
+
             next = ctx->next;
 
             ctx->handler(ctx);
         }
 
-        if (naddrs > 1) {
+        if (addrs != NULL) {
+            ngx_resolver_free(r, addrs->sockaddr);
             ngx_resolver_free(r, addrs);
         }
 
@@ -1918,9 +1960,15 @@ ngx_resolver_create_addr_query(ngx_resol
 {
     u_char              *p, *d;
     size_t               len;
+    in_addr_t            addr;
     ngx_int_t            n;
     ngx_uint_t           ident;
     ngx_resolver_hdr_t  *query;
+    struct sockaddr_in  *sin;
+
+    if (ctx->addr.sockaddr->sa_family != AF_INET) {
+        return NGX_ERROR;
+    }
 
     len = sizeof(ngx_resolver_hdr_t)
           + sizeof(".255.255.255.255.in-addr.arpa.") - 1
@@ -1950,8 +1998,11 @@ ngx_resolver_create_addr_query(ngx_resol
 
     p += sizeof(ngx_resolver_hdr_t);
 
+    sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+    addr = ntohl(sin->sin_addr.s_addr);
+
     for (n = 0; n < 32; n += 8) {
-        d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
+        d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff);
         *p = (u_char) (d - &p[1]);
         p = d;
     }
@@ -2167,27 +2218,38 @@ ngx_resolver_dup(ngx_resolver_t *r, void
 }
 
 
-static in_addr_t *
-ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
+static ngx_addr_t *
+ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n,
+    ngx_uint_t rotate)
 {
-    void        *dst, *p;
-    ngx_uint_t   j;
-
-    dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
-
+    ngx_addr_t          *dst;
+    ngx_uint_t           i, j;
+    struct sockaddr_in  *sin;
+
+    dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
     if (dst == NULL) {
-        return dst;
+        return NULL;
     }
 
-    j = ngx_random() % n;
-
-    if (j == 0) {
-        ngx_memcpy(dst, src, n * sizeof(in_addr_t));
-        return dst;
+    sin = ngx_resolver_calloc(r, n * sizeof(struct sockaddr_in));
+
+    if (sin == NULL) {
+        ngx_resolver_free(r, dst);
+        return NULL;
     }
 
-    p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
-    ngx_memcpy(p, src, j * sizeof(in_addr_t));
+    j = rotate ? ngx_random() % n : 0;
+
+    for (i = 0; i < n; i++) {
+        dst[i].sockaddr = (struct sockaddr *) &sin[i];
+        dst[i].socklen = sizeof(struct sockaddr_in);
+        sin[i].sin_family = AF_INET;
+        sin[i].sin_addr.s_addr = src[j++];
+
+        if (j == n) {
+            j = 0;
+        }
+    }
 
     return dst;
 }
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -121,8 +121,9 @@ struct ngx_resolver_ctx_s {
     ngx_str_t                 name;
 
     ngx_uint_t                naddrs;
-    in_addr_t                *addrs;
-    in_addr_t                 addr;
+    ngx_addr_t               *addrs;
+    ngx_addr_t                addr;
+    struct sockaddr_in        sin;
 
     ngx_resolver_handler_pt   handler;
     void                     *data;
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -816,11 +816,12 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolve
 {
     ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
 
-    u_char              *p;
-    size_t               len;
-    in_port_t            port;
-    ngx_uint_t           i;
-    struct sockaddr_in  *sin;
+    u_char           *p;
+    size_t            len;
+    in_port_t         port;
+    socklen_t         socklen;
+    ngx_uint_t        i;
+    struct sockaddr  *sockaddr;
 
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                    "ssl ocsp resolve handler");
@@ -835,15 +836,19 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolve
 
 #if (NGX_DEBUG)
     {
-    in_addr_t   addr;
+    u_char     text[NGX_SOCKADDR_STRLEN];
+    ngx_str_t  addr;
+
+    addr.data = text;
 
     for (i = 0; i < resolve->naddrs; i++) {
-        addr = ntohl(resolve->addrs[i]);
+        addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
+                                 resolve->addrs[i].socklen,
+                                 text, NGX_SOCKADDR_STRLEN, 0);
 
-        ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
-                       "name was resolved to %ud.%ud.%ud.%ud",
-                       (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-                       (addr >> 8) & 0xff, addr & 0xff);
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
+                       "name was resolved to %V", &addr);
+
     }
     }
 #endif
@@ -859,27 +864,34 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolve
 
     for (i = 0; i < resolve->naddrs; i++) {
 
-        sin = ngx_pcalloc(ctx->pool, sizeof(struct sockaddr_in));
-        if (sin == NULL) {
+        socklen = resolve->addrs[i].socklen;
+
+        sockaddr = ngx_palloc(ctx->pool, socklen);
+        if (sockaddr == NULL) {
             goto failed;
         }
 
-        sin->sin_family = AF_INET;
-        sin->sin_port = port;
-        sin->sin_addr.s_addr = resolve->addrs[i];
+        ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
 
-        ctx->addrs[i].sockaddr = (struct sockaddr *) sin;
-        ctx->addrs[i].socklen = sizeof(struct sockaddr_in);
+        switch (sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            ((struct sockaddr_in6 *) sockaddr)->sin6_port = port;
+            break;
+#endif
+        default: /* AF_INET */
+            ((struct sockaddr_in *) sockaddr)->sin_port = port;
+        }
 
-        len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
+        ctx->addrs[i].sockaddr = sockaddr;
+        ctx->addrs[i].socklen = socklen;
 
-        p = ngx_pnalloc(ctx->pool, len);
+        p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
         if (p == NULL) {
             goto failed;
         }
 
-        len = ngx_sock_ntop((struct sockaddr *) sin, sizeof(struct sockaddr_in),
-                            p, len, 1);
+        len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
 
         ctx->addrs[i].name.len = len;
         ctx->addrs[i].name.data = p;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -918,16 +918,18 @@ ngx_http_upstream_resolve_handler(ngx_re
 
 #if (NGX_DEBUG)
     {
-    in_addr_t   addr;
+    u_char      text[NGX_SOCKADDR_STRLEN];
+    ngx_str_t   addr;
     ngx_uint_t  i;
 
+    addr.data = text;
+
     for (i = 0; i < ctx->naddrs; i++) {
-        addr = ntohl(ur->addrs[i]);
-
-        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "name was resolved to %ud.%ud.%ud.%ud",
-                       (addr >> 24) & 0xff, (addr >> 16) & 0xff,
-                       (addr >> 8) & 0xff, addr & 0xff);
+        addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
+                                 text, NGX_SOCKADDR_STRLEN, 0);
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "name was resolved to %V", &addr);
     }
     }
 #endif
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -256,7 +256,7 @@ typedef struct {
     ngx_uint_t                       no_port; /* unsigned no_port:1 */
 
     ngx_uint_t                       naddrs;
-    in_addr_t                       *addrs;
+    ngx_addr_t                      *addrs;
 
     struct sockaddr                 *sockaddr;
     socklen_t                        socklen;
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -266,8 +266,9 @@ ngx_http_upstream_create_round_robin_pee
 {
     u_char                            *p;
     size_t                             len;
+    socklen_t                          socklen;
     ngx_uint_t                         i, n;
-    struct sockaddr_in                *sin;
+    struct sockaddr                   *sockaddr;
     ngx_http_upstream_rr_peers_t      *peers;
     ngx_http_upstream_rr_peer_data_t  *rrp;
 
@@ -306,27 +307,34 @@ ngx_http_upstream_create_round_robin_pee
 
         for (i = 0; i < ur->naddrs; i++) {
 
-            len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
+            socklen = ur->addrs[i].socklen;
+
+            sockaddr = ngx_palloc(r->pool, socklen);
+            if (sockaddr == NULL) {
+                return NGX_ERROR;
+            }
+
+            ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen);
 
-            p = ngx_pnalloc(r->pool, len);
+            switch (sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+            case AF_INET6:
+                ((struct sockaddr_in6 *) sockaddr)->sin6_port = htons(ur->port);
+                break;
+#endif
+            default: /* AF_INET */
+                ((struct sockaddr_in *) sockaddr)->sin_port = htons(ur->port);
+            }
+
+            p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN);
             if (p == NULL) {
                 return NGX_ERROR;
             }
 
-            len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
-            len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
+            len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
 
-            sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
-            if (sin == NULL) {
-                return NGX_ERROR;
-            }
-
-            sin->sin_family = AF_INET;
-            sin->sin_port = htons(ur->port);
-            sin->sin_addr.s_addr = ur->addrs[i];
-
-            peers->peer[i].sockaddr = (struct sockaddr *) sin;
-            peers->peer[i].socklen = sizeof(struct sockaddr_in);
+            peers->peer[i].sockaddr = sockaddr;
+            peers->peer[i].socklen = socklen;
             peers->peer[i].name.len = len;
             peers->peer[i].name.data = p;
             peers->peer[i].weight = 1;
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -55,7 +55,6 @@ static ngx_str_t  smtp_tempunavail = ngx
 void
 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    struct sockaddr_in        *sin;
     ngx_resolver_ctx_t        *ctx;
     ngx_mail_core_srv_conf_t  *cscf;
 
@@ -67,11 +66,13 @@ ngx_mail_smtp_init_session(ngx_mail_sess
         return;
     }
 
-    if (c->sockaddr->sa_family != AF_INET) {
+#if (NGX_HAVE_UNIX_DOMAIN)
+    if (c->sockaddr->sa_family == AF_UNIX) {
         s->host = smtp_tempunavail;
         ngx_mail_smtp_greeting(s, c);
         return;
     }
+#endif
 
     c->log->action = "in resolving client address";
 
@@ -81,11 +82,8 @@ ngx_mail_smtp_init_session(ngx_mail_sess
         return;
     }
 
-    /* AF_INET only */
-
-    sin = (struct sockaddr_in *) c->sockaddr;
-
-    ctx->addr = sin->sin_addr.s_addr;
+    ctx->addr.sockaddr = c->sockaddr;
+    ctx->addr.socklen = c->socklen;
     ctx->handler = ngx_mail_smtp_resolve_addr_handler;
     ctx->data = s;
     ctx->timeout = cscf->resolver_timeout;
@@ -181,10 +179,8 @@ ngx_mail_smtp_resolve_name(ngx_event_t *
 static void
 ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
 {
-    in_addr_t            addr;
     ngx_uint_t           i;
     ngx_connection_t    *c;
-    struct sockaddr_in  *sin;
     ngx_mail_session_t  *s;
 
     s = ctx->data;
@@ -205,22 +201,29 @@ ngx_mail_smtp_resolve_name_handler(ngx_r
 
     } else {
 
-        /* AF_INET only */
+#if (NGX_DEBUG)
+        {
+        u_char     text[NGX_SOCKADDR_STRLEN];
+        ngx_str_t  addr;
 
-        sin = (struct sockaddr_in *) c->sockaddr;
+        addr.data = text;
 
         for (i = 0; i < ctx->naddrs; i++) {
-
-            addr = ctx->addrs[i];
+            addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr,
+                                     ctx->addrs[i].socklen,
+                                     text, NGX_SOCKADDR_STRLEN, 0);
 
-            ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
-                           "name was resolved to %ud.%ud.%ud.%ud",
-                           (ntohl(addr) >> 24) & 0xff,
-                           (ntohl(addr) >> 16) & 0xff,
-                           (ntohl(addr) >> 8) & 0xff,
-                           ntohl(addr) & 0xff);
+            ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+                           "name was resolved to %V", &addr);
+        }
+        }
+#endif
 
-            if (addr == sin->sin_addr.s_addr) {
+        for (i = 0; i < ctx->naddrs; i++) {
+            if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen,
+                                 c->sockaddr, c->socklen, 0)
+                == NGX_OK)
+            {
                 goto found;
             }
         }