-
Notifications
You must be signed in to change notification settings - Fork 1
/
qmail-1.03-qmtpc.patch
205 lines (195 loc) · 6.05 KB
/
qmail-1.03-qmtpc.patch
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
Apply this patch to qmail using "patch <patchfile". Recompile and
reinstall according to qmail's INSTALL documentation.
This patch to qmail-remote causes it to attempt qmtp first if the MX priority
indicates so. Read http://cr.yp.to/proto/mxps.txt for more information.
If you want this qmail-remote to be able to send email to you using qmtp,
then you should be running a qmtpd on port 209, and you should have your
lowest MX priority be 12801.
This is version 2 of the patch. Ian Lance Taylor fixed a problem
whereby qmtp did not properly fall back to smtp if the qmtp connect()
failed. This would cause problems for hosts with an MXPS QMTP
priority, or hosts whose firewall was rejecting QMTP but not SMTP.
diff -u orig/qmail-remote.c ./qmail-remote.c
--- orig/qmail-remote.c Fri Jan 5 01:31:36 2001
+++ ./qmail-remote.c Wed Jan 17 10:11:29 2001
@@ -1,4 +1,5 @@
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -14,6 +15,7 @@
#include "dns.h"
#include "alloc.h"
#include "quote.h"
+#include "fmt.h"
#include "ip.h"
#include "ipalloc.h"
#include "ipme.h"
@@ -31,8 +33,8 @@
#define HUGESMTPTEXT 5000
-#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */
-unsigned long port = PORT_SMTP;
+unsigned long smtp_port = 25; /* silly rabbit, /etc/services is for users */
+unsigned long qmtp_port = 209;
GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
@@ -70,6 +72,8 @@
Unable to switch to home directory. (#4.3.0)\n"); zerodie(); }
void temp_control() { out("Z\
Unable to read control files. (#4.3.0)\n"); zerodie(); }
+void temp_proto() { out("Z\
+recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); }
void perm_partialline() { out("D\
SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); }
void perm_usage() { out("D\
@@ -122,9 +126,9 @@
return r;
}
-char inbuf[1024];
+char inbuf[1500];
substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
-char smtptobuf[1024];
+char smtptobuf[1500];
substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf);
char smtpfrombuf[128];
substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf);
@@ -273,6 +277,113 @@
quit("K"," accepted message");
}
+int qmtp_priority(int pref)
+{
+ if (pref < 12800) return 0;
+ if (pref > 13055) return 0;
+ if (pref % 16 == 1) return 1;
+ return 0;
+}
+
+void qmtp()
+{
+ struct stat st;
+ unsigned long len;
+ int len2;
+ char *x;
+ int i;
+ int n;
+ unsigned char ch;
+ char num[FMT_ULONG];
+ int flagallok;
+
+ if (fstat(0,&st) == -1) quit("Z", " unable to fstat stdin");
+ len = st.st_size;
+
+ /* the following code was substantially taken from serialmail'ss serialqmtp.c */
+ substdio_put(&smtpto,num,fmt_ulong(num,len+1));
+ substdio_put(&smtpto,":\n",2);
+ while (len > 0) {
+ n = substdio_feed(&ssin);
+ if (n <= 0) _exit(32); /* wise guy again */
+ x = substdio_PEEK(&ssin);
+ substdio_put(&smtpto,x,n);
+ substdio_SEEK(&ssin,n);
+ len -= n;
+ }
+ substdio_put(&smtpto,",",1);
+
+ len = sender.len;
+ substdio_put(&smtpto,num,fmt_ulong(num,len));
+ substdio_put(&smtpto,":",1);
+ substdio_put(&smtpto,sender.s,sender.len);
+ substdio_put(&smtpto,",",1);
+
+ len = 0;
+ for (i = 0;i < reciplist.len;++i)
+ len += fmt_ulong(num,reciplist.sa[i].len) + 1 + reciplist.sa[i].len + 1;
+ substdio_put(&smtpto,num,fmt_ulong(num,len));
+ substdio_put(&smtpto,":",1);
+ for (i = 0;i < reciplist.len;++i) {
+ substdio_put(&smtpto,num,fmt_ulong(num,reciplist.sa[i].len));
+ substdio_put(&smtpto,":",1);
+ substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len);
+ substdio_put(&smtpto,",",1);
+ }
+ substdio_put(&smtpto,",",1);
+ substdio_flush(&smtpto);
+
+ flagallok = 1;
+
+ for (i = 0;i < reciplist.len;++i) {
+ len = 0;
+ for (;;) {
+ get(&ch);
+ if (ch == ':') break;
+ if (len > 200000000) temp_proto();
+ if (ch - '0' > 9) temp_proto();
+ len = 10 * len + (ch - '0');
+ }
+ if (!len) temp_proto();
+ get(&ch); --len;
+ if ((ch != 'Z') && (ch != 'D') && (ch != 'K')) temp_proto();
+
+ if (!stralloc_copyb(&smtptext,&ch,1)) temp_proto();
+ if (!stralloc_cats(&smtptext,"qmtp: ")) temp_nomem();
+
+ while (len > 0) {
+ get(&ch);
+ --len;
+ }
+
+ for (len = 0;len < smtptext.len;++len) {
+ ch = smtptext.s[len];
+ if ((ch < 32) || (ch > 126)) smtptext.s[len] = '?';
+ }
+ get(&ch);
+ if (ch != ',') temp_proto();
+ smtptext.s[smtptext.len-1] = '\n';
+
+ if (smtptext.s[0] == 'K') out("r");
+ else if (smtptext.s[0] == 'D') {
+ out("h");
+ flagallok = 0;
+ }
+ else { /* if (smtptext.s[0] == 'Z') */
+ out("s");
+ flagallok = 0;
+ }
+ if (substdio_put(subfdoutsmall,smtptext.s+1,smtptext.len-1) == -1) temp_noconn();
+ zero();
+ }
+ if (!flagallok) {
+ out("DGiving up on ");outhost();out("\n");
+ } else {
+ out("KAll received okay by ");outhost();out("\n");
+ }
+ zerodie();
+}
+
stralloc canonhost = {0};
stralloc canonbox = {0};
@@ -357,7 +468,7 @@
if (relayhost) {
i = str_chr(relayhost,':');
if (relayhost[i]) {
- scan_ulong(relayhost + i + 1,&port);
+ scan_ulong(relayhost + i + 1,&smtp_port);
relayhost[i] = 0;
}
if (!stralloc_copys(&host,relayhost)) temp_nomem();
@@ -414,7 +525,17 @@
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 (qmtp_priority(ip.ix[i].pref)) {
+ if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) qmtp_port,timeoutconnect) == 0) {
+ tcpto_err(&ip.ix[i].ip,0);
+ partner = ip.ix[i].ip;
+ qmtp(); /* does not return */
+ }
+ close(smtpfd);
+ smtpfd = socket(AF_INET,SOCK_STREAM,0);
+ if (smtpfd == -1) temp_oserr();
+ }
+ if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) smtp_port,timeoutconnect) == 0) {
tcpto_err(&ip.ix[i].ip,0);
partner = ip.ix[i].ip;
smtp(); /* does not return */