diff -P -C 5 -r -N qmail-1.03-jms1.7.08/Makefile qmail-1.03-jms1.7.08-st/Makefile
*** qmail-1.03-jms1.7.08/Makefile	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/Makefile	Tue Dec 23 20:55:11 2008
***************
*** 1571,1581 ****
  	timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o \
  	constmap.o received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a \
  	fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
  	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o \
  	auto_break.o base64.o `cat socket.lib` `cat dns.lib` \
! 	-lssl -lcrypto -lcrypt
  
  qmail-smtpd.0: \
  qmail-smtpd.8
  	nroff -man qmail-smtpd.8 > qmail-smtpd.0
  
--- 1571,1581 ----
  	timeoutwrite.o ip.o ipme.o ipalloc.o strsalloc.o control.o \
  	constmap.o received.o date822fmt.o now.o qmail.o spf.o dns.o cdb.a \
  	fd.a wait.a datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
  	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o \
  	auto_break.o base64.o `cat socket.lib` `cat dns.lib` \
! 	-lssl -lcrypto
  
  qmail-smtpd.0: \
  qmail-smtpd.8
  	nroff -man qmail-smtpd.8 > qmail-smtpd.0
  
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/cdb_seek.c qmail-1.03-jms1.7.08-st/cdb_seek.c
*** qmail-1.03-jms1.7.08/cdb_seek.c	Mon Jun 15 12:53:16 1998
--- qmail-1.03-jms1.7.08-st/cdb_seek.c	Tue Dec 23 20:55:11 2008
***************
*** 1,8 ****
  #include <sys/types.h>
  #include <errno.h>
- extern int errno;
  #include "cdb.h"
  
  #ifndef SEEK_SET
  #define SEEK_SET 0
  #endif
--- 1,7 ----
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/dns.c qmail-1.03-jms1.7.08-st/dns.c
*** qmail-1.03-jms1.7.08/dns.c	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/dns.c	Tue Dec 23 20:55:11 2008
***************
*** 5,16 ****
  #include <arpa/nameser.h>
  #include <resolv.h>
  #include <errno.h>
  extern int res_query();
  extern int res_search();
- extern int errno;
- extern int h_errno;
  #include "ip.h"
  #include "ipalloc.h"
  #include "strsalloc.h"
  #include "fmt.h"
  #include "alloc.h"
--- 5,14 ----
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/error.3 qmail-1.03-jms1.7.08-st/error.3
*** qmail-1.03-jms1.7.08/error.3	Mon Jun 15 12:53:16 1998
--- qmail-1.03-jms1.7.08-st/error.3	Tue Dec 23 20:55:11 2008
***************
*** 1,12 ****
  .TH error 3
  .SH NAME
  error \- syscall error codes
  .SH SYNTAX
  .B #include <error.h>
! 
! extern int \fBerrno\fP;
  
  extern int \fBerror_intr\fP;
  .br
  extern int \fBerror_nomem\fP;
  .br
--- 1,11 ----
  .TH error 3
  .SH NAME
  error \- syscall error codes
  .SH SYNTAX
  .B #include <error.h>
! .B #include <errno.h>
  
  extern int \fBerror_intr\fP;
  .br
  extern int \fBerror_nomem\fP;
  .br
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/error.h qmail-1.03-jms1.7.08-st/error.h
*** qmail-1.03-jms1.7.08/error.h	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/error.h	Tue Dec 23 20:55:11 2008
***************
*** 1,9 ****
  #ifndef ERROR_H
  #define ERROR_H
  
- /* extern int errno; */
  #include <errno.h>
  
  extern int error_intr;
  extern int error_nomem;
  extern int error_noent;
--- 1,8 ----
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/qmail-control.9 qmail-1.03-jms1.7.08-st/qmail-control.9
*** qmail-1.03-jms1.7.08/qmail-control.9	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/qmail-control.9	Tue Dec 23 20:55:11 2008
***************
*** 63,72 ****
--- 63,73 ----
  .I idhost	\fIme	\fRqmail-inject
  .I localiphost	\fIme	\fRqmail-smtpd
  .I locals	\fIme	\fRqmail-send
  .I mfcheck	\fR0	\fRqmail-smtpd
  .I morercpthosts	\fR(none)	\fRqmail-smtpd
