/*
* ZMailer smtpserver child-registry
*
* Registers/keeps track of IP addresses that are currently
* talking with us in order to figure out of there are too
* many parallel connections from same IP address out there..
*
* Copyright Matti Aarnio <mea@nic.funet.fi> 1998-1999, 2003
*
*/
#include "smtpserver.h"
static int child_space = 0;
static int child_top = 0;
static struct {
int pid; /* PID of the working smtpserver (subprocess) */
int tag; /* 0: smtp, 1: smtps, 2: submit, 3: lmtp, ... */
time_t when; /* When to next check on this child */
Usockaddr addr; /* Address the connection comes from */
} *childs = NULL;
static int child_poll_interval = 30;
static time_t child_now = 0;
int childsameip(addr, childcntp)
Usockaddr *addr;
int *childcntp;
{
int i, cnt = 1; /* Ourself */
int childcnt = 1; /* Ourself */
time(&child_now);
*childcntp = 1;
if (childs == NULL) return 0;
for (i = 0; i < child_top; ++i) {
/* Do we have a child to check for possible sneaky
disappearance ? */
if (childs[i].pid != 0 &&
childs[i].when > child_now) {
/* Ok, we check on this, reset the timer */
childs[i].when = child_now + child_poll_interval;
/* Does this process exist ? */
if (kill(childs[i].pid, 0) != 0) {
/* No such process in there anymore ? */
memset(&childs[i], 0, sizeof(childs[i]));
continue;
}
}
if (childs[i].pid != 0 &&
/* PID non zero */
addr->v4.sin_family == childs[i].addr.v4.sin_family) {
/* Same AddressFamily */
if ((addr->v4.sin_family == AF_INET &&
/* Address is IPv4 one */
memcmp(& addr->v4.sin_addr, & childs[i].addr.v4.sin_addr, 4) == 0)
#if defined(AF_INET6) && defined(INET6)
||
((addr->v6.sin6_family == AF_INET6 &&
/* ... or Address is IPv6 one */
memcmp(& addr->v6.sin6_addr, & childs[i].addr.v6.sin6_addr, 16) == 0))
#endif
)
++cnt;
}
if (childs[i].pid != 0)
++childcnt;
}
*childcntp = childcnt;
return cnt;
}
void childregister(cpid, addr, socktag)
int cpid, socktag;
Usockaddr *addr;
{
int i;
/* Called with SIGCHLD held ! */
if (kill(cpid, 0) < 0) {
/* When there is no subprocess with this PID, DON'T
register anything! The subprocess is already
gone for some reason... */
return;
}
/* Now count those processes.. */
MIBMtaEntry->ss.IncomingSMTPSERVERprocesses += 1;
MIBMtaEntry->ss.IncomingSMTPSERVERforks += 1;
switch (socktag) {
case 0:
MIBMtaEntry->ss.IncomingParallelSMTPconnects += 1;
break;
case 1:
MIBMtaEntry->ss.IncomingParallelSMTPSconnects += 1;
break;
case 2:
MIBMtaEntry->ss.IncomingParallelSUBMITconnects += 1;
break;
default:
break;
}
/* And do registering! */
time(&child_now);
if (child_top == child_space) {
if (child_space == 0) {
child_space = 8;
} else {
child_space <<= 1;
}
if (childs == NULL) {
childs = emalloc(child_space * sizeof(*childs));
} else {
childs = erealloc(childs, child_space * sizeof(*childs));
}
for (i = child_top; i < child_space; ++i)
memset(&childs[i], 0, sizeof(childs[i]));
}
for (i = 0; i < child_space; ++i) {
/* Do we have a child to check for possible sneaky
disappearance ? */
if (childs[i].pid != 0 &&
childs[i].when > child_now) {
/* Ok, we check on this, reset the timer */
childs[i].when = child_now + child_poll_interval;
/* Does this process exist ? */
if (kill(childs[i].pid, 0) != 0) {
/* No such process in there anymore !?
We free this slot now! */
memset(&childs[i], 0, sizeof(childs[i]));
}
}
if (childs[i].pid == 0) { /* Free slot! */
childs[i].pid = cpid;
childs[i].when = child_now + child_poll_interval;
if (addr->v4.sin_family == AF_INET) {
childs[i].addr.v4.sin_family = AF_INET;
memcpy(&childs[i].addr.v4.sin_addr, &addr->v4.sin_addr, 4);
}
#if defined(AF_INET6) && defined(INET6)
else if (addr->v6.sin6_family == AF_INET6) {
childs[i].addr.v6.sin6_family = AF_INET6;
memcpy(&childs[i].addr.v6.sin6_addr, &addr->v6.sin6_addr, 16);
}
#endif
if (i >= child_top)
child_top = i+1;
return;
}
}
}
void childreap(cpid)
int cpid;
{
int i;
if (childs == NULL) return;
for (i = 0; i < child_top; ++i)
if (childs[i].pid == cpid) {
MIBMtaEntry->ss.IncomingSMTPSERVERprocesses -= 1;
switch (childs[i].tag) {
case 0:
MIBMtaEntry->ss.IncomingParallelSMTPconnects -= 1;
break;
case 1:
MIBMtaEntry->ss.IncomingParallelSMTPSconnects -= 1;
break;
case 2:
MIBMtaEntry->ss.IncomingParallelSUBMITconnects -= 1;
break;
default:
break;
}
memset(&childs[i], 0, sizeof(childs[i]));
break;
}
}
syntax highlighted by Code2HTML, v. 0.9.1