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