+ .I outgoingip   \fR0.0.0.0      \fRqmail-remote
  .I percenthack	\fR(none)	\fRqmail-send
  .I plusdomain	\fIme	\fRqmail-inject
  .I qmqpservers	\fR(none)	\fRqmail-qmqpc
  .I queuelifetime	\fR604800	\fRqmail-send
  .I rcpthosts	\fR(none)	\fRqmail-smtpd
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/qmail-remote.8 qmail-1.03-jms1.7.08-st/qmail-remote.8
*** qmail-1.03-jms1.7.08/qmail-remote.8	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/qmail-remote.8	Tue Dec 23 20:55:11 2008
***************
*** 122,131 ****
--- 122,138 ----
  if that is supplied;
  otherwise
  .B qmail-remote
  refuses to run.
  .TP 5
+ .I outgoingip
+ IP address to be used on outgoing connections.
+ Default: system-defined.
+ The value 
+ .IR 0.0.0.0 
+ is equivalent to the system default.
+ .TP 5
  .I smtproutes
  Artificial SMTP routes.
  Each route has the form
  
  .EX
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/qmail-remote.c qmail-1.03-jms1.7.08-st/qmail-remote.c
*** qmail-1.03-jms1.7.08/qmail-remote.c	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/qmail-remote.c	Tue Dec 23 20:55:11 2008
***************
*** 52,61 ****
--- 52,62 ----
  GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
  GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
  static stralloc sauninit = {0};
  
  stralloc helohost = {0};
+ stralloc outgoingip = {0};
  stralloc routes = {0};
  struct constmap maproutes;
  stralloc host = {0};
  stralloc sender = {0};
  stralloc auth_smtp_user = {0};
***************
*** 63,81 ****
--- 64,84 ----
  stralloc auth_smtp_plain = {0};
  
  saa reciplist = {0};
  
  struct ip_address partner;
