/* ** Modular Logfile Analyzer ** Copyright 2000 Jan Kneschke ** ** Homepage: http://www.modlogan.org ** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version, and provided that the above copyright and permission notice is included with all distributed copies of this or derived software. 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 ** ** $Id: parse.c,v 1.5 2003/05/17 18:53:52 miham Exp $ */ #include #include #include #include #include #include #include "mlocale.h" #include "mplugins.h" #include "mrecord.h" #include "mdatatypes.h" #include "misc.h" #include "plugin_config.h" #define DEBUG_PCRE typedef struct { int type; pcre *match; } Matches; int parse_record_pcre(mconfig *ext_conf, mlogrec *record, buffer *b) { #define N 20 + 1 const char **list; int ovector[3 * N], n; #ifdef DEBUG_PCRE int i; #endif enum { M_ISDN4BSD_CHD, M_ISDN4BSD_CHD_DIAL, M_ISDN4BSD_CHD_OUT_PROC, M_ISDN4BSD_CHD_OUT_ACT, M_ISDN4BSD_CHD_OUT_CLEAR, M_ISDN4BSD_CHD_OUT_CLEAR_REASON, M_ISDN4BSD_CHD_RATE, M_ISDN4BSD_CHD_CHARGING, M_ISDN4BSD_CHD_ACCOUNTING, M_ISDN4BSD_CHD_MANUAL }; config_input *conf = ext_conf->plugin_conf; const Matches matches [] = { { M_ISDN4BSD_CHD, conf->match_isdn4bsd_chd }, { M_ISDN4BSD_CHD_DIAL, conf->match_isdn4bsd_chd_dialing}, { M_ISDN4BSD_CHD_OUT_PROC, conf->match_isdn4bsd_chd_outgoing_proceeding}, { M_ISDN4BSD_CHD_OUT_ACT, conf->match_isdn4bsd_chd_outgoing_active}, { M_ISDN4BSD_CHD_OUT_CLEAR, conf->match_isdn4bsd_chd_outgoing_clearing}, { M_ISDN4BSD_CHD_OUT_CLEAR_REASON, conf->match_isdn4bsd_chd_outgoing_clearing_reason}, { M_ISDN4BSD_CHD_RATE, conf->match_isdn4bsd_chd_rate}, { M_ISDN4BSD_CHD_CHARGING, conf->match_isdn4bsd_chd_charging }, { M_ISDN4BSD_CHD_ACCOUNTING, conf->match_isdn4bsd_chd_accounting }, { M_ISDN4BSD_CHD_MANUAL, conf->match_isdn4bsd_chd_manual }, { 0, NULL } }; /* try to match the syslog prefix */ if ((n = pcre_exec(conf->match_isdn4bsd, NULL, b->ptr, b->used - 1, 0, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { #if 0 fprintf(stderr, "%s.%d: isdn4bsd prefix doesn't match: %s\n", __FILE__, __LINE__, b->ptr); #endif return M_RECORD_IGNORED; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } /* the prefixed matched */ if (n) { int match = -1; int offset = 0; /* get timestamp and get the length of the string */ pcre_get_substring_list(b->ptr, ovector, n, &list); offset = strlen(list[0]); /* timestamp is in list[1] */ pcre_free(list); /* check CHD string */ if ((n = pcre_exec(conf->match_isdn4bsd_chd, NULL, b->ptr, b->used - 1, offset, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { #if 0 fprintf(stderr, "%s.%d: isdn4bsd channel (CHD) prefix doesn't match: %s\n", __FILE__, __LINE__, b->ptr); #endif return M_RECORD_IGNORED; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } if (n) { pcre_get_substring_list(b->ptr, ovector, n, &list); offset += strlen(list[0]); /* connenction-id is in list[1] */ pcre_free(list); match = -1; i = 0; while ( matches[i].match != NULL ) { /* find the corresponding match */ if ((n = pcre_exec(matches[i].match, NULL, b->ptr, b->used - 1, offset, 0, ovector, 3 * N)) < 0) { if (n == PCRE_ERROR_NOMATCH) { i++; continue; } else { fprintf(stderr, "%s.%d: execution error while matching: %d\n", __FILE__, __LINE__, n); return M_RECORD_HARD_ERROR; } } else { match = matches[i].type; break; } } if (n >= 1 && match != -1) { pcre_get_substring_list(b->ptr, ovector, n, &list); switch (match) { case M_ISDN4BSD_CHD_RATE: return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_DIAL: /* we are dialing out * * - save connection * - set outgoing and incoming number * - wait for traffic numbers * * 1 - source * 2 - dest */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_OUT_PROC: /* 1 - channel */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_OUT_ACT: /* connection is up and running * * just set timestamp for the start * */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_OUT_CLEAR: /* connection has been closed * * local / remote */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_OUT_CLEAR_REASON: /* remove the connection from the local datastore * * add a reason if necessary * * 1 - numerical * 2 - long version */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_CHARGING: /* * 1 - units * 2 - seconds */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_ACCOUNTING: /* * 1 - bytes in * 2 - bytes out * */ return M_RECORD_IGNORED; case M_ISDN4BSD_CHD_MANUAL: /* * removing connection only ? */ return M_RECORD_IGNORED; default: fprintf(stderr, "%s.%d: handling: %s - %d - %d\n", __FILE__, __LINE__, b->ptr, n, match); for (i = 0; i < n; i++) { printf("%d: %s\n", i, list[i]); } return M_RECORD_HARD_ERROR; } pcre_free(list); } else { fprintf(stderr, "%s.%d: can't handled: %s - %d - %d\n", __FILE__, __LINE__, b->ptr, n, match); return M_RECORD_HARD_ERROR; } } } return M_RECORD_NO_ERROR; #undef N } int mplugins_input_isdn4bsd_get_next_record(mconfig *ext_conf, mlogrec *record) { int ret = 0; config_input *conf = ext_conf->plugin_conf; if (record == NULL) return M_RECORD_HARD_ERROR; /* fill the line buffer */ if (NULL == mgets(&(conf->inputfile), conf->buf)) return M_RECORD_EOF; ret = parse_record_pcre (ext_conf, record, conf->buf); if (ret == M_RECORD_CORRUPT) { M_DEBUG1(ext_conf->debug_level, M_DEBUG_SECTION_PARSING, M_DEBUG_LEVEL_WARNINGS, "affected Record: %s\n", conf->buf->ptr ); } return ret; }