Does anyone have any suggestions on some software that allows you to set up multiple IP addresses to rotate through and send emails? I've utilized VOL*O software in the past, but it's expensive as all hell.
I had a patch written for net-qmail 1.05 that will rotate through a list of ips, sets max per domain connections and some other features.. This is just the MTA, you still need a front end.. I would use interspire's email maketer or something similar.
Code:
diff -Naur netqmail-1.05/FILES netqmail-1.05.patched/FILES
--- netqmail-1.05/FILES 2007-10-27 22:04:30.000000000 +0700
+++ netqmail-1.05.patched/FILES 2007-10-27 19:20:41.000000000 +0700
@@ -432,3 +432,5 @@
tcp-environ.5
constmap.h
constmap.c
+sem.h
+sem.c
diff -Naur netqmail-1.05/Makefile netqmail-1.05.patched/Makefile
--- netqmail-1.05/Makefile 2007-10-27 22:04:30.000000000 +0700
+++ netqmail-1.05.patched/Makefile 2007-10-27 19:55:48.000000000 +0700
@@ -1441,12 +1441,12 @@
load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
-substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
+substdio.a error.a str.a fs.a env.a auto_qmail.o dns.lib socket.lib sem.o
./load qmail-remote control.o constmap.o timeoutread.o \
timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
- lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
- str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
+ lock.a seek.a getln.a env.a stralloc.a alloc.a substdio.a error.a \
+ str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` sem.o
qmail-remote.0: \
qmail-remote.8
@@ -1457,15 +1457,17 @@
subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
-tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
+tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h sem.h
./compile qmail-remote.c
qmail-rspawn: \
load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
-auto_qmail.o auto_uids.o auto_spawn.o
- ./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
- sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
+auto_qmail.o auto_uids.o auto_spawn.o env.a control.o getln.a
+ ./load qmail-rspawn spawn.o scan_ulong.o control.o tcpto_clean.o \
+ now.o coe.o \
+ sig.a open.a seek.a lock.a wait.a fd.a getln.a env.a stralloc.a \
+ alloc.a \
substdio.a error.a str.a auto_qmail.o auto_uids.o \
auto_spawn.o
@@ -1483,12 +1485,12 @@
trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-auto_split.o env.a
+auto_split.o env.a sem.o
./load qmail-send qsutil.o control.o constmap.o newfield.o \
prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
- substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
+ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a sem.o
qmail-send.0: \
qmail-send.8
@@ -1508,7 +1510,7 @@
substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \
scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \
qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \
-fmtqfn.h readsubdir.h direntry.h
+fmtqfn.h readsubdir.h direntry.h sem.h
./compile qmail-send.c
qmail-showctl: \
@@ -1731,6 +1733,10 @@
&& cat select.h2 || cat select.h1 ) > select.h
rm -f trysysel.o trysysel
+sem.o: \
+compile sem.c sem.h ip.h
+ ./compile sem.c
+
sendmail: \
load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \
auto_qmail.o
diff -Naur netqmail-1.05/README.concurrencyperip netqmail-1.05.patched/README.concurrencyperip
--- netqmail-1.05/README.concurrencyperip 1970-01-01 06:00:00.000000000 +0600
+++ netqmail-1.05.patched/README.concurrencyperip 2007-10-27 19:20:41.000000000 +0700
@@ -0,0 +1,34 @@
+Qmail Per-IP Limit Patch by Joshua Megerman
+
+Because qmail attempts to deliver every message individually, and doesn't
+have any way to limit the number of connections to a given system at one time,
+some mail servers may respond slowly or not at all once a certain number of
+connections have been made. This patch provides the ability to limit the
+number of deliveries going to a single IP address at any given time by using
+semaphores to allow or deny delivery. This patch uses semaphores, and may not
+be portable to OS's other than Linux. In order to enable this patch, you need
+to enter the per-IP concurrency limit into control/concurrencyperip - if you
+enter 0 or don't create the control file, qmail will default to not using the
+semaphores and deliver mail in the traditional manner.
+
+In order to conserve semaphores, a hash method is used to reduce the 4 octets
+of the IP address to a single 8-bit integer. For an IP address a.b.c.d, the
+has is ((a^b)^(c^d)), where ^ is the C XOR operator. THus multiple IP
+addresses will map to the same hash, and can potentially be limited to a
+combined total # of remote connections. If too many connections are open to a
+particular IP address (hash), qmail-remote will try the next available MX, if
+there is one. If there are no more MXs available, qmail-remote will fail with
+a 4XX and the message will be requeued. This is the best solution to avoid
+holding up qmail-remote processes waiting for delivery in high-volume settings,
+even if it does delay mail delivery slightly for some messages.
+
+NOTE: Most Linux systems have a default maximum of 250 semaphores per semaphore
+set, and this patch uses 256. This is just a kernel tuning parameter in /proc
+and can be adjusted as follows:
+
+1) echo "256 32000 32 128" > /proc/sys/kernel/sem
+2) place the following line in /etc/sysctl.conf (or its equivalent) to set it
+on startup:
+ kernel.sem = 256 32000 32 128
+
+Questions, comments and bug reports to josh@honorablemenschen.com
diff -Naur netqmail-1.05/TARGETS netqmail-1.05.patched/TARGETS
--- netqmail-1.05/TARGETS 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/TARGETS 2007-10-27 19:20:42.000000000 +0700
@@ -385,3 +385,4 @@
man
setup
check
+sem.o
diff -Naur netqmail-1.05/qmail-control.9 netqmail-1.05.patched/qmail-control.9
--- netqmail-1.05/qmail-control.9 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-control.9 2007-10-27 19:46:34.000000000 +0700
@@ -45,6 +45,7 @@
.I bouncehost \fIme \fRqmail-send
.I concurrencylocal \fR10 \fRqmail-send
.I concurrencyremote \fR20 \fRqmail-send
+.I concurrencyperip \fR0 \fRqmail-send
.I defaultdomain \fIme \fRqmail-inject
.I defaulthost \fIme \fRqmail-inject
.I databytes \fR0 \fRqmail-smtpd
@@ -56,6 +57,7 @@
.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 -Naur netqmail-1.05/qmail-remote.8 netqmail-1.05.patched/qmail-remote.8
--- netqmail-1.05/qmail-remote.8 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-remote.8 2007-10-27 19:46:34.000000000 +0700
@@ -124,6 +124,13 @@
.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
diff -Naur netqmail-1.05/qmail-remote.c netqmail-1.05.patched/qmail-remote.c
--- netqmail-1.05/qmail-remote.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-remote.c 2007-10-28 16:22:40.000000000 +0600
@@ -20,6 +20,7 @@
#include "gen_alloc.h"
#include "gen_allocdefs.h"
#include "str.h"
+#include "env.h"
#include "now.h"
#include "exit.h"
#include "constmap.h"
@@ -28,6 +29,7 @@
#include "timeoutconn.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
+#include "sem.h"
#define HUGESMTPTEXT 5000
@@ -39,6 +41,7 @@
static stralloc sauninit = {0};
stralloc helohost = {0};
+stralloc outgoingip = {0};
stralloc routes = {0};
struct constmap maproutes;
stralloc host = {0};
@@ -47,6 +50,7 @@
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); }
@@ -56,11 +60,21 @@
ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?';
if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
+void outenv()
+{
+ out("helo=");
+ substdio_put(subfdoutsmall,helohost.s,helohost.len);
+ out(",outgoingip=");
+ substdio_put(subfdoutsmall,outgoingip.s,outgoingip.len);
+}
+
+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(); }
+Sorry, I wasn't able to establish an SMTP connection. (#4.4.1) ");
+outenv(); out("\n"); zerodie(); }
void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); }
void temp_dnscanon() { out("Z\
CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); }
@@ -70,6 +84,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(); }
+void temp_nosem() { out("Z\
+Unable to setup semaphore for per-ip connection limiting. (#4.3.0)\n"); zerodie(); }
+void temp_semnoconn() { out("Z\
+Sorry, there were too many simultaneous SMTP connections to the remote server. (#4.4.5)\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\
@@ -86,6 +104,7 @@
it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
zerodie(); }
+
void outhost()
{
char x[IPFMT];
@@ -184,6 +203,7 @@
out(prepend);
outhost();
out(append);
+ outenv();
out(".\n");
outsmtptext();
zerodie();
@@ -308,14 +328,27 @@
if (!stralloc_cat(saout,&canonhost)) temp_nomem();
}
+int perip = 0;
+
void getcontrols()
{
+ int r;
+ char *str;
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)
- temp_control();
+
+ str = env_get("HELOHOST");
+ if(str) {
+ if (!stralloc_copys(&helohost, str)) temp_nomem();
+ } else {
+ if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1)
+ temp_control();
+ }
+
+ /* if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1)
+ temp_control(); */
switch(control_readfile(&routes,"control/smtproutes",0)) {
case -1:
temp_control();
@@ -324,6 +357,22 @@
case 1:
if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
}
+ if (control_readint(&perip,"control/concurrencyperip") == -1) temp_nosem();
+
+ str = env_get("OUTGOINGIP");
+ if(str) {
+ if (!stralloc_copys(&outgoingip, str)) temp_nomem();
+ } else {
+ r = control_readline(&outgoingip,"control/outgoingip");
+ if (-1 == r) { if (errno == error_nomem) temp_nomem(); temp_control(); }
+ if (0 == r) {
+ if (!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)
@@ -331,18 +380,23 @@
char **argv;
{
static ipalloc ip = {0};
- int i;
+ int i, j;
unsigned long random;
char **recips;
unsigned long prefme;
int flagallaliases;
int flagalias;
char *relayhost;
+ int semdelay = 0;
sig_pipeignore();
if (argc < 4) perm_usage();
if (chdir(auto_qmail) == -1) temp_chdir();
getcontrols();
+ if (perip) {
+ i = setup_semaphore(0);
+ if (i == -1) temp_nosem();
+ }
if (!stralloc_copys(&host,argv[1])) temp_nomem();
@@ -411,17 +465,32 @@
for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) {
if (tcpto(&ip.ix[i].ip)) continue;
+ if (perip) {
+ j = dec_semaphore(&ip.ix[i].ip);
+ if (j == -1) {
+ semdelay = 1;
+ continue;
+ }
+ }
+
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;
smtp(); /* does not return */
}
tcpto_err(&ip.ix[i].ip,errno == error_timeout);
close(smtpfd);
+ if (perip) {
+ j = inc_semaphore(&ip.ix[i].ip);
+ }
}
- temp_noconn();
+ if (semdelay) {
+ temp_semnoconn();
+ } else {
+ temp_noconn();
+ }
}
diff -Naur netqmail-1.05/qmail-rspawn.c netqmail-1.05.patched/qmail-rspawn.c
--- netqmail-1.05/qmail-rspawn.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-rspawn.c 2007-10-27 21:19:42.000000000 +0700
@@ -1,16 +1,46 @@
#include "fd.h"
#include "wait.h"
#include "substdio.h"
+#include "stralloc.h"
+#include "control.h"
#include "exit.h"
#include "fork.h"
#include "error.h"
#include "tcpto.h"
+stralloc outgoingips = {0};
+
+static void set_outgoingip(void)
+{
+ static int i = 0;
+ int j, k;
+ char *s = outgoingips.s;
+ char ch;
+ env_unset("HELOHOST");
+ env_unset("OUTGOINGIP");
+ if(!s || !outgoingips.len) { return; }
+ j = str_chr(&s[i], ',') + i;
+ ch = s[j];
+ if(ch == ',') {
+ k = j + 1;
+ while(s[k] == ' ') { k++; }
+ if(!env_put2("HELOHOST", &s[k])) _exit(111);
+ }
+ s[j] = 0;
+ if(!env_put2("OUTGOINGIP", &s[i])) _exit(111);
+ s[j] = ch;
+ while(s[i]) { i++; }
+ i++;
+ if(i < outgoingips.len) { return; }
+ i = 0;
+}
+
void initialize(argc,argv)
int argc;
char **argv;
{
tcpto_clean();
+ control_readfile(&outgoingips, "../../control/outgoingips", 0);
}
int truncreport = 0;
@@ -84,6 +114,8 @@
int f;
char *(args[5]);
+ set_outgoingip();
+
args[0] = "qmail-remote";
args[1] = r + at + 1;
args[2] = s;
diff -Naur netqmail-1.05/qmail-send.9 netqmail-1.05.patched/qmail-send.9
--- netqmail-1.05/qmail-send.9 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-send.9 2007-10-27 19:20:41.000000000 +0700
@@ -93,6 +93,14 @@
is limited at compile time to
SPAWN.
.TP 5
+.I concurrencyperip
+Maximum number of simultaneous remote delivery attempts per hashed IP address.
+Default: 0
+If 0, per-address deliveries will not be limited.
+.I concurrencyperip
+is limited at compile time to
+32767.
+.TP 5
.I doublebouncehost
Double-bounce host.
Default:
diff -Naur netqmail-1.05/qmail-send.c netqmail-1.05.patched/qmail-send.c
--- netqmail-1.05/qmail-send.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-send.c 2007-10-27 19:20:41.000000000 +0700
@@ -31,6 +31,7 @@
#include "constmap.h"
#include "fmtqfn.h"
#include "readsubdir.h"
+#include "sem.h"
/* critical timing feature #1: if not triggered, do not busy-loop */
/* critical timing feature #2: if triggered, respond within fixed time */
@@ -782,6 +783,7 @@
unsigned long masterdelid = 1;
unsigned int concurrency[CHANNELS] = { 10, 20 };
unsigned int concurrencyused[CHANNELS] = { 0, 0 };
+unsigned int concurrencyperip = 0;
struct del *d[CHANNELS];
stralloc dline[CHANNELS];
char delbuf[2048];
@@ -1445,6 +1447,7 @@
if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0;
if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0;
if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0;
+ if (control_readint(&concurrencyperip,"control/concurrencyperip") == -1) return 0;
if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0;
if (control_rldef(&bouncefrom,"control/bouncefrom",0,"MAILER-DAEMON") != 1) return 0;
if (control_rldef(&bouncehost,"control/bouncehost",1,"bouncehost") != 1) return 0;
@@ -1521,11 +1524,21 @@
int nfds;
struct timeval tv;
int c;
+ char cip_strnum[FMT_ULONG];
if (chdir(auto_qmail) == -1)
{ log1("alert: cannot start: unable to switch to home directory\n"); _exit(111); }
if (!getcontrols())
{ log1("alert: cannot start: unable to read controls\n"); _exit(111); }
+ if (concurrencyperip)
+ {
+ cip_strnum[fmt_ulong(cip_strnum,concurrencyperip)] = 0;
+ log3("per-IP concurrency is set to: ", cip_strnum, "\n");
+ c = setup_semaphore(concurrencyperip);
+ if (c == -1)
+ { log1("alert: cannot setup semaphore for outbound per-ip rate limiting\n"); _exit(111); }
+ }
+ else semaphore = -1;
if (chdir("queue") == -1)
{ log1("alert: cannot start: unable to switch to queue directory\n"); _exit(111); }
sig_pipeignore();
@@ -1607,6 +1620,10 @@
}
}
pqfinish();
+ if (semaphore != -1)
+ { c = destroy_semaphore(); }
+ if (c == -1)
+ { log1("warning: could not destroy semaphore\n"); }
log1("status: exiting\n");
_exit(0);
}
diff -Naur netqmail-1.05/qmail-showctl.c netqmail-1.05.patched/qmail-showctl.c
--- netqmail-1.05/qmail-showctl.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/qmail-showctl.c 2007-10-27 19:46:35.000000000 +0700
@@ -230,6 +230,7 @@
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 -Naur netqmail-1.05/remoteinfo.c netqmail-1.05.patched/remoteinfo.c
--- netqmail-1.05/remoteinfo.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/remoteinfo.c 2007-10-27 19:46:35.000000000 +0700
@@ -44,12 +44,12 @@
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 -Naur netqmail-1.05/sem.c netqmail-1.05.patched/sem.c
--- netqmail-1.05/sem.c 1970-01-01 06:00:00.000000000 +0600
+++ netqmail-1.05.patched/sem.c 2007-10-27 19:20:42.000000000 +0700
@@ -0,0 +1,88 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include "sem.h"
+#include "ip.h"
+#include "qsutil.h"
+
+int semaphore;
+
+int setup_semaphore(int max_out) {
+
+ key_t key;
+ int i;
+ unsigned short array[256];
+ union semun semopts;
+
+ if ((max_out > 32767) || (max_out < 0)) {
+ return(-1);
+ }
+
+ if ((key = ftok("control/me", 'q')) == -1) {
+ return(-1);
+ }
+ if ((semaphore = semget(key, 256, 0660 | IPC_CREAT)) == -1) {
+ return(-1);
+ }
+
+ if (max_out) {
+ for (i = 0; i < 256; i++) { array[i] = max_out; }
+ semopts.array = array;
+ if ((i = semctl(semaphore, 0, SETALL, array)) == -1) {
+ semctl(semaphore, 0, IPC_RMID);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+
+int destroy_semaphore() {
+
+ int i;
+
+ if((i = semctl(semaphore, 0, IPC_RMID)) == -1) {
+ return(-1);
+ }
+ return(0);
+}
+
+int dec_semaphore(struct ip_address *ip) {
+
+ struct sembuf sop;
+ int i;
+ unsigned char a, b, c, d;
+ a = ip->d[0];
+ b = ip->d[1];
+ c = ip->d[2];
+ d = ip->d[3];
+
+ sop.sem_num = ((a^b)^(c^d));
+ sop.sem_op = -1;
+ sop.sem_flg = (IPC_NOWAIT | SEM_UNDO);
+
+ if ((i = semop(semaphore, &sop, 1)) == -1) {
+ return(-1);
+ }
+ return(0);
+}
+
+int inc_semaphore(struct ip_address *ip) {
+
+ struct sembuf sop;
+ int i;
+ unsigned char a, b, c, d;
+ a = ip->d[0];
+ b = ip->d[1];
+ c = ip->d[2];
+ d = ip->d[3];
+
+ sop.sem_num = ((a^b)^(c^d));
+ sop.sem_op = 1;
+ sop.sem_flg = SEM_UNDO;
+
+ if ((i = semop(semaphore, &sop, 1)) == -1) {
+ return(-1);
+ }
+ return(0);
+}
diff -Naur netqmail-1.05/sem.h netqmail-1.05.patched/sem.h
--- netqmail-1.05/sem.h 1970-01-01 06:00:00.000000000 +0600
+++ netqmail-1.05.patched/sem.h 2007-10-27 19:20:42.000000000 +0700
@@ -0,0 +1,24 @@
+#ifndef SEM_H
+#define SEM_H
+
+#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h> */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+ /* Linux specific part: */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
+};
+#endif
+
+extern int semaphore;
+
+int setup_semaphore();
+int destroy_semaphore();
+int dec_semaphore();
+int inc_semaphore();
+
+#endif
diff -Naur netqmail-1.05/timeoutconn.c netqmail-1.05.patched/timeoutconn.c
--- netqmail-1.05/timeoutconn.c 1998-06-15 17:53:16.000000000 +0700
+++ netqmail-1.05.patched/timeoutconn.c 2007-10-27 19:46:35.000000000 +0700
@@ -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 @@
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;
That's a patch for net-qmail-1.0.5 .
It uses: control/outgoingips
format:
IP,HOSTNAME
208.53.131.31,mx131-31.domainname.com
And max connection per ip should be control/concurrencyperip
IP,MAX