comparison src/mail/ngx_mail_core_module.c @ 8104:4cc2bfeff46c

Filtering duplicate addresses in listen (ticket #2400). Due to the glibc bug[1], getaddrinfo("localhost") with AI_ADDRCONFIG on a typical host with glibc and without IPv6 returns two 127.0.0.1 addresses, and therefore "listen localhost:80;" used to result in "duplicate ... address and port pair" after 4f9b72a229c1. Fix is to explicitly filter out duplicate addresses returned during resolution of a name. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=14969
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 23 Nov 2022 17:30:08 +0300
parents ec1071830799
children 2af1287d2da7
comparison
equal deleted inserted replaced
8103:b809f53d3f5b 8104:4cc2bfeff46c
306 ngx_mail_core_srv_conf_t *cscf = conf; 306 ngx_mail_core_srv_conf_t *cscf = conf;
307 307
308 ngx_str_t *value, size; 308 ngx_str_t *value, size;
309 ngx_url_t u; 309 ngx_url_t u;
310 ngx_uint_t i, n, m; 310 ngx_uint_t i, n, m;
311 ngx_mail_listen_t *ls, *als; 311 ngx_mail_listen_t *ls, *als, *nls;
312 ngx_mail_module_t *module; 312 ngx_mail_module_t *module;
313 ngx_mail_core_main_conf_t *cmcf; 313 ngx_mail_core_main_conf_t *cmcf;
314 314
315 cscf->listen = 1; 315 cscf->listen = 1;
316 316
331 return NGX_CONF_ERROR; 331 return NGX_CONF_ERROR;
332 } 332 }
333 333
334 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); 334 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
335 335
336 ls = ngx_array_push_n(&cmcf->listen, u.naddrs); 336 ls = ngx_array_push(&cmcf->listen);
337 if (ls == NULL) { 337 if (ls == NULL) {
338 return NGX_CONF_ERROR; 338 return NGX_CONF_ERROR;
339 } 339 }
340 340
341 ngx_memzero(ls, sizeof(ngx_mail_listen_t)); 341 ngx_memzero(ls, sizeof(ngx_mail_listen_t));
566 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 566 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
567 "the invalid \"%V\" parameter", &value[i]); 567 "the invalid \"%V\" parameter", &value[i]);
568 return NGX_CONF_ERROR; 568 return NGX_CONF_ERROR;
569 } 569 }
570 570
571 als = cmcf->listen.elts;
572
573 for (n = 0; n < u.naddrs; n++) { 571 for (n = 0; n < u.naddrs; n++) {
574 ls[n] = ls[0]; 572
575 573 for (i = 0; i < n; i++) {
576 ls[n].sockaddr = u.addrs[n].sockaddr; 574 if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
577 ls[n].socklen = u.addrs[n].socklen; 575 u.addrs[i].sockaddr, u.addrs[i].socklen, 0)
578 ls[n].addr_text = u.addrs[n].name; 576 == NGX_OK)
579 ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); 577 {
580 578 goto next;
581 for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { 579 }
580 }
581
582 if (n != 0) {
583 nls = ngx_array_push(&cmcf->listen);
584 if (nls == NULL) {
585 return NGX_CONF_ERROR;
586 }
587
588 *nls = *ls;
589
590 } else {
591 nls = ls;
592 }
593
594 nls->sockaddr = u.addrs[n].sockaddr;
595 nls->socklen = u.addrs[n].socklen;
596 nls->addr_text = u.addrs[n].name;
597 nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
598
599 als = cmcf->listen.elts;
600
601 for (i = 0; i < cmcf->listen.nelts - 1; i++) {
582 602
583 if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, 603 if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
584 ls[n].sockaddr, ls[n].socklen, 1) 604 nls->sockaddr, nls->socklen, 1)
585 != NGX_OK) 605 != NGX_OK)
586 { 606 {
587 continue; 607 continue;
588 } 608 }
589 609
590 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 610 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
591 "duplicate \"%V\" address and port pair", 611 "duplicate \"%V\" address and port pair",
592 &ls[n].addr_text); 612 &nls->addr_text);
593 return NGX_CONF_ERROR; 613 return NGX_CONF_ERROR;
594 } 614 }
615
616 next:
617 continue;
595 } 618 }
596 619
597 return NGX_CONF_OK; 620 return NGX_CONF_OK;
598 } 621 }
599 622