Mercurial > hg > nginx
comparison src/mail/ngx_mail_core_module.c @ 7478:4f9b72a229c1
Multiple addresses in "listen".
Previously only one address was used by the listen directive handler even if
host name resolved to multiple addresses. Now a separate listening socket is
created for each address.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 15 Mar 2019 15:45:56 +0300 |
parents | 7f955d3b9a0d |
children | 12ea1de7d87c |
comparison
equal
deleted
inserted
replaced
7477:c74904a17021 | 7478:4f9b72a229c1 |
---|---|
295 { | 295 { |
296 ngx_mail_core_srv_conf_t *cscf = conf; | 296 ngx_mail_core_srv_conf_t *cscf = conf; |
297 | 297 |
298 ngx_str_t *value, size; | 298 ngx_str_t *value, size; |
299 ngx_url_t u; | 299 ngx_url_t u; |
300 ngx_uint_t i, m; | 300 ngx_uint_t i, n, m; |
301 ngx_mail_listen_t *ls; | 301 ngx_mail_listen_t *ls, *als; |
302 ngx_mail_module_t *module; | 302 ngx_mail_module_t *module; |
303 ngx_mail_core_main_conf_t *cmcf; | 303 ngx_mail_core_main_conf_t *cmcf; |
304 | 304 |
305 cscf->listen = 1; | 305 cscf->listen = 1; |
306 | 306 |
321 return NGX_CONF_ERROR; | 321 return NGX_CONF_ERROR; |
322 } | 322 } |
323 | 323 |
324 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); | 324 cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); |
325 | 325 |
326 ls = cmcf->listen.elts; | 326 ls = ngx_array_push_n(&cmcf->listen, u.naddrs); |
327 | |
328 for (i = 0; i < cmcf->listen.nelts; i++) { | |
329 | |
330 if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, | |
331 (struct sockaddr *) &u.sockaddr, u.socklen, 1) | |
332 != NGX_OK) | |
333 { | |
334 continue; | |
335 } | |
336 | |
337 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
338 "duplicate \"%V\" address and port pair", &u.url); | |
339 return NGX_CONF_ERROR; | |
340 } | |
341 | |
342 ls = ngx_array_push(&cmcf->listen); | |
343 if (ls == NULL) { | 327 if (ls == NULL) { |
344 return NGX_CONF_ERROR; | 328 return NGX_CONF_ERROR; |
345 } | 329 } |
346 | 330 |
347 ngx_memzero(ls, sizeof(ngx_mail_listen_t)); | 331 ngx_memzero(ls, sizeof(ngx_mail_listen_t)); |
348 | 332 |
349 ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); | |
350 | |
351 ls->socklen = u.socklen; | |
352 ls->backlog = NGX_LISTEN_BACKLOG; | 333 ls->backlog = NGX_LISTEN_BACKLOG; |
353 ls->rcvbuf = -1; | 334 ls->rcvbuf = -1; |
354 ls->sndbuf = -1; | 335 ls->sndbuf = -1; |
355 ls->wildcard = u.wildcard; | |
356 ls->ctx = cf->ctx; | 336 ls->ctx = cf->ctx; |
357 | 337 |
358 #if (NGX_HAVE_INET6) | 338 #if (NGX_HAVE_INET6) |
359 ls->ipv6only = 1; | 339 ls->ipv6only = 1; |
360 #endif | 340 #endif |
432 continue; | 412 continue; |
433 } | 413 } |
434 | 414 |
435 if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { | 415 if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { |
436 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) | 416 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) |
437 size_t len; | 417 if (ngx_strcmp(&value[i].data[10], "n") == 0) { |
438 u_char buf[NGX_SOCKADDR_STRLEN]; | 418 ls->ipv6only = 1; |
439 | 419 |
440 if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { | 420 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { |
441 | 421 ls->ipv6only = 0; |
442 if (ngx_strcmp(&value[i].data[10], "n") == 0) { | |
443 ls->ipv6only = 1; | |
444 | |
445 } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { | |
446 ls->ipv6only = 0; | |
447 | |
448 } else { | |
449 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
450 "invalid ipv6only flags \"%s\"", | |
451 &value[i].data[9]); | |
452 return NGX_CONF_ERROR; | |
453 } | |
454 | |
455 ls->bind = 1; | |
456 | 422 |
457 } else { | 423 } else { |
458 len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, | |
459 NGX_SOCKADDR_STRLEN, 1); | |
460 | |
461 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 424 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
462 "ipv6only is not supported " | 425 "invalid ipv6only flags \"%s\"", |
463 "on addr \"%*s\", ignored", len, buf); | 426 &value[i].data[9]); |
464 } | 427 return NGX_CONF_ERROR; |
465 | 428 } |
429 | |
430 ls->bind = 1; | |
466 continue; | 431 continue; |
467 #else | 432 #else |
468 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 433 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
469 "bind ipv6only is not supported " | 434 "bind ipv6only is not supported " |
470 "on this platform"); | 435 "on this platform"); |
586 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 551 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
587 "the invalid \"%V\" parameter", &value[i]); | 552 "the invalid \"%V\" parameter", &value[i]); |
588 return NGX_CONF_ERROR; | 553 return NGX_CONF_ERROR; |
589 } | 554 } |
590 | 555 |
556 als = cmcf->listen.elts; | |
557 | |
558 for (n = 0; n < u.naddrs; n++) { | |
559 ls[n] = ls[0]; | |
560 | |
561 ls[n].sockaddr = u.addrs[n].sockaddr; | |
562 ls[n].socklen = u.addrs[n].socklen; | |
563 ls[n].addr_text = u.addrs[n].name; | |
564 ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr); | |
565 | |
566 for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) { | |
567 | |
568 if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen, | |
569 ls[n].sockaddr, ls[n].socklen, 1) | |
570 != NGX_OK) | |
571 { | |
572 continue; | |
573 } | |
574 | |
575 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
576 "duplicate \"%V\" address and port pair", | |
577 &ls[n].addr_text); | |
578 return NGX_CONF_ERROR; | |
579 } | |
580 } | |
581 | |
591 return NGX_CONF_OK; | 582 return NGX_CONF_OK; |
592 } | 583 } |
593 | 584 |
594 | 585 |
595 static char * | 586 static char * |