--- ../qmail-1.03-patch20010201-orig/qmail-remote.c Wed Feb 14 18:07:28 2001 +++ qmail-remote.c Wed Feb 14 18:29:47 2001 @@ -32,8 +32,15 @@ #include "timeoutwrite.h" #endif +#ifdef MXPS +#include +#include "fmt.h" +#endif + #ifdef TLS +#ifndef MXPS #include +#endif #include SSL *ssl = 0; @@ -42,11 +49,10 @@ #define HUGESMTPTEXT 5000 -#ifndef PORT_SMTP /* this is for testing purposes, so you can overwrite - this port via a simple -D argument */ -#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ +unsigned long smtp_port = 25; /* silly rabbit, /etc/services is for users */ +#ifdef MXPS +unsigned long qmtp_port = 209; #endif -unsigned long port = PORT_SMTP; GEN_ALLOC_typedef(saa,stralloc,sa,len,a) GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) @@ -84,6 +90,10 @@ 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(); } +#ifdef MXPS +void temp_proto() { out("Z\ +recipient did not talk proper QMTP (#4.3.0)\n"); zerodie(); } +#endif void perm_partialline() { out("D\ SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); } void perm_usage() { out("D\ @@ -175,10 +185,14 @@ if (r <= 0) dropped(); return r; } - +#ifdef MXPS +char inbuf[1500]; +char smtptobuf[1500]; +#else char inbuf[1024]; -substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); char smtptobuf[1024]; +#endif +substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf); char smtpfrombuf[128]; substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf); @@ -486,6 +500,115 @@ quit("K"," accepted message"); } +#ifdef MXPS +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(); +} +#endif + stralloc canonhost = {0}; stralloc canonbox = {0}; @@ -574,7 +697,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(); @@ -633,8 +756,21 @@ /* performace hack to send TCP ACK's without delay */ setsockopt(smtpfd, IPPROTO_TCP, TCP_NODELAY, &tcpnodelay, sizeof(tcpnodelay)); - - if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { + +#ifdef MXPS + 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); /* in case of failure: it is not allowed to call connect twice on the same socket */ + smtpfd = socket(AF_INET,SOCK_STREAM,0); + if (smtpfd == -1) temp_oserr(); + } +#endif + + 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; #ifdef TLS