[prev in list] [next in list] [prev in thread] [next in thread]
List: qmail
Subject: patch: qmail-remote.c - bind to specified local address based on
From: "Paul J. Park" <paul () idealworldinc ! com>
Date: 2005-04-26 23:29:32
Message-ID: 1114558171.2543.42.camel () eden ! idealworldinc ! com
[Download RAW message or body]
My first foray into the guts of qmail, but I think that this basically
does something that I've been wanting qmail to do for a while. The
synopsis can be found at
http://www.idealworldinc.com/qmail/qmail-outbound-bind.html
We use this on a couple of low-volume servers that host a number of
domains. YMMV.
No manpage or qmail-showctl updates, sadly.
Cheers!
Paul Park
["qmail-remote.c.diff" (qmail-remote.c.diff)]
*** qmail-remote.c.orig 2005-04-26 07:01:53.000000000 -0400
--- qmail-remote.c 2005-04-26 17:10:11.000000000 -0400
***************
*** 31,36 ****
--- 31,43 ----
#include "timeoutwrite.h"
#endif
+ /*
+ * BIND_CONTROL:
+ * non-zero => bind failure is a temporary resource problem.
+ * zero => ignore bind failure.
+ */
+ #define BIND_CONTROL 1
+
#ifdef TLS
#include <sys/stat.h>
#include <openssl/ssl.h>
***************
*** 51,56 ****
--- 58,67 ----
stralloc helohost = {0};
stralloc routes = {0};
struct constmap maproutes;
+ #ifdef BIND_CONTROL
+ stralloc bindings = {0};
+ struct constmap mapbindings;
+ #endif /* BIND_CONTROL */
stralloc host = {0};
stralloc sender = {0};
***************
*** 577,582 ****
--- 588,606 ----
case 1:
if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
}
+ #ifdef BIND_CONTROL
+ /*
+ * Swish in the bind control map.
+ */
+ switch(control_readfile(&bindings,"control/domainoutbind",0)) {
+ case -1:
+ temp_control();
+ case 0:
+ if (!constmap_init(&mapbindings,"",0,1)) temp_nomem(); break;
+ case 1:
+ if (!constmap_init(&mapbindings,bindings.s,bindings.len,1)) temp_nomem(); break;
+ }
+ #endif /* BIND_CONTROL */
#ifdef TLS
if (control_rldef(&tlsclientciphers,"control/tlsclientciphers",0,"DEFAULT") != 1)
temp_control();
***************
*** 596,601 ****
--- 620,630 ----
int flagallaliases;
int flagalias;
char *relayhost;
+ #ifdef BIND_CONTROL
+ char *bindaddress = (char *) NULL;
+ stralloc bindhost = {0};
+ ipalloc bindip = {0};
+ #endif /* BIND_CONTROL */
#ifdef TLS
sig_alarmcatch(sigalrm);
***************
*** 624,632 ****
if (!stralloc_copys(&host,relayhost)) temp_nomem();
}
-
addrmangle(&sender,argv[2],&flagalias,0);
if (!saa_readyplus(&reciplist,0)) temp_nomem();
if (ipme_init() != 1) temp_oserr();
--- 653,689 ----
if (!stralloc_copys(&host,relayhost)) temp_nomem();
}
addrmangle(&sender,argv[2],&flagalias,0);
+ #ifdef BIND_CONTROL
+ /*
+ * Look for a match on the sender, then failing that, look for a match
+ * on the rhs of the address.
+ */
+ if (!(bindaddress = constmap(&mapbindings, sender.s, sender.len))) {
+ int atindx = str_rchr(sender.s, '@');
+ if (sender.s[atindx]) {
+ atindx++;
+ bindaddress = constmap(&mapbindings, sender.s + atindx,
+ sender.len - atindx);
+ }
+ }
+
+ /*
+ * Now resolve anything we found...
+ */
+ if (bindaddress) {
+ if (!stralloc_copys(&bindhost, bindaddress)) temp_nomem();
+ switch (dns_ip(&bindip, &bindhost)) {
+ case DNS_MEM: temp_nomem();
+ case DNS_SOFT: temp_dns();
+ case DNS_HARD: perm_dns();
+ case 1:
+ if (bindip.len <= 0) temp_dns();
+ }
+ }
+ #endif /* BIND_CONTROL */
+
if (!saa_readyplus(&reciplist,0)) temp_nomem();
if (ipme_init() != 1) temp_oserr();
***************
*** 675,680 ****
--- 732,760 ----
smtpfd = socket(AF_INET,SOCK_STREAM,0);
if (smtpfd == -1) temp_oserr();
+ #ifdef BIND_CONTROL
+ /*
+ * Finally, if we have a match from above, make sure we bind to the
+ * address we were told above.
+ */
+ if (bindip.len) {
+ struct sockaddr_in bind2;
+ byte_zero(&bind2, sizeof(bind2));
+ /*
+ * What to do about multiple A records? Ignore them!
+ */
+ byte_copy(&bind2.sin_addr, sizeof(bind2.sin_addr), &bindip.ix[0].ip);
+ bind2.sin_family = AF_INET;
+ if (bind(smtpfd, (struct sockaddr *) &bind2, sizeof(bind2))) {
+ #if BIND_CONTROL
+ temp_oserr();
+ #else /* !BIND_CONTROL */
+ /* I don't care, what you say... */
+ #endif /* !BIND_CONTROL */
+ }
+ }
+ #endif /* BIND_CONTROL */
+
if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
tcpto_err(&ip.ix[i].ip,0);
partner = ip.ix[i].ip;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic