summaryrefslogtreecommitdiff
path: root/mail-mta/netqmail/outgoingip.patch
blob: c5c6632f77a92f1f5a29ef5187a8d4775853a8c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
diff --git i/qmail-control.9 w/qmail-control.9
index 822f397..f3f77d6 100644
--- i/qmail-control.9
+++ w/qmail-control.9
@@ -60,6 +60,7 @@ control default used by
 .I localiphost \fIme \fRqmail-smtpd
 .I locals \fIme \fRqmail-send
 .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
diff --git i/qmail-remote.8 w/qmail-remote.8
index 685f47c..0a29a0b 100644
--- i/qmail-remote.8
+++ w/qmail-remote.8
@@ -137,6 +137,13 @@ is the fully-qualified domain name of the server).
 .IR (tlshosts/<FQDN>.pem 
 takes precedence over this file however).
 
+.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.
diff --git i/qmail-remote.c w/qmail-remote.c
index 9787135..254b078 100644
--- i/qmail-remote.c
+++ w/qmail-remote.c
@@ -40,6 +40,7 @@ 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};
@@ -49,6 +50,7 @@ stralloc sender = {0};
 saa reciplist = {0};
 
 struct ip_address partner;
+struct ip_address outip;
 
 #ifdef TLS
 # include <sys/stat.h>
@@ -70,6 +72,7 @@ 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(); }
@@ -742,6 +745,7 @@ int flagcname;
 
 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)
@@ -756,6 +760,12 @@ void getcontrols()
     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();
 }
 
 void main(argc,argv)
@@ -854,7 +864,7 @@ char **argv;
     smtpfd = socket(AF_INET,SOCK_STREAM,0);
     if (smtpfd == -1) temp_oserr();
  
-    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 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
diff --git i/qmail-showctl.c w/qmail-showctl.c
index a24aa63..4e44beb 100644
--- i/qmail-showctl.c
+++ w/qmail-showctl.c
@@ -230,6 +230,7 @@ void main()
   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: ",".");
diff --git i/remoteinfo.c w/remoteinfo.c
index c7abd70..5532813 100644
--- i/remoteinfo.c
+++ w/remoteinfo.c
@@ -44,12 +44,12 @@ int timeout;
   s = socket(AF_INET,SOCK_STREAM,0);
   if (s == -1) return 0;
  
-  byte_zero(&sin,sizeof(sin));
+/*  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; }
+  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;
diff --git i/timeoutconn.c w/timeoutconn.c
index 33a16d9..e768b52 100644
--- i/timeoutconn.c
+++ w/timeoutconn.c
@@ -10,9 +10,10 @@
 #include "byte.h"
 #include "timeoutconn.h"
 
-int timeoutconn(s,ip,port,timeout)
+int timeoutconn(s,ip,outip,port,timeout)
 int s;
 struct ip_address *ip;
+struct ip_address *outip;
 unsigned int port;
 int timeout;
 {
@@ -22,6 +23,13 @@ int timeout;
   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;