comparison src/stream/ngx_stream_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 2ab7b55ae4a0
children 2af1287d2da7 91ad1abfb285
comparison
equal deleted inserted replaced
8103:b809f53d3f5b 8104:4cc2bfeff46c
576 ngx_stream_core_srv_conf_t *cscf = conf; 576 ngx_stream_core_srv_conf_t *cscf = conf;
577 577
578 ngx_str_t *value, size; 578 ngx_str_t *value, size;
579 ngx_url_t u; 579 ngx_url_t u;
580 ngx_uint_t i, n, backlog; 580 ngx_uint_t i, n, backlog;
581 ngx_stream_listen_t *ls, *als; 581 ngx_stream_listen_t *ls, *als, *nls;
582 ngx_stream_core_main_conf_t *cmcf; 582 ngx_stream_core_main_conf_t *cmcf;
583 583
584 cscf->listen = 1; 584 cscf->listen = 1;
585 585
586 value = cf->args->elts; 586 value = cf->args->elts;
600 return NGX_CONF_ERROR; 600 return NGX_CONF_ERROR;
601 } 601 }
602 602
603 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); 603 cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
604 604
605 ls = ngx_array_push_n(&cmcf->listen, u.naddrs); 605 ls = ngx_array_push(&cmcf->listen);
606 if (ls == NULL) { 606 if (ls == NULL) {
607 return NGX_CONF_ERROR; 607 return NGX_CONF_ERROR;
608 } 608 }
609 609
610 ngx_memzero(ls, sizeof(ngx_stream_listen_t)); 610 ngx_memzero(ls, sizeof(ngx_stream_listen_t));
884 return "\"fastopen\" parameter is incompatible with \"udp\""; 884 return "\"fastopen\" parameter is incompatible with \"udp\"";
885 } 885 }
886 #endif 886 #endif
887 } 887 }
888 888
889 als = cmcf->listen.elts;
890
891 for (n = 0; n < u.naddrs; n++) { 889 for (n = 0; n < u.naddrs; n++) {
892 ls[n] = ls[0]; 890
893 891 for (i = 0; i < n; i++) {
894 ls[n].sockaddr = u.addrs[n].sockaddr; 892 if (ngx_cmp_sockaddr(u.addrs[n].sockaddr, u.addrs[n].socklen,
895 ls[n].socklen = u.addrs[n].socklen; 893 u.addrs[i].sockaddr, u.addrs[i].socklen, 0)
896 ls[n].addr_text = u.addrs[n].name; 894 == NGX_OK)
897 ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); 895 {
898 896 goto next;
899 for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { 897 }
900 if (ls[n].type != als[i].type) { 898 }
899
900 if (n != 0) {
901 nls = ngx_array_push(&cmcf->listen);
902 if (nls == NULL) {
903 return NGX_CONF_ERROR;
904 }
905
906 *nls = *ls;
907
908 } else {
909 nls = ls;
910 }
911
912 nls->sockaddr = u.addrs[n].sockaddr;
913 nls->socklen = u.addrs[n].socklen;
914 nls->addr_text = u.addrs[n].name;
915 nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
916
917 als = cmcf->listen.elts;
918
919 for (i = 0; i < cmcf->listen.nelts - 1; i++) {
920 if (nls->type != als[i].type) {
901 continue; 921 continue;
902 } 922 }
903 923
904 if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, 924 if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
905 ls[n].sockaddr, ls[n].socklen, 1) 925 nls->sockaddr, nls->socklen, 1)
906 != NGX_OK) 926 != NGX_OK)
907 { 927 {
908 continue; 928 continue;
909 } 929 }
910 930
911 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 931 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
912 "duplicate \"%V\" address and port pair", 932 "duplicate \"%V\" address and port pair",
913 &ls[n].addr_text); 933 &nls->addr_text);
914 return NGX_CONF_ERROR; 934 return NGX_CONF_ERROR;
915 } 935 }
936
937 next:
938 continue;
916 } 939 }
917 940
918 return NGX_CONF_OK; 941 return NGX_CONF_OK;
919 } 942 }
920 943