baseline commit of sendmail release 8 version 8.1B
(this is the sendmail stuff as it will appear in 4.4BSD)
This commit is contained in:
parent
b580eb544e
commit
100f4f365f
|
@ -0,0 +1,10 @@
|
|||
Everything in this directory (except this file) has been contributed.
|
||||
We will not fix bugs in these programs. Contact the original author
|
||||
for assistance.
|
||||
|
||||
Some of these are patches to sendmail itself. You may need to take
|
||||
care -- some of the patches may be out of date with the latest release
|
||||
of sendmail. Also, the previous comment applies -- patches belong to
|
||||
the original author, not to me.
|
||||
|
||||
Eric Allman, 26 May 1993
|
|
@ -0,0 +1,409 @@
|
|||
/*
|
||||
* By John G. Myers, jgm+@cmu.edu
|
||||
* Version 1.1
|
||||
*
|
||||
* Process a BITNET "internet.listing" file, producing output
|
||||
* suitable for input to makemap.
|
||||
*
|
||||
* The input file can be obtained via anonymous FTP to bitnic.educom.edu.
|
||||
* Change directory to "netinfo" and get the file internet.listing
|
||||
* The file is updated monthly.
|
||||
*
|
||||
* Feed the output of this program to "makemap hash /etc/bitdomain.db"
|
||||
* to create the table used by the "FEATURE(bitdomain)" config file macro.
|
||||
* If your sendmail does not have the db library compiled in, you can instead
|
||||
* use "makemap dbm /etc/bitdomain" and
|
||||
* "FEATURE(bitdomain,`dbm -o /etc/bitdomain')"
|
||||
*
|
||||
* The bitdomain table should be rebuilt monthly.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
/* don't use sizeof because sizeof(long) is different on 64-bit machines */
|
||||
#define SHORTSIZE 2 /* size of a short (really, must be 2) */
|
||||
#define LONGSIZE 4 /* size of a long (really, must be 4) */
|
||||
|
||||
typedef union
|
||||
{
|
||||
HEADER qb1;
|
||||
char qb2[PACKETSZ];
|
||||
} querybuf;
|
||||
|
||||
extern int h_errno;
|
||||
extern char *malloc();
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
|
||||
char *lookup();
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "o:")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
if (!freopen(optarg, "w", stdout)) {
|
||||
perror(optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [-o outfile] [internet.listing]\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
if (!freopen(argv[optind], "r", stdin)) {
|
||||
perror(argv[optind]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
readfile(stdin);
|
||||
finish();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and process an input file
|
||||
*/
|
||||
readfile(infile)
|
||||
FILE *infile;
|
||||
{
|
||||
int skippingheader = 1;
|
||||
char buf[1024], *node, *hostname, *p;
|
||||
|
||||
while (fgets(buf, sizeof(buf), infile)) {
|
||||
for (p = buf; *p && isspace(*p); p++);
|
||||
if (!*p) {
|
||||
skippingheader = 0;
|
||||
continue;
|
||||
}
|
||||
if (skippingheader) continue;
|
||||
|
||||
node = p;
|
||||
for (; *p && !isspace(*p); p++) {
|
||||
if (isupper(*p)) *p = tolower(*p);
|
||||
}
|
||||
if (!*p) {
|
||||
fprintf(stderr, "%-8s: no domain name in input file\n", node);
|
||||
continue;
|
||||
}
|
||||
*p++ = '\0';
|
||||
|
||||
for (; *p && isspace(*p); p++) ;
|
||||
if (!*p) {
|
||||
fprintf(stderr, "%-8s no domain name in input file\n", node);
|
||||
continue;
|
||||
}
|
||||
|
||||
hostname = p;
|
||||
for (; *p && !isspace(*p); p++) {
|
||||
if (isupper(*p)) *p = tolower(*p);
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
/* Chop off any trailing .bitnet */
|
||||
if (strlen(hostname) > 7 &&
|
||||
!strcmp(hostname+strlen(hostname)-7, ".bitnet")) {
|
||||
hostname[strlen(hostname)-7] = '\0';
|
||||
}
|
||||
entry(node, hostname, sizeof(buf)-(hostname - buf));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a single entry in the input file.
|
||||
* The entry tells us that "node" expands to "domain".
|
||||
* "domain" can either be a domain name or a bitnet node name
|
||||
* The buffer pointed to by "domain" may be overwritten--it
|
||||
* is of size "domainlen".
|
||||
*/
|
||||
entry(node, domain, domainlen)
|
||||
char *node;
|
||||
char *domain;
|
||||
char *domainlen;
|
||||
{
|
||||
char *otherdomain, *p, *err;
|
||||
|
||||
/* See if we have any remembered information about this node */
|
||||
otherdomain = lookup(node);
|
||||
|
||||
if (otherdomain && strchr(otherdomain, '.')) {
|
||||
/* We already have a domain for this node */
|
||||
if (!strchr(domain, '.')) {
|
||||
/*
|
||||
* This entry is an Eric Thomas FOO.BITNET kludge.
|
||||
* He doesn't want LISTSERV to do transitive closures, so we
|
||||
* do them instead. Give the the domain expansion for "node"
|
||||
* (which is in "otherdomian") to FOO (which is in "domain")
|
||||
* if "domain" doesn't have a domain expansion already.
|
||||
*/
|
||||
p = lookup(domain);
|
||||
if (!p || !index(p, '.')) remember(domain, otherdomain);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!strchr(domain, '.') || valhost(domain, domainlen)) {
|
||||
remember(node, domain);
|
||||
if (otherdomain) {
|
||||
/*
|
||||
* We previously mapped the node "node" to the node
|
||||
* "otherdomain". If "otherdomain" doesn't already
|
||||
* have a domain expansion, give it the expansion "domain".
|
||||
*/
|
||||
p = lookup(otherdomain);
|
||||
if (!p || !index(p, '.')) remember(otherdomain, domain);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (h_errno) {
|
||||
case HOST_NOT_FOUND:
|
||||
err = "not registered in DNS";
|
||||
break;
|
||||
|
||||
case TRY_AGAIN:
|
||||
err = "temporary DNS lookup failure";
|
||||
break;
|
||||
|
||||
case NO_RECOVERY:
|
||||
err = "non-recoverable nameserver error";
|
||||
break;
|
||||
|
||||
case NO_DATA:
|
||||
err = "registered in DNS, but not mailable";
|
||||
break;
|
||||
|
||||
default:
|
||||
err = "unknown nameserver error";
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%-8s %s %s\n", node, domain, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate whether the mail domain "host" is registered in the DNS.
|
||||
* If "host" is a CNAME, it is expanded in-place if the expansion fits
|
||||
* into the buffer of size "hbsize". Returns nonzero if it is, zero
|
||||
* if it is not. A BIND error code is left in h_errno.
|
||||
*/
|
||||
int
|
||||
valhost(host, hbsize)
|
||||
char *host;
|
||||
int hbsize;
|
||||
{
|
||||
register u_char *eom, *ap;
|
||||
register int n;
|
||||
HEADER *hp;
|
||||
querybuf answer;
|
||||
int ancount, qdcount;
|
||||
int ret;
|
||||
int type;
|
||||
int qtype;
|
||||
char nbuf[1024];
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
||||
return (0);
|
||||
|
||||
_res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
|
||||
_res.retrans = 30;
|
||||
_res.retry = 10;
|
||||
|
||||
qtype = T_ANY;
|
||||
|
||||
for (;;) {
|
||||
h_errno = NO_DATA;
|
||||
ret = res_querydomain(host, "", C_IN, qtype,
|
||||
&answer, sizeof(answer));
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (errno == ECONNREFUSED || h_errno == TRY_AGAIN)
|
||||
{
|
||||
/* the name server seems to be down */
|
||||
h_errno = TRY_AGAIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (h_errno != HOST_NOT_FOUND)
|
||||
{
|
||||
/* might have another type of interest */
|
||||
if (qtype == T_ANY)
|
||||
{
|
||||
qtype = T_A;
|
||||
continue;
|
||||
}
|
||||
else if (qtype == T_A)
|
||||
{
|
||||
qtype = T_MX;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise, no record */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This might be a bogus match. Search for A, MX, or
|
||||
** CNAME records.
|
||||
*/
|
||||
|
||||
hp = (HEADER *) &answer;
|
||||
ap = (u_char *) &answer + sizeof(HEADER);
|
||||
eom = (u_char *) &answer + ret;
|
||||
|
||||
/* skip question part of response -- we know what we asked */
|
||||
for (qdcount = ntohs(hp->qdcount); qdcount--; ap += ret + QFIXEDSZ)
|
||||
{
|
||||
if ((ret = dn_skipname(ap, eom)) < 0)
|
||||
{
|
||||
return 0; /* ???XXX??? */
|
||||
}
|
||||
}
|
||||
|
||||
for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
|
||||
{
|
||||
n = dn_expand((u_char *) &answer, eom, ap,
|
||||
(u_char *) nbuf, sizeof nbuf);
|
||||
if (n < 0)
|
||||
break;
|
||||
ap += n;
|
||||
GETSHORT(type, ap);
|
||||
ap += SHORTSIZE + LONGSIZE;
|
||||
GETSHORT(n, ap);
|
||||
switch (type)
|
||||
{
|
||||
case T_MX:
|
||||
case T_A:
|
||||
return 1;
|
||||
|
||||
case T_CNAME:
|
||||
/* value points at name */
|
||||
if ((ret = dn_expand((u_char *)&answer,
|
||||
eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0)
|
||||
break;
|
||||
if (strlen(nbuf) < hbsize) {
|
||||
(void)strcpy(host, nbuf);
|
||||
}
|
||||
return 1;
|
||||
|
||||
default:
|
||||
/* not a record of interest */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** If this was a T_ANY query, we may have the info but
|
||||
** need an explicit query. Try T_A, then T_MX.
|
||||
*/
|
||||
|
||||
if (qtype == T_ANY)
|
||||
qtype = T_A;
|
||||
else if (qtype == T_A)
|
||||
qtype = T_MX;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct entry {
|
||||
struct entry *next;
|
||||
char *node;
|
||||
char *domain;
|
||||
};
|
||||
struct entry *firstentry;
|
||||
|
||||
/*
|
||||
* Find any remembered information about "node"
|
||||
*/
|
||||
char *lookup(node)
|
||||
char *node;
|
||||
{
|
||||
struct entry *p;
|
||||
|
||||
for (p = firstentry; p; p = p->next) {
|
||||
if (!strcmp(node, p->node)) {
|
||||
return p->domain;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the node "node" as equivalent to "domain". "domain" can either
|
||||
* be a bitnet node or a domain name--if it is the latter, the mapping
|
||||
* will be written to stdout.
|
||||
*/
|
||||
remember(node, domain)
|
||||
char *node;
|
||||
char *domain;
|
||||
{
|
||||
struct entry *p;
|
||||
|
||||
if (strchr(domain, '.')) {
|
||||
fprintf(stdout, "%-8s %s\n", node, domain);
|
||||
}
|
||||
|
||||
for (p = firstentry; p; p = p->next) {
|
||||
if (!strcmp(node, p->node)) {
|
||||
p->domain = malloc(strlen(domain)+1);
|
||||
if (!p->domain) {
|
||||
goto outofmemory;
|
||||
}
|
||||
strcpy(p->domain, domain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
p = (struct entry *)malloc(sizeof(struct entry));
|
||||
if (!p) goto outofmemory;
|
||||
|
||||
p->next = firstentry;
|
||||
firstentry = p;
|
||||
p->node = malloc(strlen(node)+1);
|
||||
p->domain = malloc(strlen(domain)+1);
|
||||
if (!p->node || !p->domain) goto outofmemory;
|
||||
strcpy(p->node, node);
|
||||
strcpy(p->domain, domain);
|
||||
return;
|
||||
|
||||
outofmemory:
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk through the database, looking for any cases where we know
|
||||
* node FOO is equivalent to node BAR and node BAR has a domain name.
|
||||
* For those cases, give FOO the same domain name as BAR.
|
||||
*/
|
||||
finish()
|
||||
{
|
||||
struct entry *p;
|
||||
char *domain;
|
||||
|
||||
for (p = firstentry; p; p = p->next) {
|
||||
if (!strchr(p->domain, '.') && (domain = lookup(p->domain))) {
|
||||
remember(p->node, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,297 @@
|
|||
(Message /home/auspex/a/staff/eric/.mh/inbox:2575)
|
||||
From: John Gardiner Myers <jgm+@cmu.edu>
|
||||
Subject: contrib/rcpt-streaming
|
||||
Date: Fri, 4 Jun 1993 13:54:06 -0400 (EDT)
|
||||
To: sendmail@cs.berkeley.edu
|
||||
|
||||
This patch implements "RCPT streaming" in sendmail version 6. This
|
||||
patch is not an official part of sendmail. Please report all problems
|
||||
with this patch to jgm+@cmu.edu.
|
||||
|
||||
RCPT streming avoids network round trips by sending all RCPT commands
|
||||
for a single SMTP transaction together. Sendmail then waits for all
|
||||
the replies, matching them up with the apropriate addresses.
|
||||
|
||||
Apply to the sendmail src directory (your line numbers may vary) and
|
||||
compile with -DRCPTSTREAM
|
||||
|
||||
diff -cr src.orig/deliver.c src/deliver.c
|
||||
*** src.orig/deliver.c Thu May 27 14:38:22 1993
|
||||
--- src/deliver.c Fri Jun 4 13:50:02 1993
|
||||
***************
|
||||
*** 1325,1330 ****
|
||||
--- 1325,1345 ----
|
||||
register int i;
|
||||
|
||||
/* send the recipient list */
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ /***********************************************************************
|
||||
+ *
|
||||
+ * RCPT streaming code by John G Myers, jgm+@cmu.edu
|
||||
+ * This is not supported by the maintainer of sendmail.
|
||||
+ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
|
||||
+ *
|
||||
+ ***********************************************************************
|
||||
+ */
|
||||
+ for (to = tochain; to != NULL; to = to->q_tchain)
|
||||
+ {
|
||||
+ smtpstreammessage("RCPT To:<%s>", m, mci,
|
||||
+ to->q_user);
|
||||
+ }
|
||||
+ #endif
|
||||
tobuf[0] = '\0';
|
||||
for (to = tochain; to != NULL; to = to->q_tchain)
|
||||
{
|
||||
diff -cr src.orig/usersmtp.c src/usersmtp.c
|
||||
*** src.orig/usersmtp.c Thu May 27 14:38:09 1993
|
||||
--- src/usersmtp.c Fri Jun 4 13:48:24 1993
|
||||
***************
|
||||
*** 44,49 ****
|
||||
--- 44,61 ----
|
||||
|
||||
# include <sysexits.h>
|
||||
# include <errno.h>
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ /***********************************************************************
|
||||
+ *
|
||||
+ * RCPT streaming code by John G Myers, jgm+@cmu.edu
|
||||
+ * This is not supported by the maintainer of sendmail.
|
||||
+ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
|
||||
+ *
|
||||
+ ***********************************************************************
|
||||
+ */
|
||||
+ # include <sys/types.h>
|
||||
+ # include <sys/time.h>
|
||||
+ #endif
|
||||
|
||||
# ifdef SMTP
|
||||
|
||||
***************
|
||||
*** 62,67 ****
|
||||
--- 74,87 ----
|
||||
char SmtpError[MAXLINE] = ""; /* save failure error messages */
|
||||
int SmtpPid; /* pid of mailer */
|
||||
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ char *SmtpStreamBuf; /* buffer for streaming output */
|
||||
+ int SmtpStreamBufSize = 0; /* allocated size of buffer */
|
||||
+ char *SmtpStreamStart; /* pointer to text not yet written */
|
||||
+ int SmtpStreamLen = 0; /* # chars not yet written */
|
||||
+ #endif
|
||||
+
|
||||
+
|
||||
#ifdef __STDC__
|
||||
extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);
|
||||
#endif
|
||||
***************
|
||||
*** 404,410 ****
|
||||
--- 424,432 ----
|
||||
{
|
||||
register int r;
|
||||
|
||||
+ #ifndef RCPTSTREAM
|
||||
smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
|
||||
+ #endif
|
||||
|
||||
SmtpPhase = mci->mci_phase = "RCPT wait";
|
||||
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
|
||||
***************
|
||||
*** 626,631 ****
|
||||
--- 648,657 ----
|
||||
bool firstline = TRUE;
|
||||
char junkbuf[MAXLINE];
|
||||
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ extern char MsgBuf[]; /* err.c */
|
||||
+ #endif
|
||||
+
|
||||
if (mci->mci_out != NULL)
|
||||
(void) fflush(mci->mci_out);
|
||||
|
||||
***************
|
||||
*** 641,646 ****
|
||||
--- 667,709 ----
|
||||
register char *p;
|
||||
extern time_t curtime();
|
||||
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ if (SmtpStreamLen > 0) {
|
||||
+ int outfd;
|
||||
+
|
||||
+ outfd = fileno(mci->mci_out);
|
||||
+
|
||||
+ nonblock(outfd, TRUE);
|
||||
+ r = write(outfd, SmtpStreamStart, SmtpStreamLen);
|
||||
+ nonblock(outfd, FALSE);
|
||||
+ if (r == -1 && errno != EAGAIN
|
||||
+ #ifdef EWOULDBLOCK
|
||||
+ && errno != EWOULDBLOCK
|
||||
+ #endif
|
||||
+ ) {
|
||||
+
|
||||
+ mci->mci_errno = errno;
|
||||
+ message("451 streamreply: write error to %s",
|
||||
+ mci->mci_host);
|
||||
+
|
||||
+ /* if debugging, pause so we can see state */
|
||||
+ if (tTd(18, 100))
|
||||
+ pause();
|
||||
+ # ifdef LOG
|
||||
+ if (LogLevel > 0)
|
||||
+ syslog(LOG_INFO, "%s", &MsgBuf[4]);
|
||||
+ # endif /* LOG */
|
||||
+ /* stop trying to write output */
|
||||
+ SmtpStreamLen = 0;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (r > 0) {
|
||||
+ SmtpStreamStart += r;
|
||||
+ SmtpStreamLen -= r;
|
||||
+ }
|
||||
+ }
|
||||
+ #endif /* RCPTSTREAM */
|
||||
+
|
||||
/* actually do the read */
|
||||
if (e->e_xfp != NULL)
|
||||
(void) fflush(e->e_xfp); /* for debugging */
|
||||
***************
|
||||
*** 742,747 ****
|
||||
--- 805,880 ----
|
||||
|
||||
return (r);
|
||||
}
|
||||
+
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ /*
|
||||
+ ** SMTPSTREAMMESSAGE -- buffer message to be streamed to server
|
||||
+ **
|
||||
+ ** Parameters:
|
||||
+ ** f -- format
|
||||
+ ** m -- the mailer to control formatting.
|
||||
+ ** a, b, c -- parameters
|
||||
+ **
|
||||
+ ** Returns:
|
||||
+ ** none.
|
||||
+ **
|
||||
+ ** Side Effects:
|
||||
+ ** stores message in SmtpStreamBuf
|
||||
+ */
|
||||
+
|
||||
+ /*VARARGS1*/
|
||||
+ #ifdef __STDC__
|
||||
+ smtpstreammessage(char *f, MAILER *m, MCI *mci, ...)
|
||||
+ #else
|
||||
+ smtpstreammessage(f, m, mci, va_alist)
|
||||
+ char *f;
|
||||
+ MAILER *m;
|
||||
+ MCI *mci;
|
||||
+ va_dcl
|
||||
+ #endif
|
||||
+ {
|
||||
+ VA_LOCAL_DECL
|
||||
+ int len;
|
||||
+
|
||||
+ VA_START(mci);
|
||||
+ (void) vsprintf(SmtpMsgBuffer, f, ap);
|
||||
+ VA_END;
|
||||
+
|
||||
+ if (tTd(18, 1) || Verbose)
|
||||
+ nmessage(">>> %s", SmtpMsgBuffer);
|
||||
+
|
||||
+ if (mci->mci_out == NULL) {
|
||||
+ if (tTd(18, 1)) printf("smtpstreammessage: NULL mci_out\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ strcat(SmtpMsgBuffer, m == NULL ? "\r\n" : m->m_eol);
|
||||
+ len = strlen(SmtpMsgBuffer);
|
||||
+
|
||||
+ if (SmtpStreamLen == 0) {
|
||||
+ if (SmtpStreamBufSize == 0) {
|
||||
+ SmtpStreamBufSize = MAXLINE;
|
||||
+ SmtpStreamBuf = xalloc(SmtpStreamBufSize);
|
||||
+ }
|
||||
+ SmtpStreamStart = SmtpStreamBuf;
|
||||
+ }
|
||||
+
|
||||
+ if (SmtpStreamBufSize - SmtpStreamLen < len + 1) {
|
||||
+ int start = SmtpStreamStart - SmtpStreamBuf;
|
||||
+ SmtpStreamBufSize += MAXLINE;
|
||||
+ SmtpStreamBuf = realloc(SmtpStreamBuf, SmtpStreamBufSize);
|
||||
+ if (!SmtpStreamBuf) {
|
||||
+ syserr("Out of memory!!");
|
||||
+ abort();
|
||||
+ /* exit(EX_UNAVAILABLE); */
|
||||
+ }
|
||||
+ SmtpStreamStart = SmtpStreamBuf + start;
|
||||
+ }
|
||||
+
|
||||
+ strcpy(SmtpStreamBuf + SmtpStreamLen, SmtpMsgBuffer);
|
||||
+ SmtpStreamLen += len;
|
||||
+ }
|
||||
+ #endif /* RCPTSTREAM */
|
||||
/*
|
||||
** SMTPMESSAGE -- send message to server
|
||||
**
|
||||
Only in src: usersmtp.c.orig
|
||||
Only in src: usersmtp.c~
|
||||
Only in src: usersmtp.o
|
||||
diff -cr src.orig/util.c src/util.c
|
||||
*** src.orig/util.c Thu May 27 14:38:20 1993
|
||||
--- src/util.c Wed Jun 2 16:39:15 1993
|
||||
***************
|
||||
*** 955,960 ****
|
||||
--- 955,1004 ----
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
+
|
||||
+ #ifdef RCPTSTREAM
|
||||
+ /***********************************************************************
|
||||
+ *
|
||||
+ * RCPT streaming code by John G Myers, jgm+@cmu.edu
|
||||
+ * This is not supported by the maintainer of sendmail.
|
||||
+ * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
|
||||
+ *
|
||||
+ ***********************************************************************
|
||||
+ */
|
||||
+
|
||||
+ #include <fcntl.h>
|
||||
+
|
||||
+ /*
|
||||
+ ** NONBLOCK -- set or clear non-blocking mode on file descriptor
|
||||
+ **
|
||||
+ ** Parameters:
|
||||
+ ** fd -- the file descriptor
|
||||
+ ** mode -- TRUE to set non-blocking mode
|
||||
+ ** FALSE to clear non-blocking mode
|
||||
+ **
|
||||
+ ** Returns:
|
||||
+ ** none
|
||||
+ **
|
||||
+ ** Side Effects:
|
||||
+ ** modifies nonblocking status of fd
|
||||
+ */
|
||||
+
|
||||
+ nonblock(fd, mode)
|
||||
+ int fd;
|
||||
+ bool mode;
|
||||
+ {
|
||||
+ int flags;
|
||||
+
|
||||
+ flags = fcntl(fd, F_GETFL, 0);
|
||||
+ if (mode) {
|
||||
+ flags |= FNONBIO;
|
||||
+ }
|
||||
+ else {
|
||||
+ flags &= ~FNONBIO;
|
||||
+ }
|
||||
+ fcntl(fd, F_SETFL, flags);
|
||||
+ }
|
||||
+ #endif
|
||||
/*
|
||||
** STRCONTAINEDIN -- tell if one string is contained in another
|
||||
**
|
||||
Only in src: util.c.orig
|
||||
Only in src: util.o
|
||||
Only in src: version.o
|
|
@ -0,0 +1,207 @@
|
|||
XLA - Extended Load Average design for Sendmail R6
|
||||
--------------------------------------------------
|
||||
|
||||
Christophe Wolfhugel - Herve Schauer Consultants
|
||||
wolf@grasp.insa-lyon.fr, wolf@hsc-sec.fr
|
||||
|
||||
|
||||
WARNING: this extension is supplied as a contribution to Sendmail.
|
||||
Should you have trouble, questions, please contact me directly, and
|
||||
*not* the Sendmail development team.
|
||||
|
||||
|
||||
ABSTRACT
|
||||
|
||||
Sendmail currently furnishes a limitation mecanism which is based on
|
||||
the system load average, when available. Experience has prooven that
|
||||
this was not sufficiant for some particular situations, for example
|
||||
if you have slow and/or overloaded links. This can easily cause both
|
||||
system and network congestions with Sendmail having to handle a large
|
||||
number of simultaneous sessions on the same overloaded link, causing
|
||||
most of the SMTP sessions to timeout after a long time. The system
|
||||
load average is also generally too slow to react when your system
|
||||
gets a burst of incoming or outgoing SMTP sessions which on some
|
||||
stations can easily cause system unavailabilities.
|
||||
|
||||
The extended load average module has been designed in order to furnish
|
||||
a way of limitation the load generated by Sendmail to both your
|
||||
system and your network. This design can be used either alone or as
|
||||
complementary to the system load average if your system supports it.
|
||||
|
||||
Limitation is based on the number of incoming/outgoing SMTP sessions,
|
||||
and remote hosts are classified in classes. The system administrator
|
||||
will define a maximum number of incoming SMTP sessions as well as
|
||||
a maximum total (incoming + outgoing) sessions for each class of
|
||||
hosts. A class can be either an individual machine or a network.
|
||||
|
||||
When the limit is reached for a given class, all incoming SMTP
|
||||
connections will be politely refused. When the limit is reached for
|
||||
all classes, the SMTP connections will be refused by the system
|
||||
(which one could consider as less politely :)).
|
||||
On outgoing mail, messages will be queued for delayed processing.
|
||||
|
||||
The extended load average parameters are given in the Sendmail
|
||||
configuration file, and when not present, Sendmail behaves the
|
||||
usual way.
|
||||
|
||||
|
||||
COMPILATION
|
||||
|
||||
Copy the xla.c module in the src sub-directory, edit the Makefile
|
||||
in order to define XLA (-DXLA). Also add the xla.[co] module name
|
||||
in the list of files so that it gets compiled.
|
||||
|
||||
Regenerate sendmail by removing all objects, or at least those
|
||||
containing references to XLA (this list may vary, so use grep to
|
||||
get the module list). This will generate a new sendmail executable
|
||||
containing the xla code.
|
||||
|
||||
Debugging level 59 has been assigned to this module and when used
|
||||
it provides some output (sendmail -d59.x). Please check the source
|
||||
code to see which levels are supported.
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
|
||||
The extended average uses a new set of configuration lines in the
|
||||
sendmail.cf file. All newly introduced line begin with the letter L
|
||||
(capital L).
|
||||
|
||||
Before detailling the syntax, first an example (this can be placed
|
||||
at any section of the sendmail.cf file, note that the order is
|
||||
important). Fields are separated by (one or more) tabs/spaces.
|
||||
|
||||
# File name used to store the counters
|
||||
L/etc/sendmail.la
|
||||
# Classes definition
|
||||
# Lname #queue #reject
|
||||
L*.insa-lyon.fr 8 3
|
||||
L*.univ-lyon1.fr 6 4
|
||||
L* 15 16
|
||||
|
||||
The first line defines the working file which will be used in order
|
||||
to have the occurences of Sendmail read and update the counters. The
|
||||
format of this file is described in the "Design" section.
|
||||
This line is mandatory and the specified file must be absolute (ie
|
||||
begin with a slash).
|
||||
|
||||
Then you can specify one or more classes. The last class (*) is also
|
||||
mandatory and should be in last position as the first match will stop
|
||||
the search and if there is no match the behavior of Sendmail is unknown.
|
||||
|
||||
Each class has three fields separated by one or more tabs/spaces.
|
||||
|
||||
L{mask} {queue_#} {refuse_#}
|
||||
|
||||
The {mask} is a simple mask. It can be either an explicit host name
|
||||
(like grasp.insa-lyon.fr) or a mask starting with "*." or just "*".
|
||||
No other variants are allowed.
|
||||
|
||||
Lgrasp.insa-lyon.fr will match exactely any session to/from this host.
|
||||
|
||||
L*.insa-lyon.fr will match any session to/from any machine in the
|
||||
insa-lyon.fr domain as well as from the machine
|
||||
named "insa-lyon.fr" if it exists.
|
||||
|
||||
L* will match any session, and thus should also be
|
||||
last in the list to act as a catchup line.
|
||||
|
||||
The {queue_#} is the maximum number of SMTP sessions in the given class
|
||||
for both incoming and outgoing messages. The {refuse_#} indicates when
|
||||
to refuse incoming messages for this class. The interaction between
|
||||
those counters is somewhat subtle. It seems logical that a standard
|
||||
configuration has {queue_#} >= {refuse_#}, and in fact in most
|
||||
configurations they can be equal (that's why what I use in my environment).
|
||||
Thus, this is not mandatory. If {queue_#} < {refuse_#} outgoing messages
|
||||
will be lower priority than incoming messages and once a class gets loaded
|
||||
the outgoing messages are blocked first.
|
||||
|
||||
I use very low values in some situations, for example I have a customer
|
||||
connected to the Internet via a 9600 bps line, they also have internal
|
||||
users sending burst of messages (10, 20 small messages coming in just
|
||||
one or two seconds). Both situations were unsupportable. The line is
|
||||
too slow to handle many simultaneous connections and the mail server
|
||||
does not have the ressources to handle such a heavy load (it's a 12 Megs
|
||||
Sun 3 also doing Usenet news).
|
||||
|
||||
I have defined following section in the configuration file, and experience
|
||||
shows the benefits for everyone. Fake domain for the example: customer.fr.
|
||||
|
||||
L/etc/sendmail.la
|
||||
L*.customer.fr 8 8
|
||||
L* 3 3
|
||||
|
||||
This means that there might not be more than 8 simultaneous SMTP sessions
|
||||
between the mail server and any other internal host. This is to protect
|
||||
the station from heavy loads like users (or applications !) sending
|
||||
several tenths of messages in just a few seconds).
|
||||
No more than 3 SMTP sessions are authorized with any other host, this is
|
||||
to save the load of the slow 9600 line to the Internet.
|
||||
|
||||
Drawback is that is you have 3 * 2 Megs sessions established from/to the
|
||||
outside, all your mail will be held until one slot gets available, on
|
||||
a 9600 bps line just make your counts, il blocks your line during over
|
||||
one hour.
|
||||
|
||||
|
||||
DESIGN
|
||||
|
||||
Sendmail will analyze the "L" lines in the configuration file during
|
||||
startup (or read the initialized structure from the frozen file).
|
||||
When started in daemon mode (and only there), any existing working file
|
||||
will be cleared and a new one is created. Each class gets a record in
|
||||
the sendmail.la work file. The size of this record is a short integer
|
||||
(generally two bytes) and represents the count of active sessions in
|
||||
the given class. Read/Write operations in this file are done in
|
||||
one operation (as anyway the size is far below one disk sector). The
|
||||
file is locked with Sendmail's lockfile() function priori to any
|
||||
access.
|
||||
|
||||
Handling incoming SMTP sessions.
|
||||
|
||||
There is interaction is two points in the Sendmail source code. First
|
||||
on the listen system call: if all slots in all classes are in use,
|
||||
a listen(0) is done so that the system rejects any incoming SMTP session.
|
||||
This avois to fork and then reject the connexion.
|
||||
|
||||
If there are some free slots, nothing better than accepting the
|
||||
connection, then forking can be done. The child process then checks if
|
||||
the adequate class is full or not. If full, it rejects the connection
|
||||
with a "421 Too many sessions" diagnostic to the sender (which should
|
||||
then appear when the remote users do a mailq). If the treshold {reject_#}
|
||||
is not reached, the connection is accepted and the counter is sendmail.la
|
||||
is updated.
|
||||
|
||||
Handling outgoing SMTP sessions.
|
||||
|
||||
As soon as Sendmail needs to connect to a distant host, the adequate class
|
||||
is checked against {queue_#} and if no slots are available, the message is
|
||||
queued for further processing.
|
||||
|
||||
Sendmail's connection caching.
|
||||
|
||||
Sendmail-R6 introduces a new design: connection caching, ie several SMTP
|
||||
sessions can be opened at the same time. This could cause some problems
|
||||
when sending mail, as after having a few connections opened, all slots
|
||||
could be in use and generate a partial delivery of the message. In
|
||||
order to deal with this, xla.c uses following design "for a given
|
||||
sendmail process, only the first connection in a given class is counted".
|
||||
This can be done because sendmail does not do parralel message sending
|
||||
on the different channels.
|
||||
|
||||
End of connection.
|
||||
|
||||
As soon as a connection is closed, the counters will be automatically
|
||||
updated.
|
||||
|
||||
|
||||
|
||||
Please look at the code to understand of all this works. Comments,
|
||||
suggestions, questions welcome.
|
||||
|
||||
|
||||
|
||||
Christophe Wolfhugel
|
||||
Herve Schauer Consultants
|
||||
Paris, France
|
||||
May 23, 1993
|
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
* (C) Copyright 1993, Herve Schauer Consultants
|
||||
*
|
||||
* This module written by Christophe.Wolfhugel@hsc-sec.fr
|
||||
* is to be used under the same conditions and terms (and absence
|
||||
* or warranties) than the other modules of the Sendmail package.
|
||||
*
|
||||
* ABSOLUTELY NO WARRANTY. USE AT YOUR OWN RISKS.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifdef XLA
|
||||
|
||||
#ifndef MAXLARULES
|
||||
# define MAXLARULES 20
|
||||
#endif
|
||||
|
||||
# include "sendmail.h"
|
||||
|
||||
typedef struct {
|
||||
short queue; /* # of connexions to have queueing */
|
||||
short reject; /* # of conn. to reject */
|
||||
short num; /* # of increments this process */
|
||||
char *mask; /* Mask (domain) */
|
||||
} XLARULE;
|
||||
|
||||
char *XlaFname; /* Work file name */
|
||||
char XlaHostName[1024]; /* Temporary */
|
||||
int XlaNext; /* # of XlaRules */
|
||||
pid_t XlaPid; /* Pid updating the tables */
|
||||
XLARULE XlaRules[MAXLARULES]; /* The rules themselves */
|
||||
short XlaCtr[MAXLARULES]; /* Counter (for work file only) */
|
||||
|
||||
extern bool lockfile();
|
||||
|
||||
/*
|
||||
** XLAMATCH -- Matches a fnmatch like expression.
|
||||
**
|
||||
** Parameters:
|
||||
** mask -- mask to match the string too;
|
||||
** name -- string.
|
||||
**
|
||||
** Mask can either be a plain string or a simplified fnmatch like mask:
|
||||
** *.string or string.*
|
||||
** No other alternatives are accepted.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
|
||||
bool
|
||||
XlaMatch(mask, name)
|
||||
char *mask, *name;
|
||||
{
|
||||
int l1, l2;
|
||||
|
||||
l1 = strlen(mask); l2 = strlen(name);
|
||||
if (l1 == 1 && mask[0] == '*') return(TRUE);
|
||||
if (mask[0] == '*' && mask[1] == '.') {
|
||||
if (l2 < (l1 - 2)) return(FALSE);
|
||||
if (strcasecmp(&mask[2], name) == 0) return(TRUE);
|
||||
if (strcasecmp(&mask[1], name + l2 - l1 + 1) == 0) return(TRUE);
|
||||
return(FALSE);
|
||||
}
|
||||
if (l1 < 3) return(FALSE);
|
||||
if (mask[l1 -1] == '*') {
|
||||
if (l2 < l1 - 1) return(FALSE);
|
||||
if (strncasecmp(mask, name, l1 - 1) == 0) return(TRUE);
|
||||
return(FALSE);
|
||||
}
|
||||
if (strcasecmp(mask, name) == 0) return(TRUE);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
** XLAZERO -- Zeroes the used variables
|
||||
**
|
||||
** Just initializes some variables, called once at sendmail
|
||||
** startup.
|
||||
**
|
||||
** Parameters:
|
||||
** none.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** none.
|
||||
*/
|
||||
|
||||
xla_zero()
|
||||
{
|
||||
if (tTd(59, 1)) {
|
||||
printf("xla_zero\n");
|
||||
}
|
||||
XlaFname = NULL;
|
||||
XlaNext = 0;
|
||||
XlaPid = 0;
|
||||
memset(&XlaRules[0], 0, sizeof(XLARULE) * MAXLARULES);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XLAINIT -- initialized extended load average stuff
|
||||
**
|
||||
** This routine handles the L lines appearing in the configuration
|
||||
** file.
|
||||
**
|
||||
** L/etc/sendmail.la indicates the working file
|
||||
** Lmask #1 #2 Xtended LA to apply to mask
|
||||
** #1 = Queueing # of connections
|
||||
** #2 = Reject connections.
|
||||
**
|
||||
** Parameters:
|
||||
** line -- the cf file line to parse.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** Builds several internal tables.
|
||||
*/
|
||||
|
||||
xla_init(line)
|
||||
char *line;
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (tTd(59, 1)) {
|
||||
printf("xla_init line: %s\n", line);
|
||||
}
|
||||
if (XlaFname == NULL && *line == '/') { /* Work file name */
|
||||
XlaFname = newstr(line);
|
||||
if (tTd(59, 10))
|
||||
printf("xla_init: fname = %s\n", XlaFname);
|
||||
return;
|
||||
}
|
||||
if (XlaNext == MAXLARULES) {
|
||||
syserr("too many xla rules defined (%d max)", MAXLARULES);
|
||||
return;
|
||||
}
|
||||
s = strtok(line, " \t");
|
||||
if (s == NULL) {
|
||||
syserr("xla: line unparseable");
|
||||
return;
|
||||
}
|
||||
XlaRules[XlaNext].mask = newstr(s);
|
||||
s = strtok(NULL, " \t");
|
||||
if (s == NULL) {
|
||||
syserr("xla: line unparseable");
|
||||
return;
|
||||
}
|
||||
XlaRules[XlaNext].queue = atoi(s);
|
||||
s = strtok(NULL, " \t");
|
||||
if (s == NULL) {
|
||||
syserr("xla: line unparseable");
|
||||
return;
|
||||
}
|
||||
XlaRules[XlaNext].reject = atoi(s);
|
||||
if (tTd(59, 10))
|
||||
printf("xla_init: rule #%d = %s q=%d r=%d\n", XlaNext,
|
||||
XlaRules[XlaNext].mask,
|
||||
XlaRules[XlaNext].queue, XlaRules[XlaNext].reject);
|
||||
XlaNext++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XLACREATEFILE -- Create the working file
|
||||
**
|
||||
** Tries to create the working file, called each time sendmail is
|
||||
** invoked with the -bd option.
|
||||
**
|
||||
** Parameters:
|
||||
** none.
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** Creates the working file (sendmail.la) and zeroes it.
|
||||
*/
|
||||
|
||||
xla_create_file()
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_create_file:\n");
|
||||
if (XlaFname == NULL) return;
|
||||
fd = open(XlaFname, O_RDWR|O_CREAT, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_create_file: open failed");
|
||||
return;
|
||||
}
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_create_file: can't set lock");
|
||||
return;
|
||||
}
|
||||
if (ftruncate(fd, 0) == -1) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_create_file: can't truncate XlaFname");
|
||||
return;
|
||||
}
|
||||
if (write(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
XlaFname == NULL;
|
||||
syserr("xla_create_file: can't write XlaFname");
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XLASMTPOK -- Checks if all slots are in use
|
||||
**
|
||||
** Check is there are still some slots available for an SMTP
|
||||
** connection.
|
||||
**
|
||||
** Parameters:
|
||||
** none.
|
||||
**
|
||||
** Returns:
|
||||
** TRUE -- slots are available;
|
||||
** FALSE -- no more slots.
|
||||
**
|
||||
** Side Effects:
|
||||
** Reads a file, uses a lock and updates sendmail.la if a slot
|
||||
** is free for use.
|
||||
*/
|
||||
|
||||
bool
|
||||
xla_smtp_ok()
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_smtp_ok:\n");
|
||||
if (XlaFname == NULL) return(TRUE);
|
||||
fd = open(XlaFname, O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_smtp_ok: open failed");
|
||||
return(TRUE);
|
||||
}
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_smtp_ok: can't set lock");
|
||||
return(TRUE);
|
||||
}
|
||||
if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_smtp_ok: can't read XlaFname");
|
||||
return(TRUE);
|
||||
}
|
||||
close(fd);
|
||||
for (i = 0; i < XlaNext; i++) {
|
||||
if (XlaCtr[i] < XlaRules[i].reject)
|
||||
return(TRUE);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XLAHOSTOK -- Can we accept a connection from this host
|
||||
**
|
||||
** Check the quota for the indicated host
|
||||
**
|
||||
** Parameters:
|
||||
** name -- host name or IP# (string)
|
||||
**
|
||||
** Returns:
|
||||
** TRUE -- we can accept the connection;
|
||||
** FALSE -- we must refuse the connection.1
|
||||
**
|
||||
** Side Effects:
|
||||
** Reads and writes a file, uses a lock and still updates
|
||||
** sendmail.la is a slot gets assigned.
|
||||
*/
|
||||
|
||||
bool
|
||||
xla_host_ok(name)
|
||||
char *name;
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_host_ok:\n");
|
||||
if (XlaFname == NULL) return(TRUE);
|
||||
fd = open(XlaFname, O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_host_ok: open failed");
|
||||
return(TRUE);
|
||||
}
|
||||
XlaPid = getpid();
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_host_ok: can't set lock");
|
||||
return(TRUE);
|
||||
}
|
||||
if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_smtp_ok: can't read XlaFname");
|
||||
return(TRUE);
|
||||
}
|
||||
strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
|
||||
XlaHostName[sizeof(XlaHostName) -1] = 0;
|
||||
i = strlen(name) - 1;
|
||||
if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
|
||||
for (i = 0; i < XlaNext; i++) {
|
||||
if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
|
||||
if (XlaCtr[i] < XlaRules[i].reject) {
|
||||
if (XlaRules[i].num++ == 0) {
|
||||
XlaCtr[i]++;
|
||||
lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
|
||||
if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i])) != sizeof(XlaCtr[i]))
|
||||
XlaFname = NULL;
|
||||
}
|
||||
close(fd);
|
||||
return(TRUE);
|
||||
}
|
||||
close(fd);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
** XLANOQUEUEOK -- Can we sent this message to the remote host
|
||||
**
|
||||
** Check if we can send to the remote host
|
||||
**
|
||||
** Parameters:
|
||||
** name -- host name or IP# (string)
|
||||
**
|
||||
** Returns:
|
||||
** TRUE -- we can send the message to the remote site;
|
||||
** FALSE -- we can't connect the remote host, queue.
|
||||
**
|
||||
** Side Effects:
|
||||
** Reads and writes a file, uses a lock.
|
||||
** And still updates the sendmail.la file.
|
||||
*/
|
||||
|
||||
bool
|
||||
xla_noqueue_ok(name)
|
||||
char *name;
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_noqueue_ok:\n");
|
||||
if (XlaFname == NULL) return(TRUE);
|
||||
fd = open(XlaFname, O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_noqueue_ok: open failed");
|
||||
return(TRUE);
|
||||
}
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_noqueue_ok: can't set lock");
|
||||
return(TRUE);
|
||||
}
|
||||
XlaPid = getpid();
|
||||
if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_noqueue_ok: can't read XlaFname");
|
||||
return(TRUE);
|
||||
}
|
||||
strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
|
||||
XlaHostName[sizeof(XlaHostName) -1] = 0;
|
||||
i = strlen(name) - 1;
|
||||
if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
|
||||
for (i = 0; i < XlaNext; i++) {
|
||||
if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
|
||||
if (XlaCtr[i] < XlaRules[i].queue) {
|
||||
if (XlaRules[i].num++ == 0) {
|
||||
XlaCtr[i]++;
|
||||
lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
|
||||
if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i])) != sizeof(XlaCtr[i]))
|
||||
XlaFname = NULL;
|
||||
}
|
||||
close(fd);
|
||||
return(TRUE);
|
||||
}
|
||||
close(fd);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** XLAHOSTEND -- Notice that a connection is terminated.
|
||||
**
|
||||
** Updates the counters to reflect the end of an SMTP session
|
||||
** (in or outgoing).
|
||||
**
|
||||
** Parameters:
|
||||
** name -- host name or IP# (string)
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** Reads and writes a file, uses a lock.
|
||||
** And still updates sendmail.la.
|
||||
*/
|
||||
|
||||
xla_host_end(name)
|
||||
char *name;
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_host_end:\n");
|
||||
if (XlaFname == NULL || XlaPid != getpid()) return;
|
||||
fd = open(XlaFname, O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_host_end: open failed");
|
||||
return;
|
||||
}
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_host_end: can't set lock");
|
||||
return;
|
||||
}
|
||||
if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_host_end: can't read XlaFname");
|
||||
return(TRUE);
|
||||
}
|
||||
strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
|
||||
XlaHostName[sizeof(XlaHostName) -1] = 0;
|
||||
i = strlen(name) - 1;
|
||||
if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
|
||||
for (i = 0; i < XlaNext; i++) {
|
||||
if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
|
||||
if (XlaRules[i].num > 0 && XlaRules[i].num-- == 1) {
|
||||
if (XlaCtr[i]) XlaCtr[i]--;
|
||||
lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
|
||||
if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i]))
|
||||
!= sizeof(XlaCtr[i]))
|
||||
XlaFname = NULL;
|
||||
}
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
** XLAALLEND -- Mark all connections as closed.
|
||||
**
|
||||
** Generally due to an emergency exit.
|
||||
**
|
||||
** Parameters:
|
||||
** name -- host name or IP# (string)
|
||||
**
|
||||
** Returns:
|
||||
** none.
|
||||
**
|
||||
** Side Effects:
|
||||
** Reads and writes a file, uses a lock.
|
||||
** And guess what: updates sendmail.la.
|
||||
*/
|
||||
|
||||
xla_all_end()
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
if (tTd(59, 1))
|
||||
printf("xla_all_end:\n");
|
||||
if (XlaFname == NULL || XlaPid != getpid()) return;
|
||||
fd = open(XlaFname, O_RDWR, 0644);
|
||||
if (fd == -1) {
|
||||
XlaFname = NULL;
|
||||
syserr("xla_all_end: open failed");
|
||||
return;
|
||||
}
|
||||
if (!lockfile(fd, XlaFname, LOCK_EX)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_all_end: can't set lock");
|
||||
return;
|
||||
}
|
||||
if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
close(fd);
|
||||
XlaFname = NULL;
|
||||
syserr("xla_all_end: can't read XlaFname");
|
||||
return(TRUE);
|
||||
}
|
||||
for (i = 0; i < XlaNext; i++) {
|
||||
if (XlaCtr[i] > 0 && XlaRules[i].num > 0) {
|
||||
XlaCtr[i]--; XlaRules[i].num = 0;
|
||||
}
|
||||
}
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
if (write(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
|
||||
XlaFname = NULL;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
#endif /* XLA */
|
Loading…
Reference in New Issue