📄 xla.c
字号:
/* * (C) Copyright 1993-94, 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. * * Version: 940417, applied a patch from Paul Graham <pjg@acsu.buffalo.edu> * (lockfile syntax in xla.c did not reflect anymore the * new one used by sendmail, now fine). * */#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.*/boolXlaMatch(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((char *) &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, NULL, 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.*/boolxla_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, NULL, 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.*/boolxla_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, NULL, 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.*/boolxla_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, NULL, 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, NULL, 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, NULL, 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -