# HG changeset patch # User Ruslan Ermilov # Date 1386325827 -14400 # Node ID 07dd5bd222ac0d0f81553fd4c7772bf74dc86399 # Parent b43b02bb54dbe0fc5c8222e34361d80b3f228314 Changed resolver API to use ngx_addr_t. diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- 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; } diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h --- 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; diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c --- 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; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- 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 diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- 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; diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- 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; 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 @@ -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; } }