+ struct ip_address outip;
  
  void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
  void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
  void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
  void outsafe(sa) stralloc *sa; { int i; char ch;
  for (i = 0;i < sa->len;++i) {
  ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?';
  if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
  
+ void temp_noip() { out("Zinvalid ipaddr in control/outgoingip (#4.3.0)\n"); zerodie(); }
  void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
  void temp_oserr() { out("Z\
  System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); }
  void temp_noconn() { out("Z\
  Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); }
***************
*** 368,378 ****
     if (stat(servercert.s,&st) == 0)  needtlsauth = 1;
    }
  #endif
  
    code = smtpcode();
!   if (code >= 400 && code < 600) return; /* try next MX, see RFC 2821 */
    if (code != 220) quit("ZConnected to "," but greeting failed");
   
    substdio_puts(&smtpto,"EHLO ");
    substdio_put(&smtpto,helohost.s,helohost.len);
    substdio_puts(&smtpto,"\r\n");
--- 371,382 ----
     if (stat(servercert.s,&st) == 0)  needtlsauth = 1;
    }
  #endif
  
    code = smtpcode();
!   if (code >= 500 && code < 600) quit("DConnected to "," but greeting failed");
!   if (code >= 400 && code < 500) return; /* try next MX, see RFC 2821 */
    if (code != 220) quit("ZConnected to "," but greeting failed");
   
    substdio_puts(&smtpto,"EHLO ");
    substdio_put(&smtpto,helohost.s,helohost.len);
    substdio_puts(&smtpto,"\r\n");
***************
*** 380,390 ****
    if (smtpcode() != 250){
     substdio_puts(&smtpto,"HELO ");
     substdio_put(&smtpto,helohost.s,helohost.len);
     substdio_puts(&smtpto,"\r\n");
     substdio_flush(&smtpto);
!    if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
    }
  
  #ifdef TLS
    if(can_tls) {
    i = 0; 
--- 384,396 ----
    if (smtpcode() != 250){
     substdio_puts(&smtpto,"HELO ");
     substdio_put(&smtpto,helohost.s,helohost.len);
     substdio_puts(&smtpto,"\r\n");
     substdio_flush(&smtpto);
!    code = smtpcode();
!    if (code >= 500) quit("DConnected to "," but my name was rejected");
!    if (code != 250) quit("ZConnected to "," but my name was rejected");
    }
  
  #ifdef TLS
    if(can_tls) {
    i = 0; 
***************
*** 615,624 ****
--- 621,631 ----
    if (!stralloc_cat(saout,&canonhost)) temp_nomem();
  }
  
  void getcontrols()
  {
+   int r;
    if (control_init() == -1) temp_control();
    if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control();
    if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
      temp_control();
    if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1)
***************
*** 629,638 ****
--- 636,652 ----
      case 0:
        if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break;
      case 1:
        if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
    }
+   r = control_readline(&outgoingip,"control/outgoingip");
+   if (-1 == r) { if (errno == error_nomem) temp_nomem(); temp_control(); }
+   if (0 == r && !stralloc_copys(&outgoingip, "0.0.0.0")) temp_nomem();
+   if (str_equal(outgoingip.s, "0.0.0.0"))
+     { outip.d[0]=outip.d[1]=outip.d[2]=outip.d[3]=(unsigned long) 0; }
+   else if (!ip_scan(outgoingip.s, &outip)) temp_noip();
+ 
  #ifdef TLS
    if (control_rldef(&tlsclientciphers,"control/tlsclientciphers",0,"DEFAULT") != 1)
      temp_control();
    if(!stralloc_0(&tlsclientciphers)) temp_nomem();
  #endif
***************
*** 756,766 ****
      if (smtpfd == -1) temp_oserr();
  
      bind_by_sender ( smtpfd , sender.s , 1 ) ;
      bind_by_remoteip ( smtpfd , &ip.ix[i].ip , 0 ) ;
  
!     if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
        tcpto_err(&ip.ix[i].ip,0);
        partner = ip.ix[i].ip;
  #ifdef TLS
        smtp(ip.ix[i].fqdn); /* does not return */
  #else
--- 770,780 ----
      if (smtpfd == -1) temp_oserr();
  
      bind_by_sender ( smtpfd , sender.s , 1 ) ;
      bind_by_remoteip ( smtpfd , &ip.ix[i].ip , 0 ) ;
  
!     if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) port,timeoutconnect) == 0) {
        tcpto_err(&ip.ix[i].ip,0);
        partner = ip.ix[i].ip;
  #ifdef TLS
        smtp(ip.ix[i].fqdn); /* does not return */
  #else
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/qmail-showctl.c qmail-1.03-jms1.7.08-st/qmail-showctl.c
*** qmail-1.03-jms1.7.08/qmail-showctl.c	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/qmail-showctl.c	Tue Dec 23 20:55:11 2008
***************
*** 234,243 ****
--- 234,244 ----
    do_str("helohost",1,"helohost","SMTP client HELO host name is ");
    do_str("idhost",1,"idhost","Message-ID host name is ");
    do_str("localiphost",1,"localiphost","Local IP address becomes ");
    do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally.");
    do_str("me",0,"undefined! Uh-oh","My name is ");
+   do_str("outgoingip",0,"0.0.0.0","Outgoing IP address is ");
    do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@",".");
    do_str("plusdomain",1,"plusdomain","Plus domain name is ");
    do_lst("qmqpservers","No QMQP servers.","QMQP server: ",".");
    do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds");
  
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/qmail.c qmail-1.03-jms1.7.08-st/qmail.c
*** qmail-1.03-jms1.7.08/qmail.c	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/qmail.c	Tue Dec 23 20:55:18 2008
***************
*** 129,139 ****
  
    switch(exitcode) {
      case  1: return "IYour SPAM has been ignored.";
      case 115: /* compatibility */
      case 11: return "Denvelope address too long for qq (#5.1.3)";
!     case 31: return "Dmail server permanently rejected message (#5.3.0)";
      case 32: return "Dwe do not accept SPAM (#5.3.0)";
      case 51: return "Zqq out of memory (#4.3.0)";
      case 52: return "Zqq timeout (#4.3.0)";
      case 53: return "Zqq write error or disk full (#4.3.0)";
      case 0: if (!qq->flagerr) return ""; /* fall through */
--- 129,139 ----
  
    switch(exitcode) {
      case  1: return "IYour SPAM has been ignored.";
      case 115: /* compatibility */
      case 11: return "Denvelope address too long for qq (#5.1.3)";
!     case 31: return "GWe have reasons to believe this mail is spam (#5.7.1)";
      case 32: return "Dwe do not accept SPAM (#5.3.0)";
      case 51: return "Zqq out of memory (#4.3.0)";
      case 52: return "Zqq timeout (#4.3.0)";
      case 53: return "Zqq write error or disk full (#4.3.0)";
      case 0: if (!qq->flagerr) return ""; /* fall through */
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/remoteinfo.c qmail-1.03-jms1.7.08-st/remoteinfo.c
*** qmail-1.03-jms1.7.08/remoteinfo.c	Mon Jun 15 12:53:16 1998
--- qmail-1.03-jms1.7.08-st/remoteinfo.c	Tue Dec 23 20:55:18 2008
***************
*** 42,57 ****
    t = timeout;
   
    s = socket(AF_INET,SOCK_STREAM,0);
    if (s == -1) return 0;
   
!   byte_zero(&sin,sizeof(sin));
    sin.sin_family = AF_INET;
    byte_copy(&sin.sin_addr,4,ipl);
    sin.sin_port = 0;
!   if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; }
!   if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; }
    fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY);
   
    len = 0;
    len += fmt_ulong(line + len,rp);
    len += fmt_str(line + len," , ");
--- 42,57 ----
    t = timeout;
   
    s = socket(AF_INET,SOCK_STREAM,0);
    if (s == -1) return 0;
   
! /*  byte_zero(&sin,sizeof(sin));
    sin.sin_family = AF_INET;
    byte_copy(&sin.sin_addr,4,ipl);
    sin.sin_port = 0;
!   if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } */
!   if (timeoutconn(s,ipr,ipl,113,timeout) == -1) { close(s); return 0; }
    fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY);
   
    len = 0;
    len += fmt_ulong(line + len,rp);
    len += fmt_str(line + len," , ");
