Mercurial > syslog2iptables
annotate src/syslogconfig.cpp @ 50:75361069c6ef
changes for fedora 10
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Wed, 24 Dec 2008 18:40:54 -0800 |
parents | ba0259c9e411 |
children | 206448c00b55 |
rev | line source |
---|---|
36 | 1 /* |
2 | |
3 Copyright (c) 2007 Carl Byington - 510 Software Group, released under | |
4 the GPL version 3 or any later version at your choice available at | |
5 http://www.gnu.org/licenses/gpl-3.0.txt | |
6 | |
7 */ | |
1 | 8 |
9 #include "includes.h" | |
2 | 10 #include <fcntl.h> |
3 | 11 #include <sys/socket.h> |
12 #include <netinet/in.h> | |
13 #include <arpa/inet.h> | |
14 #include <netdb.h> | |
4 | 15 #include <limits.h> |
1 | 16 |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
17 const char *token_add; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
18 const char *token_bucket; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
19 const char *token_file; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
20 const char *token_ignore; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
21 const char *token_include; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
22 const char *token_index; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
23 const char *token_lbrace; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
24 const char *token_message; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
25 const char *token_pattern; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
26 const char *token_rbrace; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
27 const char *token_remove; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
28 const char *token_semi; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
29 const char *token_slash; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
30 const char *token_threshold; |
3 | 31 |
32 struct ltint | |
33 { | |
34 bool operator()(const int s1, const int s2) const | |
35 { | |
36 | 36 return (unsigned)s1 < (unsigned)s2; |
3 | 37 } |
38 }; | |
1 | 39 |
4 | 40 struct bucket { |
36 | 41 int count; |
42 bool latch; // true iff ever count>threshold | |
4 | 43 }; |
44 | |
36 | 45 string_set all_strings; // owns all the strings, only modified by the config loader thread |
46 const int maxlen = 1000; // used for snprintf buffers | |
4 | 47 typedef map<int, bucket, ltint> ip_buckets; |
3 | 48 |
49 class IPR { | |
36 | 50 ip_buckets violations; |
3 | 51 public: |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
52 void add(int ip, int amount, CONFIG &con, const char *file_name, int pattern_index, const char *message); |
36 | 53 void leak(int amount, CONFIG &con); |
54 void free_all(CONFIG &con); | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
55 void update(int ip, bool added, const char *file_name, int pattern_index, const char *message); |
36 | 56 void changed(CONFIG &con, int ip, bool added); |
3 | 57 }; |
58 | |
59 IPR recorder; | |
60 | |
61 | |
62 //////////////////////////////////////////////// | |
63 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
64 void IPR::add(int ip, int amount, CONFIG &con, const char *file_name, int pattern_index, const char *message) { |
36 | 65 if (con.looking(ip)) { |
66 ip_buckets::iterator i = violations.find(ip); | |
67 if (i == violations.end()) { | |
68 bucket b; | |
69 b.count = amount; | |
70 b.latch = (con.get_threshold() <= b.count); | |
71 violations[ip] = b; | |
72 if (b.latch) { | |
73 update(ip, true, file_name, pattern_index, message); | |
74 changed(con, ip, true); | |
75 } | |
76 } | |
77 else { | |
78 bucket &b = (*i).second; | |
79 if (b.count < (INT_MAX-amount)) { | |
80 int t = con.get_threshold(); | |
81 int c = b.count; | |
82 b.count += amount; | |
83 if ((!b.latch) && (c < t) && (t <= b.count)) { | |
84 b.latch = true; | |
85 update(ip, true, file_name, pattern_index, message); | |
86 changed(con, ip, true); | |
87 } | |
88 } | |
89 } | |
90 } | |
3 | 91 } |
92 | |
93 | |
94 void IPR::leak(int amount, CONFIG &con) { | |
36 | 95 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); ) { |
96 int ip = (*i).first; | |
97 bucket &b = (*i).second; | |
98 if (b.count <= amount) { | |
99 if (b.latch) { | |
100 update(ip, false, NULL, 0, NULL); | |
101 changed(con, ip, false); | |
102 } | |
103 violations.erase(i++); | |
104 } | |
105 else { | |
106 b.count -= amount; | |
107 i++; | |
108 } | |
109 } | |
110 } | |
111 | |
112 | |
113 void IPR::free_all(CONFIG &con) { | |
37 | 114 if (debug_syslog > 2) { |
115 my_syslog("syslog2iptables shutting down"); | |
116 } | |
36 | 117 for (ip_buckets::iterator i=violations.begin(); i!=violations.end(); i++) { |
118 int ip = (*i).first; | |
119 bucket &b = (*i).second; | |
120 if (b.latch) { | |
121 update(ip, false, NULL, 0, NULL); | |
122 changed(con, ip, false); | |
123 } | |
124 } | |
125 violations.clear(); | |
20 | 126 } |
127 | |
128 | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
129 void IPR::update(int ip, bool added, const char *file_name, int pattern_index, const char *message) { |
36 | 130 if (debug_syslog > 2) { |
131 char buf[maxlen]; | |
132 in_addr ad; | |
133 ad.s_addr = htonl(ip); | |
134 if (added) { | |
135 if (message) snprintf(buf, maxlen, "dropping traffic from/to %s based on %s in %s", inet_ntoa(ad), message, file_name); | |
136 else snprintf(buf, maxlen, "dropping traffic from/to %s based on pattern match %d in %s", inet_ntoa(ad), pattern_index, file_name); | |
137 } | |
138 else snprintf(buf, maxlen, "allowing traffic from/to %s", inet_ntoa(ad)); | |
139 my_syslog(buf); | |
140 } | |
3 | 141 } |
142 | |
143 | |
20 | 144 void IPR::changed(CONFIG &con, int ip, bool added) { |
36 | 145 int t = con.get_threshold(); |
146 char buf[maxlen]; | |
147 if (added) { | |
148 bucket &b = violations[ip]; | |
149 if (con.looking(ip) && (b.count > t)) { | |
150 in_addr ad; | |
151 ad.s_addr = htonl(ip); | |
152 snprintf(buf, maxlen, con.add_command, inet_ntoa(ad)); | |
153 system(buf); | |
154 } | |
155 } | |
156 else { | |
157 in_addr ad; | |
158 ad.s_addr = htonl(ip); | |
159 snprintf(buf, maxlen, con.remove_command, inet_ntoa(ad)); | |
160 system(buf); | |
161 } | |
3 | 162 } |
1 | 163 |
164 | |
3 | 165 //////////////////////////////////////////////// |
166 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
167 int ip_address(const char *have); |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
168 int ip_address(const char *have) { |
36 | 169 int ipaddr = 0; |
170 in_addr ip; | |
171 if (inet_aton(have, &ip)) ipaddr = ip.s_addr; | |
172 else { | |
173 struct hostent *host = gethostbyname(have); | |
174 if (host && host->h_addrtype == AF_INET) memcpy(&ipaddr, host->h_addr, sizeof(ipaddr)); | |
175 } | |
176 return ntohl(ipaddr); | |
3 | 177 } |
178 | |
179 | |
180 //////////////////////////////////////////////// | |
181 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
182 PATTERN::PATTERN(TOKEN &tok, const char *pattern_, int index_, int amount_, const char *msg_) { |
36 | 183 pattern = pattern_; |
184 index = index_; | |
185 amount = amount_; | |
186 message = msg_; | |
187 if (pattern) { | |
188 int rc = regcomp(&re, pattern, REG_ICASE | REG_EXTENDED); | |
189 if (rc) { | |
190 char bu[maxlen]; | |
191 regerror(rc, &re, bu, maxlen); | |
192 char buf[maxlen]; | |
193 snprintf(buf, sizeof(buf), "pattern %s not valid - %s", pattern, bu); | |
194 tok.token_error(buf); | |
195 pattern = NULL; | |
196 } | |
197 } | |
3 | 198 } |
199 | |
200 | |
201 PATTERN::~PATTERN() { | |
36 | 202 regfree(&re); |
3 | 203 } |
204 | |
205 | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
206 bool PATTERN::process(char *buf, CONFIG &con, const char *file_name, int pattern_index) { |
36 | 207 if (pattern) { |
208 const int nmatch = index+1; | |
209 regmatch_t match[nmatch]; | |
210 if (0 == regexec(&re, buf, nmatch, match, 0)) { | |
211 int s = match[index].rm_so; | |
212 int e = match[index].rm_eo; | |
213 if (s != -1) { | |
214 if (debug_syslog > 3) { | |
215 my_syslog(buf); // show lines with matches | |
216 } | |
217 buf[e] = '\0'; | |
218 int ip = ip_address(buf+s); | |
219 if (ip) { | |
220 recorder.add(ip, amount, con, file_name, pattern_index, message); | |
221 } | |
222 return true; | |
223 } | |
224 } | |
225 } | |
226 return false; | |
3 | 227 } |
228 | |
229 | |
230 void PATTERN::dump(int level) { | |
36 | 231 char indent[maxlen]; |
232 int i = min(maxlen-1, level*4); | |
233 memset(indent, ' ', i); | |
234 indent[i] = '\0'; | |
235 printf("%s pattern \"%s\" {; \n", indent, pattern); | |
236 printf("%s index %d; \n", indent, index); | |
237 printf("%s bucket %d; \n", indent, amount); | |
238 if (message) printf("%s message \"%s\"; \n", indent, message); | |
239 printf("%s }; \n", indent); | |
3 | 240 } |
241 | |
242 | |
243 //////////////////////////////////////////////// | |
244 // | |
1 | 245 CONFIG::CONFIG() { |
36 | 246 reference_count = 0; |
247 generation = 0; | |
248 load_time = 0; | |
249 threshold = 500; | |
250 add_command = "/sbin/iptables -I INPUT --src %s --jump DROP"; | |
251 remove_command = "/sbin/iptables -D INPUT --src %s --jump DROP"; | |
1 | 252 } |
253 | |
254 | |
255 CONFIG::~CONFIG() { | |
36 | 256 for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) { |
257 SYSLOGCONFIG *c = *i; | |
258 delete c; | |
259 } | |
260 ignore.clear(); | |
1 | 261 } |
262 | |
263 | |
264 void CONFIG::add_syslogconfig(SYSLOGCONFIGP con) { | |
36 | 265 syslogconfigs.push_back(con); |
1 | 266 } |
267 | |
268 | |
3 | 269 void CONFIG::add_pair(IPPAIR pair) { |
36 | 270 ignore.push_back(pair); |
3 | 271 } |
272 | |
273 | |
1 | 274 void CONFIG::dump() { |
36 | 275 printf(" threshold %d; \n\n", threshold); |
3 | 276 |
36 | 277 printf(" add_command \"%s\"; \n", add_command); |
278 printf(" remove_command \"%s\"; \n\n", remove_command); | |
27 | 279 |
36 | 280 printf(" ignore { \n"); |
281 for (ippair_list::iterator i=ignore.begin(); i!=ignore.end(); i++) { | |
282 IPPAIR &p = *i; | |
283 in_addr ip; | |
284 ip.s_addr = htonl(p.first); | |
285 printf(" %s/%d; \n", inet_ntoa(ip), p.cidr); | |
286 } | |
287 printf(" }; \n\n"); | |
3 | 288 |
36 | 289 for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) { |
290 SYSLOGCONFIGP c = *i; | |
291 c->dump(0); | |
292 } | |
1 | 293 } |
294 | |
295 | |
2 | 296 void CONFIG::read() { |
36 | 297 while (true) { |
298 bool have = false; | |
299 for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) { | |
300 SYSLOGCONFIGP c = *i; | |
301 have |= c->read(*this); | |
302 } | |
303 if (!have) break; | |
304 } | |
2 | 305 } |
306 | |
307 | |
4 | 308 void CONFIG::sleep(int duration, time_t &previous) { |
36 | 309 ::sleep(duration); |
310 time_t now = time(NULL); | |
311 recorder.leak(now-previous, *this); | |
312 previous = now; | |
3 | 313 } |
314 | |
315 | |
36 | 316 void CONFIG::free_all() { |
317 recorder.free_all(*this); | |
318 } | |
319 | |
3 | 320 bool CONFIG::looking(int ip) { |
36 | 321 for (ippair_list::iterator i=ignore.begin(); i!=ignore.end(); i++) { |
322 IPPAIR &p = *i; | |
323 if ((p.first <= ip) && (ip <= p.last)) return false; | |
324 } | |
325 return true; | |
3 | 326 } |
327 | |
328 //////////////////////////////////////////////// | |
329 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
330 SYSLOGCONFIG::SYSLOGCONFIG(TOKEN &tok, const char *file_name_) { |
36 | 331 tokp = &tok; |
332 file_name = file_name_; | |
333 open(true); | |
1 | 334 } |
335 | |
336 | |
337 SYSLOGCONFIG::~SYSLOGCONFIG() { | |
36 | 338 close(); |
339 for (pattern_list::iterator i=patterns.begin(); i!=patterns.end(); i++) { | |
340 PATTERN *p = *i; | |
341 delete p; | |
342 } | |
2 | 343 } |
344 | |
345 | |
4 | 346 void SYSLOGCONFIG::open(bool msg) { |
36 | 347 fd = ::open(file_name, O_RDONLY); |
348 len = 0; | |
349 if (fd == -1) { | |
350 if (msg) { | |
351 char buf[maxlen]; | |
352 snprintf(buf, sizeof(buf), "syslog file %s not readable", file_name); | |
353 tokp->token_error(buf); | |
354 } | |
355 } | |
356 else { | |
357 if (debug_syslog > 1) { | |
358 snprintf(buf, sizeof(buf), "syslog file %s opened", file_name); | |
359 my_syslog(buf); | |
360 } | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
361 if (msg) lseek(fd, 0, SEEK_END); |
36 | 362 if (fstat(fd, &openfdstat)) { |
363 close(); | |
364 snprintf(buf, sizeof(buf), "syslog file %s cannot stat after open", file_name); | |
365 tokp->token_error(buf); | |
366 } | |
367 // specify that this fd gets closed on exec, so that selinux | |
368 // won't complain about iptables trying to read log files. | |
369 int oldflags = fcntl(fd, F_GETFD, 0); | |
370 if (oldflags >= 0) { | |
371 fcntl(fd, F_SETFD, oldflags | FD_CLOEXEC); | |
372 } | |
373 } | |
3 | 374 } |
375 | |
376 | |
377 bool SYSLOGCONFIG::read(CONFIG &con) { | |
36 | 378 if (failed()) { |
379 open(false); | |
380 if (failed()) return false; | |
381 } | |
382 int n = ::read(fd, buf+len, buflen-len); | |
383 bool have = (n > 0); | |
384 if (have) { | |
385 len += n; | |
386 while (true) { | |
387 char *p = (char*)memchr(buf, '\n', len); | |
388 if (!p) break; | |
389 n = p-buf; | |
390 *p = '\0'; | |
391 process(con); // process null terminated string | |
392 len -= n+1; | |
393 memmove(buf, p+1, len); | |
394 } | |
395 // no <lf> in a full buffer | |
396 if (len == buflen) len = 0; | |
397 } | |
398 else { | |
399 // check for file close | |
400 struct stat filenamest; | |
401 if (0 == stat(file_name, &filenamest)) { | |
402 if ((filenamest.st_dev != openfdstat.st_dev) || | |
403 (filenamest.st_ino != openfdstat.st_ino)) { | |
404 close(); | |
405 } | |
406 } | |
407 else { | |
408 // filename no longer exists | |
409 close(); | |
410 } | |
411 } | |
412 return have; | |
2 | 413 } |
414 | |
415 | |
4 | 416 void SYSLOGCONFIG::close() { |
36 | 417 if (debug_syslog > 1) { |
418 snprintf(buf, sizeof(buf), "syslog file %s closed", file_name); | |
419 my_syslog(buf); | |
420 } | |
421 if (fd != -1) ::close(fd); | |
422 fd = -1; | |
4 | 423 } |
424 | |
425 | |
426 void SYSLOGCONFIG::add_pattern(PATTERNP pat) { | |
36 | 427 patterns.push_back(pat); |
4 | 428 } |
429 | |
430 | |
3 | 431 void SYSLOGCONFIG::process(CONFIG &con) { |
36 | 432 int pi=0; |
433 for (pattern_list::iterator i=patterns.begin(); i!=patterns.end(); i++) { | |
434 PATTERN *p = *i; | |
435 if (p->process(buf, con, file_name, pi)) break; | |
436 pi++; | |
437 } | |
1 | 438 } |
439 | |
440 | |
441 void SYSLOGCONFIG::dump(int level) { | |
36 | 442 char indent[maxlen]; |
443 int i = min(maxlen-1, level*4); | |
444 memset(indent, ' ', i); | |
445 indent[i] = '\0'; | |
446 printf("%s file \"%s\" {\n", indent, file_name); | |
447 for (pattern_list::iterator i=patterns.begin(); i!=patterns.end(); i++) { | |
448 PATTERN *p = *i; | |
449 p->dump(level+1); | |
450 } | |
451 printf("%s }; \n", indent); | |
1 | 452 } |
453 | |
454 | |
455 //////////////////////////////////////////////// | |
456 // helper to discard the strings held by a string_set | |
457 // | |
458 void discard(string_set &s) { | |
36 | 459 for (string_set::iterator i=s.begin(); i!=s.end(); i++) { |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
460 free((void*)*i); |
36 | 461 } |
462 s.clear(); | |
1 | 463 } |
464 | |
465 | |
466 //////////////////////////////////////////////// | |
467 // helper to register a string in a string set | |
468 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
469 const char* register_string(string_set &s, const char *name) { |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
470 string_set::const_iterator i = s.find(name); |
36 | 471 if (i != s.end()) return *i; |
472 char *x = strdup(name); | |
473 s.insert(x); | |
474 return x; | |
1 | 475 } |
476 | |
477 | |
478 //////////////////////////////////////////////// | |
479 // register a global string | |
480 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
481 const char* register_string(const char *name) { |
36 | 482 return register_string(all_strings, name); |
1 | 483 } |
484 | |
485 | |
486 //////////////////////////////////////////////// | |
38 | 487 // clear all global strings, helper for valgrind checking |
488 // | |
489 void clear_strings() { | |
490 discard(all_strings); | |
491 } | |
492 | |
493 | |
494 //////////////////////////////////////////////// | |
1 | 495 // |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
496 bool tsa(TOKEN &tok, const char *token); |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
497 bool tsa(TOKEN &tok, const char *token) { |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
498 const char *have = tok.next(); |
36 | 499 if (have == token) return true; |
500 tok.token_error(token, have); | |
501 return false; | |
1 | 502 } |
503 | |
504 | |
505 //////////////////////////////////////////////// | |
506 // | |
3 | 507 bool parse_pattern(TOKEN &tok, SYSLOGCONFIG &con); |
508 bool parse_pattern(TOKEN &tok, SYSLOGCONFIG &con) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
509 const char *pat = tok.next(); |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
510 int ind = 0; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
511 int buc = 0; |
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
512 const char *msg = NULL; |
36 | 513 if (!tsa(tok, token_lbrace)) return false; |
514 while (true) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
515 const char *have = tok.next(); |
36 | 516 if (!have) break; |
517 if (have == token_rbrace) break; | |
518 if (have == token_index) { | |
519 have = tok.next(); | |
520 ind = atoi(have); | |
521 if (!tsa(tok, token_semi)) return false; | |
522 } | |
523 else if (have == token_bucket) { | |
524 have = tok.next(); | |
525 buc = atoi(have); | |
526 if (!tsa(tok, token_semi)) return false; | |
527 } | |
528 else if (have == token_message) { | |
529 msg = tok.next(); | |
530 if (!tsa(tok, token_semi)) return false; | |
531 } | |
532 else { | |
533 tok.token_error("index/bucket", have); | |
534 return false; | |
535 } | |
536 } | |
537 if (!tsa(tok, token_semi)) return false; | |
538 PATTERNP patt = new PATTERN(tok, pat, ind, buc, msg); | |
539 con.add_pattern(patt); | |
540 return true; | |
3 | 541 } |
542 | |
543 | |
544 //////////////////////////////////////////////// | |
545 // | |
546 bool parse_ignore(TOKEN &tok, CONFIG &dc); | |
547 bool parse_ignore(TOKEN &tok, CONFIG &dc) { | |
36 | 548 if (!tsa(tok, token_lbrace)) return false; |
549 while (true) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
550 const char *have = tok.next(); |
36 | 551 if (!have) break; |
552 if (have == token_rbrace) break; | |
553 int ipaddr = ip_address(have); | |
554 if (ipaddr == 0) { | |
555 tok.token_error("ip address", have); | |
556 return false; | |
557 } | |
558 if (!tsa(tok, token_slash)) return false; | |
559 have = tok.next(); | |
560 int mask = atoi(have); | |
561 if ((mask < 8) || (mask > 32)) { | |
562 tok.token_error("cidr 8..32 value", have); | |
563 return false; | |
564 } | |
565 if (!tsa(tok, token_semi)) return false; | |
566 IPPAIR pair; | |
567 const int masks[33] = {0xffffffff, // 0 | |
568 0x7fffffff, // 1 | |
569 0x3fffffff, // 2 | |
570 0x1fffffff, // 3 | |
571 0x0fffffff, // 4 | |
572 0x07ffffff, // 5 | |
573 0x03ffffff, // 6 | |
574 0x01ffffff, // 7 | |
575 0x00ffffff, // 8 | |
576 0x007fffff, // 9 | |
577 0x003fffff, // 10 | |
578 0x001fffff, // 11 | |
579 0x000fffff, // 12 | |
580 0x0007ffff, // 13 | |
581 0x0003ffff, // 14 | |
582 0x0001ffff, // 15 | |
583 0x0000ffff, // 16 | |
584 0x00007fff, // 17 | |
585 0x00003fff, // 18 | |
586 0x00001fff, // 19 | |
587 0x00000fff, // 20 | |
588 0x000007ff, // 21 | |
589 0x000003ff, // 22 | |
590 0x000001ff, // 23 | |
591 0x000000ff, // 24 | |
592 0x0000007f, // 25 | |
593 0x0000003f, // 26 | |
594 0x0000001f, // 27 | |
595 0x0000000f, // 28 | |
596 0x00000007, // 29 | |
597 0x00000003, // 30 | |
598 0x00000001, // 31 | |
599 0x00000000}; // 32 | |
600 pair.first = ipaddr; | |
601 pair.last = ipaddr | masks[mask]; | |
602 pair.cidr = mask; | |
603 dc.add_pair(pair); | |
604 } | |
605 if (!tsa(tok, token_semi)) return false; | |
606 return true; | |
3 | 607 } |
608 | |
609 | |
610 //////////////////////////////////////////////// | |
611 // | |
612 bool parse_syslogconfig(TOKEN &tok, CONFIG &dc); | |
613 bool parse_syslogconfig(TOKEN &tok, CONFIG &dc) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
614 const char *name = tok.next(); |
36 | 615 if (!tsa(tok, token_lbrace)) return false; |
616 SYSLOGCONFIGP con = new SYSLOGCONFIG(tok, name); | |
617 if (con->failed()) { | |
618 delete con; | |
619 return false; | |
620 } | |
621 dc.add_syslogconfig(con); | |
622 while (true) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
623 const char *have = tok.next(); |
36 | 624 if (!have) break; |
625 if (have == token_rbrace) break; | |
626 if (have == token_pattern) { | |
627 if (!parse_pattern(tok, *con)) return false; | |
628 } | |
629 else { | |
630 tok.token_error("pattern", have); | |
631 return false; | |
632 } | |
633 } | |
634 if (!tsa(tok, token_semi)) return false; | |
635 return true; | |
1 | 636 } |
637 | |
638 | |
639 //////////////////////////////////////////////// | |
640 // parse a config file | |
641 // | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
642 bool load_conf(CONFIG &dc, const char *fn) { |
36 | 643 int count = 0; |
644 TOKEN tok(fn, &dc.config_files); | |
645 while (true) { | |
48
ba0259c9e411
Fixes to compile on Fedora 9 and for const correctness
Carl Byington <carl@five-ten-sg.com>
parents:
42
diff
changeset
|
646 const char *have = tok.next(); |
36 | 647 if (!have) break; |
648 if (have == token_threshold) { | |
649 have = tok.next(); | |
650 dc.set_threshold(atoi(have)); | |
651 if (!tsa(tok, token_semi)) return false; | |
652 } | |
653 else if (have == token_ignore) { | |
654 if (!parse_ignore(tok, dc)) return false; | |
655 } | |
656 else if (have == token_add) { | |
657 have = tok.next(); | |
658 dc.set_add(have); | |
659 if (!tsa(tok, token_semi)) return false; | |
660 } | |
661 else if (have == token_remove) { | |
662 have = tok.next(); | |
663 dc.set_remove(have); | |
664 if (!tsa(tok, token_semi)) return false; | |
665 } | |
666 else if (have == token_file) { | |
667 if (!parse_syslogconfig(tok, dc)) return false; | |
668 count++; | |
669 } | |
670 else { | |
671 tok.token_error("threshold/ignore/add_command/remove_command/file", have); | |
672 return false; | |
673 } | |
674 } | |
675 tok.token_error("load_conf() found %d syslog files in %s", count, fn); | |
676 return (!dc.syslogconfigs.empty()); | |
1 | 677 } |
678 | |
679 | |
680 //////////////////////////////////////////////// | |
681 // init the tokens | |
682 // | |
683 void token_init() { | |
36 | 684 token_add = register_string("add_command"); |
685 token_bucket = register_string("bucket"); | |
686 token_file = register_string("file"); | |
687 token_ignore = register_string("ignore"); | |
688 token_include = register_string("include"); | |
689 token_index = register_string("index"); | |
690 token_lbrace = register_string("{"); | |
691 token_message = register_string("message"); | |
692 token_pattern = register_string("pattern"); | |
693 token_rbrace = register_string("}"); | |
694 token_remove = register_string("remove_command"); | |
695 token_semi = register_string(";"); | |
696 token_slash = register_string("/"); | |
697 token_threshold = register_string("threshold"); | |
1 | 698 } |