s/qmail 4.4.13
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-mrtg.c
Go to the documentation of this file.
1#include <unistd.h>
2#include "stralloc.h"
3#include "buffer.h"
4#include "getln.h"
5#include "exit.h"
6#include "open.h"
7#include "scan.h"
8#include "fmt.h"
9#include "case.h"
10#include "now.h"
11#include "str.h"
12#include "datetime.h"
13#include "logmsg.h"
14#include "qmail.h"
15
16#define WHO "qmail-mrtg"
17#define TAI64NLEN 24
18
25/* qmail-send */
26
27int local = 0;
28int remote = 0;
29int success = 0;
30int failure = 0;
31int bytes = 0;
32int tlstrans = 0;
33int deferral = 0;
34int bounces = 0;
35int triples = 0;
36int qmtp = 0;
37int qmtps = 0;
38
39/* qmail-smtpd */
40
41int asessions = 0;
42int rsessions = 0;
43int aorig = 0;
44int arcpt = 0;
45int rsend = 0;
46int rhelo = 0;
47int rorigbad = 0;
48int rorigdns = 0;
49int rrcptbad = 0;
50int rrcptfail = 0;
51int rsize = 0;
52int rmime = 0;
53int rloader = 0;
54int rvirus = 0;
55int rspam = 0;
56int adkim = 0;
57int rdkim = 0;
58int aauth = 0;
59int rauth = 0;
60int atls = 0;
61int rtls = 0;
62int spfpass = 0;
63int spfail = 0;
64
65/* qmail-pop3d */
66
67int apop = 0;
68int rpop = 0;
69int pok = 0;
70int pdeny = 0;
71
72/* *server + rblsmtpd */
73
74int sok = 0;
75int sdeny = 0;
76int greet = 0;
77int grey = 0;
78int rbl = 0;
79
80char bufsmall[BUFFER_SMALL];
81buffer bo = BUFFER_INIT(buffer_unixwrite,1,bufsmall,sizeof(bufsmall));
82
83static void outs(char *s)
84{
85 if (buffer_puts(&bo,s) == -1) _exit(1);
86 if (buffer_puts(&bo,"\n") == -1) _exit(1);
87 if (buffer_flush(&bo) == -1) _exit(1);
88}
89
90static void out(int i)
91{
92 char num[FMT_ULONG];
93
94 if (buffer_put(&bo,num,fmt_ulong(num,(unsigned long) i)) == -1) _exit(1);
95 if (buffer_puts(&bo,"\n") == -1) _exit(1);
96 if (buffer_flush(&bo) == -1) _exit(1);
97}
98
100buffer bi = BUFFER_INIT(buffer_unixread,0,bufspace,sizeof(bufspace));
101
102static void mrtg_results(char flag)
103{
104 switch (flag) {
105 case '1': out(success); out(tlstrans); break;
106 case '2': bytes = bytes/1024; out(bytes); out(bytes); break;
107 case '3': out(local); out(remote); break;
108 case '4': out(failure); out(deferral); break;
109 case '5': out(bounces); out(triples); break;
110 case '6': qmtps += qmtp; out(qmtp); out(qmtps); break; /* QMTP */
111
112 case 'a': out(asessions); out(rsessions); break; /* total */
113 case 'b': out(aorig); out(arcpt); break; /* accepted */
114 case 'c': out(rsend); out(rhelo); break; /* rejected MTA */
115 case 'd': out(rorigbad); out(rorigdns); break; /* Orig */
116 case 'e': out(rrcptbad); out(rrcptfail); break; /* Recipient */
117 case 'f': out(rmime); out(rloader); break; /* Warlord */
118 case 'g': out(rvirus); out(rspam); break; /* Infected/Spam */
119 case 'h': out(aauth); out(rauth); break; /* Auth */
120 case 'i': out(atls); out(rtls); break; /* TLS */
121 case 'j': out(spfpass); out(spfail); break; /* SPF */
122 case 'k': out(grey); out(greet); break; /* Greylisted/Greetdelay */
123 case 'm': out(rdkim); break; /* DKIM rejected */
124 case 'z': sdeny +=rbl; out(sok); out(sdeny); break; /* ok/reject session */
125
126 case 'A': out(apop); out(rpop); break;
127 case 'B': out(pok); out(pdeny); break;
128
129 default: break;
130 }
131}
132
133static void mrtg_sendlog(char *in, char flag)
134{
135 int i, j, k = 0;
136
137 switch (flag) {
138 case '1': if (case_starts(in,"delivery")) {
139 i = str_chr(in,':') + 2;
140 if (case_starts(in + i,"success:")) success++;
141 i = str_chr(in,'T');
142 if (case_starts(in + i,"TLS_")) tlstrans++;
143 }; break;
144 case '2': if (case_starts(in,"info msg")) {
145 i = str_chr(in,':') + 8;
146 if ((j = str_chr(in + i,' '))) in[i + j] = '\0';
147 bytes += atoi(in + i);
148 }; break;
149 case '3': if (case_starts(in,"status:")) {
150 i = str_rchr(in,'c') + 4;
151 k = str_rchr(in,'r') + 7;
152 if ((j = str_chr(in + i,'/'))) in[i + j] = '\0';
153 if (atoi(in + i) > local) local = atoi(in + i);
154 if ((j = str_chr(in + k,'/'))) in[k + j] = '\0';
155 if (atoi(in + k) > remote) remote = atoi(in + k);
156 }; break;
157 case '4': if (case_starts(in,"delivery")) {
158 i = str_chr(in,':') + 2;
159 if (case_starts(in + i,"failure:")) failure++;
160 if (case_starts(in + i,"deferral:")) deferral++;
161 }; break;
162 case '5': if (case_starts(in,"bounce msg")) bounces++;
163 if (case_starts(in,"triple bounce:")) triples++;
164 break;
165 case '6': if (case_starts(in,"delivery")) {
166 i = str_chr(in,'q');
167 if (case_starts(in + i,"qmtp:_ok")) qmtp++;
168 if (case_starts(in + i,"qmtps:_ok")) qmtps++;
169 }; break;
170 default: break;
171 }
172}
173
174static void mrtg_smtplog(char *in, char flag)
175{
176 int A, D, P, R, c, r = 0;
177
178 A = str_chr(in,'A');
179 D = str_chr(in,'D');
180 R = str_chr(in,'R');
181 P = str_chr(in,'P');
182
183 switch (flag) {
184 case 'a': if (case_starts(in + A,"Accept")) asessions++;
185 if (case_starts(in + R,"Reject")) rsessions++;
186 break;
187 case 'b': if (case_starts(in + A,"Accept::ORIG:")) aorig++;
188 if (case_starts(in + A,"Accept::RCPT:")) arcpt++;
189 if (case_starts(in + A,"Accept::SPF:Rcpthosts")) arcpt++;
190 if (case_starts(in + A,"Accept::SPF:Recipients")) arcpt++;
191 break;
192 case 'c': if (case_starts(in + R,"Reject::SNDR::Invalid_Relay")) rsend++;
193 if (case_starts(in + R,"Reject::SNDR::Bad_Helo")) rhelo++;
194 if (case_starts(in + R,"Reject::SNDR::DNS_Helo")) rhelo++;
195 break;
196 case 'd': if (case_starts(in + R,"Reject::ORIG::Bad_Mailfrom")) rorigbad++;
197 if (case_starts(in + R,"Reject::ORIG::DNS_MF")) rorigdns++;
198 break;
199 case 'e': if (case_starts(in + R,"Reject::RCPT::Bad_Rcptto")) rrcptbad++;
200 if (case_starts(in + R,"Reject::RCPT::Failed_Rcptto")) rrcptfail++;
201 break;
202 case 'f': if (case_starts(in + R,"Reject::DATA::Invalid_Size")) rsize++;
203 if (case_starts(in + R,"Reject::DATA::Bad_MIME")) rmime++;
204 if (case_starts(in + R,"Reject::DATA::MIME_Attach")) rmime++;
205 if (case_starts(in + R,"Reject::DATA::Bad_Loader")) rloader++;
206 break;
207 case 'g': if (case_starts(in + R,"Reject::DATA::Spam_Message")) rspam++;
208 if (case_starts(in + R,"Reject::DATA::Virus_Infected")) rvirus++;
209 break;
210 case 'h': if (case_starts(in + A,"Accept::AUTH:")) aauth++;
211 if (case_starts(in + R,"Reject::AUTH:")) rauth++;
212 break;
213 case 'i': if (case_starts(in + P,"P:ESMTPS")) atls++;
214 if (case_starts(in + R,"Reject::TLS:")) rtls++;
215 break;
216 case 'j': if (case_starts(in + A,"Accept::SPF:")) spfpass++;
217 if (case_starts(in + R,"Reject::SPF:")) spfail++;
218 break;
219 case 'k': if (case_starts(in + D,"Deferred::SNDR::Grey_Listed")) grey++;
220 if (case_starts(in,"rblsmtpd")) {
221 c = str_chr(in,':') + 2;
222 r = str_chr(in + r,':') + 2;
223 if (case_starts(in + c + r + 1,"reetdelay:")) greet++; // G|greetdelay
224 }
225 break;
226 case 'm': if (case_starts(in + A,"Accepted::SNDR::DKIM_Signature")) adkim++;
227 if (case_starts(in + R,"Rejected::SNDR::DKIM_Signature")) rdkim++;
228 break;
229 case 'z': if (case_starts(in,"tcpserver") || case_starts(in,"sslserver") || case_starts(in,"rblsmtpd")) {
230 c = str_chr(in,':') + 2;
231 if (case_starts(in + c,"ok")) sok++;
232 if (case_starts(in + c,"deny")) sdeny++;
233 r = str_chr(in + r,':') + 2;
234 if (case_starts(in + c + r,"451")) rbl++;
235 if (case_starts(in + c + r,"553")) rbl++;
236 } break;
237 default: break;
238 }
239}
240
241static void mrtg_pop3log(char *in, char flag)
242{
243 int A, R, c = 0;
244
245 switch (flag) {
246 case 'A': A = str_chr(in,'A'); R = str_chr(in,'R');
247 if (case_starts(in + A,"Accept::AUTH:")) apop++;
248 if (case_starts(in + R,"Reject::AUTH:")) rpop++;
249 break;
250 case 'B': if (case_starts(in,"tcpserver:") || case_starts(in,"sslserver:")) {
251 c = str_chr(in,':') + 2;
252 if (case_starts(in + c,"ok")) pok++;
253 if (case_starts(in + c,"deny")) pdeny++;
254 }; break;
255 default: break;
256 }
257}
258
259int main(int argc,char * const argv[])
260{
261 int i;
262 int c;
263 int match;
264 int enoughtime = 0;
265 unsigned long u;
266 unsigned long calltime;
267 unsigned long seconds;
268 unsigned long nanoseconds;
269 unsigned int history = 305;
270 char flag;
271
272 stralloc line = {0};
273 calltime = now();
274
275 if (argc < 2)
276 logmsg(WHO,100,USAGE,"qmail-mrtg [ -1 | -2 | -3 | -4 | -5 | -6 |\
277 -a | -b | -c | -d | -e | -f | -g | -h | -i | -j | -k | -m | -z | -A | -B ] [time (min)] \n\
278 qmail-mrtg needs to be called every [time] minutes (i.e. by crontab) - default 305 secs");
279
280 flag = *(argv[1] + 1);
281 if (argc == 3) { scan_ulong(argv[2],&u); history = 60 * u + 5; }
282
283/* Read input lines sequentially */
284
285 buffer_init(&bi,buffer_unixread,0,bufspace,sizeof(bufspace));
286
287 for (;;) {
288 if (getln(&bi,&line,&match,'\n') != 0) _exit(1);
289 if (!match) break;
290 if (!stralloc_0(&line)) _exit(1);
291
292 seconds = 0;
293 nanoseconds = 0;
294
295 if (line.s[0] == '@') { /* tai64 timestamp */
296 for (i = 1; i <= TAI64NLEN; i++) {
297 c = (int)line.s[i];
298 u = c - '0';
299 if (u >= 10) {
300 u = c - 'a';
301 if (u >= 6) break;
302 u += 10;
303 }
304 seconds <<= 4;
305 seconds += nanoseconds >> 28;
306 nanoseconds &= 0xfffffff;
307 nanoseconds <<= 4;
308 nanoseconds += u;
309 }
310 seconds -= 4611686018427387914ULL;
311 seconds = seconds > 0 ? seconds : 0;
312 } else {
313 outs("Error: No TAI64N timestamp available.");
314 _exit(1);
315 }
316
317 if (enoughtime) { /* default history = 305 sec => evaluate logs every ~5 mins */
318 if (seconds <= calltime && seconds >= (calltime - history)) {
319 if (flag >= '1' && flag <= '9') mrtg_sendlog(line.s + TAI64NLEN + 2,flag);
320 else if (flag >= 'a' && flag <= 'z') mrtg_smtplog(line.s + TAI64NLEN + 2,flag);
321 else if (flag >= 'A' && flag <= 'Z') mrtg_pop3log(line.s + TAI64NLEN + 2,flag);
322 }
323 } else {
324 if (seconds) {
325 enoughtime++;
326 } else {
327 outs("Warning: Not enough time left between calls");
328 _exit(1);
329 }
330 }
331 }
332
333 mrtg_results(flag);
334
335 _exit(0);
336}
void outs(char *s)
Definition: auto-gid.c:12
int main()
Definition: chkshsgr.c:6
char num[FMT_ULONG]
Definition: chkspawn.c:8
stralloc out
Definition: dnscname.c:12
void _exit(int)
void c(char *, char *, char *, int, int, int)
Definition: install.c:70
stralloc line
Definition: maildir2mbox.c:27
int match
Definition: matchup.c:196
datetime_sec now()
Definition: now.c:5
char * local
Definition: qmail-getpw.c:18
int adkim
Definition: qmail-mrtg.c:56
int rhelo
Definition: qmail-mrtg.c:46
int tlstrans
Definition: qmail-mrtg.c:32
int rauth
Definition: qmail-mrtg.c:59
int triples
Definition: qmail-mrtg.c:35
int rsessions
Definition: qmail-mrtg.c:42
int bytes
Definition: qmail-mrtg.c:31
int qmtp
Definition: qmail-mrtg.c:36
int bounces
Definition: qmail-mrtg.c:34
int rrcptfail
Definition: qmail-mrtg.c:50
int rloader
Definition: qmail-mrtg.c:53
int arcpt
Definition: qmail-mrtg.c:44
int pok
Definition: qmail-mrtg.c:69
int failure
Definition: qmail-mrtg.c:30
int rbl
Definition: qmail-mrtg.c:78
int rpop
Definition: qmail-mrtg.c:68
#define TAI64NLEN
Definition: qmail-mrtg.c:17
int rspam
Definition: qmail-mrtg.c:55
int
Definition: qmail-mrtg.c:27
int success
Definition: qmail-mrtg.c:29
int sdeny
Definition: qmail-mrtg.c:75
int rdkim
Definition: qmail-mrtg.c:57
int asessions
Definition: qmail-mrtg.c:41
char bufspace[BUFSIZE_LINE]
Definition: qmail-mrtg.c:99
int rvirus
Definition: qmail-mrtg.c:54
int grey
Definition: qmail-mrtg.c:77
int remote
Definition: qmail-mrtg.c:28
int spfpass
Definition: qmail-mrtg.c:62
int qmtps
Definition: qmail-mrtg.c:37
int rsize
Definition: qmail-mrtg.c:51
int rorigbad
Definition: qmail-mrtg.c:47
char bufsmall[BUFFER_SMALL]
Definition: qmail-mrtg.c:80
int rtls
Definition: qmail-mrtg.c:61
int greet
Definition: qmail-mrtg.c:76
buffer bi
Definition: qmail-mrtg.c:100
int rrcptbad
Definition: qmail-mrtg.c:49
int apop
Definition: qmail-mrtg.c:67
int pdeny
Definition: qmail-mrtg.c:70
int aauth
Definition: qmail-mrtg.c:58
int rorigdns
Definition: qmail-mrtg.c:48
int sok
Definition: qmail-mrtg.c:74
int atls
Definition: qmail-mrtg.c:60
buffer bo
Definition: qmail-mrtg.c:81
#define WHO
Definition: qmail-mrtg.c:16
int spfail
Definition: qmail-mrtg.c:63
int deferral
Definition: qmail-mrtg.c:33
int aorig
Definition: qmail-mrtg.c:43
int rsend
Definition: qmail-mrtg.c:45
int rmime
Definition: qmail-mrtg.c:52
buffer in
Definition: qmail-pw2u.c:240
int j
Definition: qmail-send.c:926
#define BUFSIZE_LINE
Definition: qmail.h:8
uint32_t k[64]
Definition: sha256.c:27