/*
messagewallstats.c - MessageWall statistics program
Copyright (C) 2002 Ian Gulliver
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <firestring.h>
static const char tagstring[] = "$Id: messagewallstats.c,v 1.17.2.3 2002/10/01 19:05:22 ian Exp $";
struct counter {
char *name;
int count;
struct counter *next;
};
struct counter *dnsbl = NULL;
struct counter *filename = NULL;
struct counter *body_text = NULL;
struct counter *rdns = NULL;
struct counter *rdns_temp = NULL;
struct counter *rmx = NULL;
struct counter *rmx_temp = NULL;
struct counter *to_cc = NULL;
struct counter *from = NULL;
struct counter *dnsbl_domain = NULL;
struct counter *dnsdcc = NULL;
struct counter *header = NULL;
struct counter *charfrom = NULL;
struct counter *charto = NULL;
struct counter *overflow = NULL;
struct counter *per_ip = NULL;
struct counter *virus = NULL;
struct counter *encoding = NULL;
struct counter *illegal_multipart = NULL;
void increment(struct counter **head, char *name) {
struct counter *temp;
temp = *head;
while (temp != NULL) {
if (firestring_strcasecmp(temp->name,name) == 0) {
temp->count++;
return;
}
temp = temp->next;
}
temp = *head;
*head = firestring_malloc(sizeof(struct counter));
(*head)->count = 1;
(*head)->name = firestring_strdup(name);
(*head)->next = temp;
}
void print (struct counter *head, char *begin) {
struct counter *temp;
struct counter *max;
while (1) {
temp = head;
max = NULL;
while (temp != NULL) {
if (max == NULL || temp->count > max->count)
max = temp;
temp = temp->next;
}
if (max == NULL)
break;
if (max->count == 0)
break;
fprintf(stdout,"%s%s: %d\n",begin,max->name,max->count);
max->count = 0;
}
}
int main(int argc, char *argv[]) {
FILE *f;
char line[2048];
int connections = 0;
int quit = 0;
int disconnect = 0;
int disconnect_data = 0;
long bytes_total = 0;
long bytes_delivered = 0;
long bytes_received =0;
int idle = 0;
int errors = 0;
int bare_lf = 0;
int bare_lf_data = 0;
int client_8bit = 0;
int tls_attempt = 0;
int tls_success = 0;
int invalid_mail = 0;
int invalid_rcpt = 0;
int messages = 0;
int messages_reject = 0;
int messages_received = 0;
int backend_send = 0;
int backend_accept = 0;
int filter_reject = 0;
int filter_dnsdcc = 0;
int filter_dnsbl_domain = 0;
int filter_dnsbl = 0;
int filter_to_cc = 0;
int filter_from = 0;
int filter_rmx = 0;
int filter_rdns = 0;
int filter_rmx_temp = 0;
int filter_rdns_temp = 0;
int filter_header = 0;
int filter_body = 0;
int filter_filename = 0;
int filter_virus = 0;
int filter_useless = 0;
int filter_noboundary = 0;
int filter_toomanyparts = 0;
int filter_illegalmultipart = 0;
int filter_unknownencoding = 0;
int filter_qp = 0;
int filter_base64 = 0;
int backend_attempt = 0;
int backend_success = 0;
int backend_tls_success = 0;
int backend_overflows = 0;
int backend_reject_overflows = 0;
int overflows = 0;
int per_ips = 0;
char *end;
char *start;
if (argc != 2) {
fprintf(stderr,"usage: %s <log file>\n",argv[0]);
exit(100);
}
f = fopen(argv[1],"r");
if (f == NULL) {
perror("fopen");
exit(100);
}
while (fgets(line,2048,f) != NULL) {
if (strstr(line,") SERVER/STATUS: connection from") != NULL) {
connections++;
continue;
}
if (strstr(line,"SMTP/FATAL: client QUIT") != NULL) {
quit++;
continue;
}
if (strstr(line,"SERVER/FATAL: disconnect\n") != NULL) {
disconnect++;
continue;
}
if (strstr(line,"SERVER/FATAL: disconnect inside DATA\n") != NULL) {
disconnect_data++;
continue;
}
if (strstr(line,"bare LF inside DATA\n") != NULL) {
bare_lf_data++;
continue;
}
if (strstr(line,"bare LF in command\n") != NULL) {
bare_lf++;
continue;
}
if (strstr(line,"SERVER/FATAL: idle timeout\n") != NULL) {
idle++;
continue;
}
if (strstr(line,"SMTP/FATAL: too many errors\n") != NULL) {
errors++;
continue;
}
if (strstr(line,") TLS/STATUS: TLS negotiation started") != NULL) {
tls_attempt++;
continue;
}
if (strstr(line,") TLS/SUCCESS: now speaking TLS") != NULL) {
tls_success++;
continue;
}
if (strstr(line,": Message start") != NULL) {
messages++;
continue;
}
if (strstr(line,"PROFILE/REJECT: reject set in profile\n") != NULL) {
messages_reject++;
continue;
}
if ((start = strstr(line,"SMTP/STATUS: received message")) != NULL) {
messages_received++;
sscanf(start,"SMTP/STATUS: received message of %ld bytes\n",&bytes_received);
bytes_total += bytes_received;
continue;
}
if ((start = strstr(line,"invalid MAIL character (")) != NULL) {
invalid_mail++;
start += 24;
start[1] = '\0';
increment(&charfrom,start);
continue;
}
if ((start = strstr(line,"invalid RCPT character (")) != NULL) {
invalid_rcpt++;
start += 24;
start[1] = '\0';
increment(&charto,start);
continue;
}
if (strstr(line,") BACKEND/STATUS: message to [") != NULL) {
backend_send++;
bytes_delivered += bytes_received;
bytes_received = 0;
continue;
}
if (strstr(line,"] BACKEND/ACCEPT: accepted message responsibility:") != NULL) {
backend_accept++;
continue;
}
if (strstr(line,"has reached or exceeded maximum") != NULL) {
filter_reject++;
continue;
}
if ((start = strstr(line,"DNSDCC/WARNING: ")) != NULL) {
filter_dnsdcc++;
start += 16;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&dnsdcc,start);
}
continue;
}
if ((start = strstr(line,"DNSBL/WARNING: ")) != NULL) {
filter_dnsbl++;
start += 15;
end = strchr(start,'/');
if (end != NULL) {
*end = '\0';
increment(&dnsbl,start);
}
continue;
}
if ((start = strstr(line,"DNSBL-DOMAIN/WARNING: ")) != NULL) {
filter_dnsbl_domain++;
start += 22;
end = strchr(start,'/');
if (end != NULL) {
*end = '\0';
increment(&dnsbl_domain,start);
}
continue;
}
if (strstr(line,"envelope forward path not in To/CC\n") != NULL) {
filter_to_cc++;
start = strstr(line,"RFC822/WARNING: ");
if (start == NULL)
continue;
start += 16;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&to_cc,start);
}
continue;
}
if (strstr(line,"envelope reverse path not in From\n") != NULL) {
filter_from++;
start = strstr(line,"RFC822/WARNING: ");
if (start == NULL)
continue;
start += 16;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&from,start);
}
continue;
}
if (strstr(line,"reverse path domain has no MX or A records (temporary)\n") != NULL) {
filter_rmx_temp++;
start = strstr(line,"RMX/WARNING: ");
if (start == NULL)
continue;
start += 13;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&rmx_temp,start);
}
continue;
}
if (strstr(line,"reverse path domain has no MX or A records\n") != NULL) {
filter_rmx++;
start = strstr(line,"RMX/WARNING: ");
if (start == NULL)
continue;
start += 13;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&rmx,start);
}
continue;
}
if (strstr(line,"IP has no reverse DNS (temporary)\n") != NULL) {
filter_rdns_temp++;
start = strstr(line,"RDNS/WARNING: ");
if (start == NULL)
continue;
start += 14;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&rdns_temp,start);
}
continue;
}
if (strstr(line,"IP has no reverse DNS\n") != NULL) {
filter_rdns++;
start = strstr(line,"RDNS/WARNING: ");
if (start == NULL)
continue;
start += 14;
end = strchr(start,':');
if (end != NULL) {
*end = '\0';
increment(&rdns,start);
}
continue;
}
if ((start = strstr(line,"message failed header check for ")) != NULL) {
filter_header++;
start += 32;
end = strchr(start,'\n');
if (end != NULL) {
*end = '\0';
increment(&header,start);
}
continue;
}
if ((start = strstr(line,"body text contains '")) != NULL) {
filter_body++;
start += 20;
end = strchr(start,'\'');
if (end != NULL) {
*end = '\0';
increment(&body_text,start);
}
continue;
}
if ((start = strstr(line,"illegal attachment filename: '")) != NULL) {
filter_filename++;
start += 30;
start = strstr(start,"\' contains \'");
if (start == NULL)
continue;
start += 12;
end = strchr(start,'\'');
if (end != NULL) {
*end = '\0';
increment(&filename,start);
}
continue;
}
if (strstr(line,"BACKEND/STATUS: connect to") != NULL) {
backend_attempt++;
continue;
}
if (strstr(line,"BACKEND/STATUS: connection established") != NULL) {
backend_success++;
continue;
}
if (strstr(line,"] TLS/SUCCESS: now speaking TLS") != NULL) {
backend_tls_success++;
continue;
}
if ((start = strstr(line,"per-ip overflow from ")) != NULL) {
per_ips++;
start += 21;
end = strchr(start,'\n');
if (end != NULL) {
*end = '\0';
increment(&per_ip,start);
}
continue;
}
if ((start = strstr(line,"client overflow from ")) != NULL) {
overflows++;
start += 21;
end = strchr(start,'\n');
if (end != NULL) {
*end = '\0';
increment(&overflow,start);
}
continue;
}
if (strstr(line,"none available to receive message") != NULL) {
backend_overflows++;
continue;
}
if (strstr(line,"none available to receive reject") != NULL) {
backend_reject_overflows++;
continue;
}
if ((start = strstr(line,"message body matches pattern for '")) != NULL) {
filter_virus++;
start += 34;
end = strchr(start,'\'');
if (end != NULL) {
*end = '\0';
increment(&virus,start);
}
continue;
}
if (strstr(line,"message contains no parts accepted at this address\n") != NULL) {
filter_useless++;
continue;
}
if (strstr(line,"unable to find boundary\n") != NULL) {
filter_noboundary++;
continue;
}
if (strstr(line,"too many parts\n") != NULL) {
filter_toomanyparts++;
continue;
}
if ((start = strstr(line,"illegal multipart encoding: ")) != NULL) {
filter_illegalmultipart++;
start += 28;
end = strchr(start,'\n');
if (end != NULL) {
*end = '\0';
increment(&illegal_multipart,start);
}
continue;
}
if ((start = strstr(line,"unknown encoding: ")) != NULL) {
filter_unknownencoding++;
start += 18;
end = strchr(start,'\n');
if (end != NULL) {
*end = '\0';
increment(&encoding,start);
}
continue;
}
if (strstr(line,"invalid quoted-printable encoding") != NULL) {
filter_qp++;
continue;
}
if (strstr(line,"invalid base64 encoding") != NULL) {
filter_base64++;
continue;
}
if (strstr(line,"client sent 8bit data to server in 7bit mode") != NULL) {
client_8bit++;
continue;
}
}
fprintf(stdout,"Client Connections: %d\n",connections);
fprintf(stdout,"\tQUIT: %d\n",quit);
fprintf(stdout,"\tDisconnect: %d\n",disconnect);
fprintf(stdout,"\tDisconnect inside DATA: %d\n",disconnect_data);
fprintf(stdout,"\tBare LF: %d\n",bare_lf);
fprintf(stdout,"\tIdle Timeout: %d\n",idle);
fprintf(stdout,"\tToo many errors: %d\n",errors);
fprintf(stdout,"\n");
fprintf(stdout,"Client TLS Attempts: %d\n",tls_attempt);
fprintf(stdout,"\tSuccess: %d\n",tls_success);
fprintf(stdout,"\n");
fprintf(stdout,"Overflows: %d\n",overflows);
print(overflow,"\t");
fprintf(stdout,"Per-IP Overflows: %d\n",per_ips);
print(per_ip,"\t");
fprintf(stdout,"\n");
fprintf(stdout,"Backend Overflows: %d\n",backend_overflows);
fprintf(stdout,"Backend Rejection Overflows: %d\n",backend_reject_overflows);
fprintf(stdout,"\n");
fprintf(stdout,"Backend connection attempts: %d\n",backend_attempt);
fprintf(stdout,"\tSuccess: %d\n",backend_success);
fprintf(stdout,"\tTLS: %d\n",backend_tls_success);
fprintf(stdout,"\n");
fprintf(stdout,"Invalid MAIL characters: %d\n",invalid_mail);
print(charfrom,"\t");
fprintf(stdout,"Invalid RCPT characters: %d\n",invalid_rcpt);
print(charto,"\t");
fprintf(stdout,"\n");
fprintf(stdout,"Client Messages: %d\n",messages);
fprintf(stdout,"\tBare LF inside DATA: %d\n",bare_lf_data);
fprintf(stdout,"\t8bit inside DATA: %d\n",client_8bit);
fprintf(stdout,"\tRejected by Profile: %d\n",messages_reject);
fprintf(stdout,"\tCompletely Received: %d\n",messages_received);
fprintf(stdout,"\tSent to Backend: %d\n",backend_send);
fprintf(stdout,"\tAccepted by Backend: %d\n",backend_accept);
fprintf(stdout,"\n");
fprintf(stdout,"Messages Rejected by Filter: %d\n",filter_reject);
fprintf(stdout,"\tFailed To/CC: %d\n",filter_to_cc);
print(to_cc,"\t\t");
fprintf(stdout,"\tFailed From: %d\n",filter_from);
print(from,"\t\t");
fprintf(stdout,"\tMatched DNSBL: %d\n",filter_dnsbl);
print(dnsbl,"\t\t");
fprintf(stdout,"\tMatched Domain DNSBL: %d\n",filter_dnsbl_domain);
print(dnsbl_domain,"\t\t");
fprintf(stdout,"\tMatched DNSDCC: %d\n",filter_dnsdcc);
print(dnsdcc,"\t\t");
fprintf(stdout,"\tReverse Path MX/A lookup timed out: %d\n",filter_rmx_temp);
print(rmx_temp,"\t\t");
fprintf(stdout,"\tReverse DNS lookup timed out: %d\n",filter_rdns_temp);
print(rdns_temp,"\t\t");
fprintf(stdout,"\tFailed Reverse Path MX/A: %d\n",filter_rmx);
print(rmx,"\t\t");
fprintf(stdout,"\tFailed Reverse DNS: %d\n",filter_rdns);
print(rdns,"\t\t");
fprintf(stdout,"\tFailed Body check: %d\n",filter_body);
print(body_text,"\t\t");
fprintf(stdout,"\tFailed Header check: %d\n",filter_header);
print(header,"\t\t");
fprintf(stdout,"\tIllegal attachment filename: %d\n",filter_filename);
print(filename,"\t\t");
fprintf(stdout,"\tVirus: %d\n",filter_virus);
print(virus,"\t\t");
fprintf(stdout,"\tNo accepted MIME parts: %d\n",filter_useless);
fprintf(stdout,"\tMissing MIME boundary: %d\n",filter_noboundary);
fprintf(stdout,"\tToo many parts: %d\n",filter_toomanyparts);
fprintf(stdout,"\tIllegal multipart encoding: %d\n",filter_illegalmultipart);
print(illegal_multipart,"\t\t");
fprintf(stdout,"\tUnknown MIME encoding: %d\n",filter_unknownencoding);
print(encoding,"\t\t");
fprintf(stdout,"\tInvalid QP encoding: %d\n",filter_qp);
fprintf(stdout,"\tInvalid base64 encoding: %d\n",filter_base64);
fprintf(stdout,"\n");
fprintf(stdout,"Mail Traffic\n");
fprintf(stdout,"\tBytes received: %ld\n",bytes_total);
fprintf(stdout,"\tBytes rejected: %ld\n",bytes_total - bytes_delivered);
fprintf(stdout,"\tBytes accepted: %ld\n",bytes_delivered);
exit(0);
}
syntax highlighted by Code2HTML, v. 0.9.1