diff -P -C 5 -r -N qmail-1.03-jms1.7.08/timeoutconn.c qmail-1.03-jms1.7.08-st/timeoutconn.c
*** qmail-1.03-jms1.7.08/timeoutconn.c	Tue Dec 23 20:56:27 2008
--- qmail-1.03-jms1.7.08-st/timeoutconn.c	Tue Dec 23 20:55:18 2008
***************
*** 89,110 ****
    bindlocal = 1 ;
    return 0;
  }
  
  
! int timeoutconn(s,ip,port,timeout)
  int s;
  struct ip_address *ip;
  unsigned int port;
  int timeout;
  {
    char ch;
    struct sockaddr_in sin;
    struct sockaddr_in salocal;
    char *x;
    fd_set wfds;
    struct timeval tv;
   
    byte_zero(&sin,sizeof(sin));
    byte_copy(&sin.sin_addr,4,ip);
    x = (char *) &sin.sin_port;
    x[1] = port; port >>= 8; x[0] = port;
--- 89,118 ----
    bindlocal = 1 ;
    return 0;
  }
  
  
! int timeoutconn(s,ip,outip,port,timeout)
  int s;
  struct ip_address *ip;
+ struct ip_address *outip;
  unsigned int port;
  int timeout;
  {
    char ch;
    struct sockaddr_in sin;
    struct sockaddr_in salocal;
    char *x;
    fd_set wfds;
    struct timeval tv;
+ 
+   /* bind() an outgoing ipaddr */
+   byte_zero(&sin,sizeof(sin));
+   byte_copy(&sin.sin_addr.s_addr,4,outip);
+   sin.sin_family = AF_INET;
+ 
+   if (-1 == bind(s,(struct sockaddr *) &sin,sizeof(sin))) return -1;
   
    byte_zero(&sin,sizeof(sin));
    byte_copy(&sin.sin_addr,4,ip);
    x = (char *) &sin.sin_port;
    x[1] = port; port >>= 8; x[0] = port;
