1 | #include "config_xor.h"
|
---|
2 |
|
---|
3 | #ifdef USE_LOGFILE_MONITOR
|
---|
4 |
|
---|
5 | #include <string.h>
|
---|
6 | #include <ctype.h>
|
---|
7 |
|
---|
8 | #undef FIL__
|
---|
9 | #define FIL__ _("sh_log_repeat.c")
|
---|
10 |
|
---|
11 | #include "samhain.h"
|
---|
12 | #include "sh_pthread.h"
|
---|
13 | #include "sh_utils.h"
|
---|
14 | #include "sh_string.h"
|
---|
15 | #include "sh_log_check.h"
|
---|
16 | #include "sh_log_evalrule.h"
|
---|
17 |
|
---|
18 | #define SH_NHIST 12
|
---|
19 | #define SH_NFINT 5
|
---|
20 | #define SH_NFIELDS 5*sizeof(SINT32) /* 16 */
|
---|
21 | #define SH_NBLOCK 63
|
---|
22 |
|
---|
23 | typedef enum
|
---|
24 | {
|
---|
25 | SH_GFLAG_EMAIL = 1 << 0,
|
---|
26 | SH_GFLAG_PATH = 1 << 1,
|
---|
27 | SH_GFLAG_IP = 1 << 2,
|
---|
28 | SH_GFLAG_FQDN = 1 << 3,
|
---|
29 | SH_GFLAG_NUM = 1 << 4,
|
---|
30 | SH_GFLAG_ELSE = 1 << 5,
|
---|
31 |
|
---|
32 | SH_GFLAG_XNUM = 1 << 6,
|
---|
33 | SH_GFLAG_CHAR = 1 << 7,
|
---|
34 | SH_GFLAG_USC = 1 << 8
|
---|
35 | } SH_GFlags;
|
---|
36 |
|
---|
37 |
|
---|
38 | /* 64 bytes
|
---|
39 | */
|
---|
40 | struct gestalt {
|
---|
41 | unsigned char hist[SH_NHIST]; /* time histogram 12 minutes */
|
---|
42 | union {
|
---|
43 | unsigned char flags[SH_NFIELDS]; /* flags indicating field type */
|
---|
44 | SINT32 flint[SH_NFINT];
|
---|
45 | } f;
|
---|
46 | UINT16 sum[SH_NFIELDS]; /* checksum of field */
|
---|
47 | UINT16 ltime; /* last time, in minutes */
|
---|
48 | UINT16 total; /* seen how often? */
|
---|
49 | };
|
---|
50 |
|
---|
51 | static unsigned int nrec = 0; /* size of array */
|
---|
52 | static unsigned int urec = 0; /* in use thereof */
|
---|
53 | static struct gestalt * arec = NULL; /* array */
|
---|
54 |
|
---|
55 | static int repeat_count = 24; /* triggers report */
|
---|
56 | static int clean_counter = 0; /* cleanup after N inserts */
|
---|
57 | static int free_slots = 0; /* free slots available */
|
---|
58 |
|
---|
59 | #define SH_CLEANUP 256
|
---|
60 |
|
---|
61 | static struct gestalt * add_entry (unsigned char * flags, UINT16 * sum,
|
---|
62 | time_t ltime)
|
---|
63 | {
|
---|
64 | struct gestalt * array = NULL;
|
---|
65 |
|
---|
66 | start:
|
---|
67 | if (urec < nrec)
|
---|
68 | {
|
---|
69 | if (free_slots)
|
---|
70 | {
|
---|
71 | unsigned int i;
|
---|
72 | for (i = 0; i < urec; ++i)
|
---|
73 | {
|
---|
74 | if (arec[i].total == 0)
|
---|
75 | {
|
---|
76 | array = &arec[i];
|
---|
77 | --free_slots;
|
---|
78 | break;
|
---|
79 | }
|
---|
80 | }
|
---|
81 | }
|
---|
82 |
|
---|
83 | if (!array)
|
---|
84 | {
|
---|
85 | array = &arec[urec];
|
---|
86 | ++urec;
|
---|
87 | }
|
---|
88 |
|
---|
89 | memcpy(array->sum, sum, sizeof(UINT16) * SH_NFIELDS);
|
---|
90 | memcpy(array->f.flags, flags, sizeof(unsigned char) * SH_NFIELDS);
|
---|
91 | memset(array->hist, 0, sizeof(unsigned char) * SH_NHIST);
|
---|
92 |
|
---|
93 | array->ltime = (UINT16)(ltime % 60);
|
---|
94 | array->hist[SH_NHIST-1] = 1;
|
---|
95 | array->total = 1;
|
---|
96 |
|
---|
97 | ++clean_counter;
|
---|
98 | return array;
|
---|
99 | }
|
---|
100 |
|
---|
101 | array = SH_ALLOC(sizeof(struct gestalt) * (nrec + SH_NBLOCK + 1));
|
---|
102 | memset(array, 0, sizeof(struct gestalt) * (nrec + SH_NBLOCK + 1));
|
---|
103 | memcpy(array, arec, sizeof(struct gestalt) * (nrec));
|
---|
104 |
|
---|
105 | nrec += (SH_NBLOCK + 1);
|
---|
106 | goto start;
|
---|
107 | }
|
---|
108 |
|
---|
109 | static UINT16 shift_history(unsigned char * hist, unsigned int shift,
|
---|
110 | UINT16 total)
|
---|
111 | {
|
---|
112 | unsigned int i, j = 0;
|
---|
113 |
|
---|
114 | if (shift >= SH_NHIST)
|
---|
115 | {
|
---|
116 | memset(hist, 0, sizeof(unsigned char) * SH_NHIST);
|
---|
117 | return 0;
|
---|
118 | }
|
---|
119 |
|
---|
120 | for (i = shift; i < SH_NHIST; ++i)
|
---|
121 | {
|
---|
122 | if (j < shift)
|
---|
123 | total -= hist[j];
|
---|
124 | hist[j] = hist[i];
|
---|
125 | ++j;
|
---|
126 | }
|
---|
127 | for (i = (SH_NHIST-shift); i < SH_NHIST; ++i)
|
---|
128 | {
|
---|
129 | hist[i] = 0;
|
---|
130 | }
|
---|
131 | return total;
|
---|
132 | }
|
---|
133 |
|
---|
134 | static void update_entry (struct gestalt * array, time_t ltime)
|
---|
135 | {
|
---|
136 | UINT16 ntime = (UINT16)(ltime % 60);
|
---|
137 |
|
---|
138 | if (array->ltime == ntime)
|
---|
139 | {
|
---|
140 | if (array->hist[SH_NHIST-1] < 255)
|
---|
141 | {
|
---|
142 | ++(array->hist[SH_NHIST-1]);
|
---|
143 | ++(array->total);
|
---|
144 | }
|
---|
145 | }
|
---|
146 | else if (array->ltime < ntime)
|
---|
147 | {
|
---|
148 | unsigned int shift = ntime - array->ltime;
|
---|
149 | array->total = shift_history(array->hist, shift, array->total);
|
---|
150 | array->hist[SH_NHIST-1] = 1;
|
---|
151 | array->ltime = ntime;
|
---|
152 | ++(array->total);
|
---|
153 | }
|
---|
154 | }
|
---|
155 |
|
---|
156 | static struct gestalt * update_or_add (unsigned char * flags, UINT16 * sum,
|
---|
157 | time_t ltime)
|
---|
158 | {
|
---|
159 | SINT32 flint[SH_NFINT];
|
---|
160 | start:
|
---|
161 |
|
---|
162 | if (arec)
|
---|
163 | {
|
---|
164 | unsigned int i;
|
---|
165 | struct gestalt * array = arec;
|
---|
166 |
|
---|
167 | memcpy(flint, flags, SH_NFIELDS);
|
---|
168 |
|
---|
169 | for (i = 0; i < urec; ++i)
|
---|
170 | {
|
---|
171 | /* Check whether field types match. Integer
|
---|
172 | * comparison is much faster than memcmp() [tested].
|
---|
173 | */
|
---|
174 | if (flint[0] == array->f.flint[0] &&
|
---|
175 | flint[1] == array->f.flint[1] &&
|
---|
176 | flint[2] == array->f.flint[2] &&
|
---|
177 | flint[3] == array->f.flint[3] &&
|
---|
178 | flint[4] == array->f.flint[4])
|
---|
179 | {
|
---|
180 | unsigned int j;
|
---|
181 | int c1 = 0, c2 = 0;
|
---|
182 | UINT16 * asum = array->sum;
|
---|
183 |
|
---|
184 | for (j = 0; j < SH_NFIELDS; ++j)
|
---|
185 | {
|
---|
186 | if (flags[j] == SH_GFLAG_ELSE)
|
---|
187 | {
|
---|
188 | ++c1;
|
---|
189 | if (asum[j] == sum[j])
|
---|
190 | ++c2;
|
---|
191 | }
|
---|
192 | }
|
---|
193 |
|
---|
194 | if (c1 == c2)
|
---|
195 | {
|
---|
196 | /* Found a matching entry, update time histogram
|
---|
197 | */
|
---|
198 | update_entry (array, ltime);
|
---|
199 | return array;
|
---|
200 | }
|
---|
201 | }
|
---|
202 | ++array;
|
---|
203 | }
|
---|
204 |
|
---|
205 | /* No match found, create a new entry
|
---|
206 | */
|
---|
207 | array = add_entry (flags, sum, ltime);
|
---|
208 | return array;
|
---|
209 | }
|
---|
210 |
|
---|
211 | arec = SH_ALLOC(sizeof(struct gestalt) * SH_NBLOCK);
|
---|
212 | nrec = SH_NBLOCK;
|
---|
213 | urec = 0;
|
---|
214 |
|
---|
215 | goto start;
|
---|
216 | }
|
---|
217 |
|
---|
218 | /* --------------------------------------------------------------------
|
---|
219 | *
|
---|
220 | * crc16 checksum from the linux kernel.
|
---|
221 | * This source code is licensed under the GNU General Public License,
|
---|
222 | * Version 2.
|
---|
223 | */
|
---|
224 |
|
---|
225 | /** CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */
|
---|
226 | UINT16 const crc16_table[256] = {
|
---|
227 | 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
---|
228 | 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
---|
229 | 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
---|
230 | 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
---|
231 | 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
---|
232 | 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
---|
233 | 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
---|
234 | 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
---|
235 | 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
---|
236 | 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
---|
237 | 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
---|
238 | 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
---|
239 | 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
---|
240 | 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
---|
241 | 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
---|
242 | 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
---|
243 | 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
---|
244 | 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
---|
245 | 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
---|
246 | 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
---|
247 | 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
---|
248 | 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
---|
249 | 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
---|
250 | 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
---|
251 | 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
---|
252 | 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
---|
253 | 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
---|
254 | 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
---|
255 | 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
---|
256 | 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
---|
257 | 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
---|
258 | 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
---|
259 | };
|
---|
260 |
|
---|
261 | static inline UINT16 crc16_byte(UINT16 crc, const unsigned char data)
|
---|
262 | {
|
---|
263 | return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
|
---|
264 | }
|
---|
265 |
|
---|
266 | /**
|
---|
267 | * crc16 - compute the CRC-16 for the data buffer
|
---|
268 | * @crc: previous CRC value
|
---|
269 | * @buffer: data pointer
|
---|
270 | * @len: number of bytes in the buffer
|
---|
271 | *
|
---|
272 | * Returns the updated CRC value.
|
---|
273 | */
|
---|
274 | static inline UINT16 crc16(UINT16 crc, const unsigned char * buffer,
|
---|
275 | size_t len)
|
---|
276 | {
|
---|
277 | while (len--)
|
---|
278 | crc = crc16_byte(crc, *buffer++);
|
---|
279 | return crc;
|
---|
280 | }
|
---|
281 |
|
---|
282 |
|
---|
283 | /* end crc16 code
|
---|
284 | *
|
---|
285 | * -------------------------------------------------------------------- */
|
---|
286 |
|
---|
287 | static void classify(char ** splits, size_t * lengths, unsigned int nfields,
|
---|
288 | unsigned char * flags, UINT16 * sums)
|
---|
289 | {
|
---|
290 | unsigned int i;
|
---|
291 | unsigned int flag;
|
---|
292 |
|
---|
293 | /* flags we don't want to see in XYZ
|
---|
294 | */
|
---|
295 | static int m_ip = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE|SH_GFLAG_CHAR|SH_GFLAG_XNUM;
|
---|
296 | static int m_num = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE|SH_GFLAG_CHAR;
|
---|
297 | static int m_fqdn = SH_GFLAG_PATH|SH_GFLAG_EMAIL|SH_GFLAG_USC|SH_GFLAG_ELSE;
|
---|
298 | static int m_email = SH_GFLAG_PATH;
|
---|
299 |
|
---|
300 | nfields = (nfields > SH_NFIELDS) ? SH_NFIELDS : nfields;
|
---|
301 |
|
---|
302 | for (i = 0; i < nfields; ++i)
|
---|
303 | {
|
---|
304 | char *p = splits[i];
|
---|
305 | unsigned int np = 0;
|
---|
306 | unsigned int fqdn = 0;
|
---|
307 |
|
---|
308 | flag = 0;
|
---|
309 |
|
---|
310 | while (*p)
|
---|
311 | {
|
---|
312 | if (isxdigit((unsigned int)*p))
|
---|
313 | {
|
---|
314 | if (isdigit((unsigned int)*p))
|
---|
315 | {
|
---|
316 | flag |= SH_GFLAG_NUM;
|
---|
317 | }
|
---|
318 | else
|
---|
319 | {
|
---|
320 | flag |= SH_GFLAG_XNUM;
|
---|
321 | }
|
---|
322 | }
|
---|
323 | else if (*p == '.')
|
---|
324 | {
|
---|
325 | flag |= SH_GFLAG_IP;
|
---|
326 | ++np;
|
---|
327 | }
|
---|
328 | else if (*p == '/')
|
---|
329 | {
|
---|
330 | flag |= SH_GFLAG_PATH;
|
---|
331 | }
|
---|
332 | else if (*p == '@')
|
---|
333 | {
|
---|
334 | flag |= SH_GFLAG_EMAIL;
|
---|
335 | }
|
---|
336 | else if (*p == '-')
|
---|
337 | {
|
---|
338 | flag |= SH_GFLAG_FQDN;
|
---|
339 | }
|
---|
340 | else if (*p == '_')
|
---|
341 | {
|
---|
342 | flag |= SH_GFLAG_USC;
|
---|
343 | }
|
---|
344 | else if (isalpha((unsigned int)*p))
|
---|
345 | {
|
---|
346 | if (flag & SH_GFLAG_IP)
|
---|
347 | ++fqdn;
|
---|
348 | flag |= SH_GFLAG_CHAR;
|
---|
349 | }
|
---|
350 | else if (!isascii((unsigned int)*p))
|
---|
351 | {
|
---|
352 | flags[i] = SH_GFLAG_ELSE;
|
---|
353 | break;
|
---|
354 | }
|
---|
355 | else
|
---|
356 | {
|
---|
357 | flag |= SH_GFLAG_ELSE;
|
---|
358 | }
|
---|
359 | ++p;
|
---|
360 | }
|
---|
361 |
|
---|
362 | if (flags[i] == 0)
|
---|
363 | {
|
---|
364 | if (0 == (flag & m_ip) &&
|
---|
365 | 0 != (flag & SH_GFLAG_IP) &&
|
---|
366 | 0 != (flag & SH_GFLAG_NUM) &&
|
---|
367 | np > 2)
|
---|
368 | {
|
---|
369 | flags[i] = SH_GFLAG_IP;
|
---|
370 | }
|
---|
371 | else if (0 == (flag & m_num) &&
|
---|
372 | (0 != (flag & SH_GFLAG_NUM) || 0 != (flag & SH_GFLAG_XNUM)))
|
---|
373 | {
|
---|
374 | flags[i] = SH_GFLAG_NUM;
|
---|
375 | }
|
---|
376 | else if (0 == (flag & m_fqdn) &&
|
---|
377 | 0 != (flag & SH_GFLAG_IP) &&
|
---|
378 | 0 != (flag & SH_GFLAG_CHAR) &&
|
---|
379 | fqdn)
|
---|
380 | {
|
---|
381 | flags[i] = SH_GFLAG_FQDN;
|
---|
382 | }
|
---|
383 | else if ('/' == splits[i][0])
|
---|
384 | {
|
---|
385 | flags[i] = SH_GFLAG_PATH;
|
---|
386 | }
|
---|
387 | else if (0 == (flag & m_email) &&
|
---|
388 | 0 != (flag & SH_GFLAG_EMAIL) &&
|
---|
389 | 0 != (flag & SH_GFLAG_CHAR))
|
---|
390 | {
|
---|
391 | flags[i] = SH_GFLAG_EMAIL;
|
---|
392 | }
|
---|
393 | else
|
---|
394 | {
|
---|
395 | flags[i] = SH_GFLAG_ELSE;
|
---|
396 | }
|
---|
397 | }
|
---|
398 |
|
---|
399 | /* CRC-16 checksum
|
---|
400 | */
|
---|
401 | sums[i] = crc16(0, (unsigned char *) splits[i], lengths[i]);
|
---|
402 | }
|
---|
403 |
|
---|
404 | return;
|
---|
405 | }
|
---|
406 |
|
---|
407 | static void cleanup_array (time_t ltime)
|
---|
408 | {
|
---|
409 | UINT16 ntime = (UINT16)(ltime % 60);
|
---|
410 |
|
---|
411 | if (ntime > 12) ntime -= 12;
|
---|
412 |
|
---|
413 | if (arec && urec > 0)
|
---|
414 | {
|
---|
415 | struct gestalt * array;
|
---|
416 | unsigned int i, last, urec_orig = urec;
|
---|
417 |
|
---|
418 | last = urec-1;
|
---|
419 | array = &arec[0];
|
---|
420 |
|
---|
421 | for (i = 0; i < urec_orig; ++i)
|
---|
422 | {
|
---|
423 | if (array->ltime < ntime)
|
---|
424 | {
|
---|
425 | memset(array, 0, sizeof(struct gestalt));
|
---|
426 | if (i != last)
|
---|
427 | ++free_slots;
|
---|
428 | else
|
---|
429 | --urec;
|
---|
430 | }
|
---|
431 | }
|
---|
432 | ++array;
|
---|
433 | }
|
---|
434 | clean_counter = 0;
|
---|
435 | return;
|
---|
436 | }
|
---|
437 |
|
---|
438 | /* ----------------------------------------------------------------------
|
---|
439 | *
|
---|
440 | * Public functions
|
---|
441 | */
|
---|
442 |
|
---|
443 | int sh_repeat_set_trigger (const char * str)
|
---|
444 | {
|
---|
445 | unsigned long value;
|
---|
446 | char * foo;
|
---|
447 |
|
---|
448 | value = (size_t) strtoul(str, &foo, 0);
|
---|
449 |
|
---|
450 | if (*foo == '\0' && value < 65535) {
|
---|
451 | repeat_count = value;
|
---|
452 | return 0;
|
---|
453 | }
|
---|
454 | return -1;
|
---|
455 | }
|
---|
456 |
|
---|
457 | static char * sh_repeat_queue = NULL;
|
---|
458 |
|
---|
459 | int sh_repeat_set_queue (const char * str)
|
---|
460 | {
|
---|
461 | if (!str)
|
---|
462 | return -1;
|
---|
463 | if (sh_repeat_queue)
|
---|
464 | SH_FREE(sh_repeat_queue);
|
---|
465 | sh_repeat_queue = sh_util_strdup(str);
|
---|
466 | return 0;
|
---|
467 | }
|
---|
468 |
|
---|
469 | static int sh_repeat_cron = S_FALSE;
|
---|
470 |
|
---|
471 | int sh_repeat_set_cron (const char * str)
|
---|
472 | {
|
---|
473 | return sh_util_flagval(str, &sh_repeat_cron);
|
---|
474 | }
|
---|
475 |
|
---|
476 | int sh_repeat_message_check (const sh_string * host,
|
---|
477 | const sh_string * msg,
|
---|
478 | time_t ltime)
|
---|
479 | {
|
---|
480 | struct gestalt * array;
|
---|
481 |
|
---|
482 | UINT16 sums[SH_NFIELDS] = { 0 };
|
---|
483 | unsigned char flags[SH_NFIELDS] = { 0 };
|
---|
484 |
|
---|
485 | /* split message into SH_NFIELDS+1, discard last */
|
---|
486 |
|
---|
487 | unsigned int nfields = SH_NFIELDS+1;
|
---|
488 | size_t lengths[SH_NFIELDS+1];
|
---|
489 | char * new;
|
---|
490 | char ** splits;
|
---|
491 |
|
---|
492 | if (repeat_count == 0)
|
---|
493 | return 0;
|
---|
494 |
|
---|
495 | if (sh_repeat_cron == S_FALSE)
|
---|
496 | {
|
---|
497 | char * s = sh_string_str(msg);
|
---|
498 |
|
---|
499 | if (0 == strcmp(s, _("cron")) || 0 == strcmp(s, _("CRON")))
|
---|
500 | return 0;
|
---|
501 | }
|
---|
502 |
|
---|
503 | new = sh_util_strdup_l(sh_string_str(msg), sh_string_len(msg));
|
---|
504 |
|
---|
505 | splits = split_array_token (new, &nfields, lengths,
|
---|
506 | " :,()='[]<>\t\n");
|
---|
507 |
|
---|
508 | /* classify fields */
|
---|
509 |
|
---|
510 | classify (splits, lengths, nfields, flags, sums);
|
---|
511 |
|
---|
512 | /* compare */
|
---|
513 |
|
---|
514 | array = update_or_add (flags, sums, ltime);
|
---|
515 |
|
---|
516 | /* report */
|
---|
517 |
|
---|
518 | if (array->total > repeat_count)
|
---|
519 | {
|
---|
520 | volatile int repeat = array->total;
|
---|
521 | char * tmpmsg;
|
---|
522 | char * tmphost;
|
---|
523 | sh_string * alias;
|
---|
524 |
|
---|
525 | /* issue report */
|
---|
526 |
|
---|
527 | SH_MUTEX_LOCK(mutex_thread_nolog);
|
---|
528 | tmphost = sh_util_safe_name (sh_string_str(host));
|
---|
529 | tmpmsg = sh_util_safe_name_keepspace (sh_string_str(msg));
|
---|
530 | sh_error_handle (sh_log_lookup_severity(sh_repeat_queue),
|
---|
531 | FIL__, __LINE__, 0, MSG_LOGMON_BURST,
|
---|
532 | repeat, tmpmsg, tmphost);
|
---|
533 | alias = sh_log_lookup_alias(sh_repeat_queue);
|
---|
534 | if (alias)
|
---|
535 | {
|
---|
536 | sh_error_mail (sh_string_str(alias),
|
---|
537 | sh_log_lookup_severity(sh_repeat_queue),
|
---|
538 | FIL__, __LINE__, 0, MSG_LOGMON_BURST,
|
---|
539 | repeat, tmpmsg, tmphost);
|
---|
540 | }
|
---|
541 | SH_FREE(tmpmsg);
|
---|
542 | SH_FREE(tmphost);
|
---|
543 | SH_MUTEX_UNLOCK(mutex_thread_nolog);
|
---|
544 |
|
---|
545 | /* mark slot as free */
|
---|
546 |
|
---|
547 | memset(array, 0, sizeof(struct gestalt));
|
---|
548 | if (array != &arec[urec-1])
|
---|
549 | ++free_slots;
|
---|
550 | else
|
---|
551 | urec -= 1;
|
---|
552 | }
|
---|
553 |
|
---|
554 | SH_FREE(new);
|
---|
555 |
|
---|
556 | /* run cleanup routine */
|
---|
557 |
|
---|
558 | if (clean_counter >= SH_CLEANUP)
|
---|
559 | {
|
---|
560 | cleanup_array(ltime);
|
---|
561 | }
|
---|
562 |
|
---|
563 | return 0;
|
---|
564 | }
|
---|
565 |
|
---|
566 | #endif
|
---|