Mercurial > dovecot > core-2.2
changeset 3181:ef3a07e0a634 HEAD
Give more understandable error message if imap/pop3 listen ports conflict.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 05 Mar 2005 22:02:07 +0200 |
parents | ef16bb8091aa |
children | 818c75139ac7 |
files | src/master/main.c src/master/master-settings.h |
diffstat | 2 files changed, 70 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/src/master/main.c Sat Mar 05 21:23:28 2005 +0200 +++ b/src/master/main.c Sat Mar 05 22:02:07 2005 +0200 @@ -206,14 +206,17 @@ i_warning("waitpid() failed: %m"); } -static struct ip_addr *resolve_ip(const char *name, unsigned int *port) +static void resolve_ip(const char *name, struct ip_addr *ip, unsigned int *port) { + struct ip_addr *ip_list; const char *p; - struct ip_addr *ip; int ret, ips_count; - if (name == NULL) - return NULL; /* defaults to "*" or "[::]" */ + if (name == NULL) { + /* defaults to "*" or "[::]" */ + ip->family = 0; + return; + } if (name[0] == '[') { /* IPv6 address */ @@ -242,20 +245,18 @@ if (strcmp(name, "*") == 0) { /* IPv4 any */ - ip = t_new(struct ip_addr, 1); net_get_ip_any4(ip); - return ip; + return; } if (strcmp(name, "::") == 0) { /* IPv6 any */ - ip = t_new(struct ip_addr, 1); net_get_ip_any6(ip); - return ip; + return; } /* Return the first IP if there happens to be multiple. */ - ret = net_gethostbyname(name, &ip, &ips_count); + ret = net_gethostbyname(name, &ip_list, &ips_count); if (ret != 0) { i_fatal("Can't resolve address %s: %s", name, net_gethosterror(ret)); @@ -264,29 +265,62 @@ if (ips_count < 1) i_fatal("No IPs for address: %s", name); - return ip; + *ip = ip_list[0]; +} + +static void +check_conflicts_set(const struct settings *set, const struct ip_addr *ip, + unsigned int port, const char *name1, const char *name2) +{ + if (set->listen_port == port && net_ip_compare(ip, &set->listen_ip) && + set->listen_fd > 0) { + i_fatal("Protocols %s and %s are listening in same ip/port", + name1, name2); + } + if (set->ssl_listen_port == port && + net_ip_compare(ip, &set->ssl_listen_ip) && set->ssl_listen_fd > 0) { + i_fatal("Protocols %ss and %s are listening in same ip/port", + name1, name2); + } +} + +static void check_conflicts(const struct ip_addr *ip, unsigned int port, + const char *proto) +{ + struct server_settings *server; + + for (server = settings_root; server != NULL; server = server->next) { + if (server->imap != NULL) { + check_conflicts_set(server->imap, ip, port, + "imap", proto); + } + if (server->pop3 != NULL) { + check_conflicts_set(server->pop3, ip, port, + "pop3", proto); + } + } } static void listen_protocols(struct settings *set, int retry) { - struct ip_addr *normal_ip, *ssl_ip, *ip; + struct ip_addr *ip; const char *const *proto; - unsigned int normal_port, ssl_port, port; + unsigned int port; int *fd, i; - normal_port = set->protocol == MAIL_PROTOCOL_IMAP ? 143 : 110; + set->listen_port = set->protocol == MAIL_PROTOCOL_IMAP ? 143 : 110; #ifdef HAVE_SSL - ssl_port = set->protocol == MAIL_PROTOCOL_IMAP ? 993 : 995; + set->ssl_listen_port = set->protocol == MAIL_PROTOCOL_IMAP ? 993 : 995; #else - ssl_port = 0; + set->ssl_listen_port = 0; #endif /* resolve */ - normal_ip = resolve_ip(set->listen, &normal_port); - ssl_ip = resolve_ip(set->ssl_listen, &ssl_port); + resolve_ip(set->listen, &set->listen_ip, &set->listen_port); + resolve_ip(set->ssl_listen, &set->ssl_listen_ip, &set->ssl_listen_port); - if (ssl_ip == NULL && set->ssl_listen == NULL) - ssl_ip = normal_ip; + if (set->ssl_listen_ip.family == 0 && set->ssl_listen == NULL) + set->ssl_listen_ip = set->listen_ip; /* register wanted protocols */ proto = t_strsplit_spaces(set->protocols, " "); @@ -295,24 +329,28 @@ if (strcasecmp(*proto, "imap") == 0) { if (set->protocol == MAIL_PROTOCOL_IMAP) { fd = &set->listen_fd; - port = normal_port; ip = normal_ip; + port = set->listen_port; + ip = &set->listen_ip; } } else if (strcasecmp(*proto, "imaps") == 0) { if (set->protocol == MAIL_PROTOCOL_IMAP && !set->ssl_disable) { fd = &set->ssl_listen_fd; - port = ssl_port; ip = ssl_ip; + port = set->ssl_listen_port; + ip = &set->ssl_listen_ip; } } else if (strcasecmp(*proto, "pop3") == 0) { if (set->protocol == MAIL_PROTOCOL_POP3) { fd = &set->listen_fd; - port = normal_port; ip = normal_ip; + port = set->listen_port; + ip = &set->listen_ip; } } else if (strcasecmp(*proto, "pop3s") == 0) { if (set->protocol == MAIL_PROTOCOL_POP3 && !set->ssl_disable) { fd = &set->ssl_listen_fd; - port = ssl_port; ip = ssl_ip; + port = set->ssl_listen_port; + ip = &set->ssl_listen_ip; } } else { i_fatal("Unknown protocol %s", *proto); @@ -329,7 +367,11 @@ else { for (i = 0; i < 10; i++) { *fd = net_listen(ip, &port, 8); - if (*fd != -1 || errno != EADDRINUSE || !retry) + if (*fd != -1 || errno != EADDRINUSE) + break; + + check_conflicts(ip, port, *proto); + if (!retry) break; /* wait a while and try again. we're SIGHUPing
--- a/src/master/master-settings.h Sat Mar 05 21:23:28 2005 +0200 +++ b/src/master/master-settings.h Sat Mar 05 22:02:07 2005 +0200 @@ -1,6 +1,8 @@ #ifndef __MASTER_SETTINGS_H #define __MASTER_SETTINGS_H +#include "network.h" + enum mail_protocol { MAIL_PROTOCOL_ANY, MAIL_PROTOCOL_IMAP, @@ -103,6 +105,8 @@ uid_t login_uid; int listen_fd, ssl_listen_fd; + struct ip_addr listen_ip, ssl_listen_ip; + unsigned int listen_port, ssl_listen_port; }; struct socket_settings {