[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