Hi

would it be possible to consider a new parameter for replication:
doveadm_local_ip which allows the source ip address to be set when
connection to a remote dovecot for replication?

It could be useful when the network interface has multiple ips and a
specific one is used for mail services. See attached proposal. I tested
against 2.2.36 only. It applies correctly against 2.3.4 with a warning,.

John


--- dovecot-2.2.36/src/doveadm/doveadm-settings.c       2018-04-30 
15:52:05.000000000 +0200
+++ dovecot-2.2.36-new/src/doveadm/doveadm-settings.c   2019-01-04 
14:59:11.556270077 +0100
@@ -62,6 +62,7 @@
        DEF(SET_UINT, doveadm_worker_count),
        DEF(SET_IN_PORT, doveadm_port),
        { SET_ALIAS, "doveadm_proxy_port", 0, NULL },
+       DEF(SET_STR, doveadm_local_ip),
        DEF(SET_STR, doveadm_username),
        DEF(SET_STR, doveadm_password),
        DEF(SET_STR, doveadm_allowed_commands),
@@ -91,6 +92,7 @@
        .doveadm_socket_path = "doveadm-server",
        .doveadm_worker_count = 0,
        .doveadm_port = 0,
+       .doveadm_local_ip = "",
        .doveadm_username = "doveadm",
        .doveadm_password = "",
        .doveadm_allowed_commands = "",
--- dovecot-2.2.36/src/doveadm/doveadm-settings.h       2017-10-05 
19:09:55.000000000 +0200
+++ dovecot-2.2.36-new/src/doveadm/doveadm-settings.h   2019-01-04 
14:57:32.906269791 +0100
@@ -19,6 +19,7 @@
        const char *doveadm_socket_path;
        unsigned int doveadm_worker_count;
        in_port_t doveadm_port;
+       const char *doveadm_local_ip;
        const char *doveadm_username;
        const char *doveadm_password;
        const char *doveadm_allowed_commands;
--- dovecot-2.2.36/src/doveadm/doveadm-util.c   2018-04-30 15:52:05.000000000 
+0200
+++ dovecot-2.2.36-new/src/doveadm/doveadm-util.c       2019-01-04 
15:26:09.326903786 +0100
@@ -100,19 +100,29 @@
 }
 
 static int
-doveadm_tcp_connect_port(const char *host, in_port_t port)
+doveadm_tcp_connect_port(const char *host, in_port_t port, char * my_ip)
 {
        struct ip_addr *ips;
        unsigned int ips_count;
        int ret, fd;
-
+       struct ip_addr my_net_ip;
+       int use_my_ip = 0;
+        if (strcmp(my_ip,"") == 0) {
+                i_info("No doveadm_local_ip setting, local ip supplied by 
operating system");
+       }
+       if (net_addr2ip(my_ip, &my_net_ip)) {
+                i_error("error using doveadm_local_ip setting %s",my_ip);
+       } else {
+                i_info("Using doveadm_local_ip setting: %s",my_ip);
+               use_my_ip = 1;
+       }
        alarm(DOVEADM_TCP_CONNECT_TIMEOUT_SECS);
        ret = net_gethostbyname(host, &ips, &ips_count);
        if (ret != 0) {
                i_fatal("Lookup of host %s failed: %s",
                        host, net_gethosterror(ret));
        }
-       fd = net_connect_ip_blocking(&ips[0], port, NULL);
+       fd = net_connect_ip_blocking(&ips[0], port, use_my_ip ? &my_net_ip : 
NULL);
        if (fd == -1) {
                i_fatal("connect(%s:%u) failed: %m",
                        net_ip2addr(&ips[0]), port);
@@ -121,7 +131,7 @@
        return fd;
 }
 
-int doveadm_tcp_connect(const char *target, in_port_t default_port)
+int doveadm_tcp_connect(const char *target, in_port_t default_port, char * 
my_ip)
 {
        const char *host;
        in_port_t port;
@@ -130,18 +140,18 @@
                i_fatal("Port not known for %s. Either set proxy_port "
                        "or use %s:port", target, target);
        }
-       return doveadm_tcp_connect_port(host, port);
+       return doveadm_tcp_connect_port(host, port, my_ip);
 }
 
 int doveadm_connect_with_default_port(const char *path,
-                                     in_port_t default_port)
+                                     in_port_t default_port, char * my_ip)
 {
        int fd;
 
        /* we'll assume UNIX sockets typically have an absolute path,
           or at the very least '/' somewhere. */
        if (strchr(path, '/') == NULL)
-               fd = doveadm_tcp_connect(path, default_port);
+               fd = doveadm_tcp_connect(path, default_port, my_ip);
        else {
                fd = net_connect_unix(path);
                if (fd == -1)
@@ -152,7 +162,7 @@
 
 int doveadm_connect(const char *path)
 {
-       return doveadm_connect_with_default_port(path, 0);
+       return doveadm_connect_with_default_port(path, 0, "");
 }
 
 int i_strccdascmp(const char *a, const char *b)
--- dovecot-2.2.36/src/doveadm/doveadm-util.h   2017-10-05 19:09:55.000000000 
+0200
+++ dovecot-2.2.36-new/src/doveadm/doveadm-util.h       2019-01-04 
14:55:52.263289702 +0100
@@ -13,9 +13,9 @@
 const char *unixdate2str(time_t timestamp);
 const char *doveadm_plugin_getenv(const char *name);
 int doveadm_connect(const char *path);
-int doveadm_tcp_connect(const char *target, in_port_t default_port);
+int doveadm_tcp_connect(const char *target, in_port_t default_port, char * 
my_ip);
 int doveadm_connect_with_default_port(const char *path,
-                                     in_port_t default_port);
+                                     in_port_t default_port, char * my_ip);
 
 void doveadm_load_modules(void);
 void doveadm_unload_modules(void);
--- dovecot-2.2.36/src/doveadm/server-connection.c      2018-04-30 
15:52:05.000000000 +0200
+++ dovecot-2.2.36-new/src/doveadm/server-connection.c  2019-01-04 
14:57:08.251519641 +0100
@@ -535,7 +535,7 @@
        conn->pool = pool;
        conn->server = server;
        conn->fd = doveadm_connect_with_default_port(server->name,
-                                                    
doveadm_settings->doveadm_port);
+                    
doveadm_settings->doveadm_port,doveadm_settings->doveadm_local_ip);
        net_set_nonblock(conn->fd, TRUE);
        conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE, FALSE);
        conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);

Reply via email to