/* $Id: ipfw.l,v 1.6 2006/03/03 17:27:38 bhockney Exp $ */ /* (C) 2004-2006 by Bob Hockney * * Based on fwlogwatch written by * * Boris Wesslowski * * * * ipfw log parser for wfwl_syslog * * * * This code is distributed under the terms of GNU GPL */ %option prefix="ipfw" %option outfile="ipfw.c" %option noyywrap %{ #define YY_NO_UNPUT #include #include #include #include "main.h" #include "utils.h" #ifndef IP_MF #define IP_MF 0x2000 #endif extern struct options opt; void ipfw_parse_start(char *input); void ipfw_parse_label(char *input); void ipfw_parse_proto(char *input, unsigned char mode); void ipfw_parse_ips(char *input, unsigned char mode); void ipfw_parse_frag(char *input); %} MONTH "Jan"|"Feb"|"Mar"|"Apr"|"May"|"Jun"|"Jul"|"Aug"|"Sep"|"Oct"|"Nov"|"Dec" STRING [a-zA-Z][a-zA-Z0-9.-]* LOGHOST [0-9.a-zA-Z()_:-]* DIGIT [0-9] NUMBER {DIGIT}+ OCTET {DIGIT}{1,3} PORT {DIGIT}{1,5} PROTO "TCP"|"UDP"|"ICMP" ACTION "Refuse"|"Deny"|"Reset"|"Reject"|"Unreach "{NUMBER}|"Unreach"|"Accept"|"Count"|"Divert "{NUMBER}|"Tee "{NUMBER}|"SkipTo "{NUMBER}|"Pipe "{NUMBER}|"Queue "{NUMBER}|"Forward to "{OCTET}"."{OCTET}"."{OCTET}"."{OCTET}":"?{PORT}?|"UNKNOWN" %% {MONTH}[ ]{1,2}{DIGIT}{1,2}[ ]{DIGIT}{2}:{DIGIT}{2}:{DIGIT}{2}[ ]{LOGHOST} ipfw_parse_start(ipfwtext); [^:]+": ipfw: "{NUMBER}" "{ACTION} ipfw_parse_label(ipfwtext); {PROTO} ipfw_parse_proto(ipfwtext, IPFW_OPT_NONE); "ICMP:"{NUMBER}"."{NUMBER} ipfw_parse_proto(ipfwtext+5, IPFW_OPT_ICMP); "P:"{NUMBER} ipfw_parse_proto(ipfwtext, IPFW_OPT_OTHER); {OCTET}"."{OCTET}"."{OCTET}"."{OCTET}[ ]{OCTET}"."{OCTET}"."{OCTET}"."{OCTET} ipfw_parse_ips(ipfwtext, IPFW_OPT_NONE); {OCTET}"."{OCTET}"."{OCTET}"."{OCTET}":"{PORT}[ ]{OCTET}"."{OCTET}"."{OCTET}"."{OCTET}":"{PORT} ipfw_parse_ips(ipfwtext, IPFW_OPT_PORTS); "in via "{STRING} { xstrncpy(opt.line->inif, ipfwtext+7, SHORTLEN); opt.parser=opt.parser|IPFW_IF; } "out via "{STRING} { xstrncpy(opt.line->outif, ipfwtext+8, SHORTLEN); opt.parser=opt.parser|IPFW_IF; } "[no if info]" /* ignore */ "(frag "{NUMBER}":"{NUMBER}"@"{NUMBER}"+"?")" ipfw_parse_frag(ipfwtext+6); [^:]+": ipfw: limit "{NUMBER}" reached on entry "{NUMBER} opt.parser=opt.parser|IPFW_NO_HIT; "MAC" /* ignore */ [ ] /* ignore whitespace */ [\n] return 0; {STRING} if(opt.verbose) fprintf(stderr, "Unrecognized token: %s\n", ipfwtext); . if(opt.verbose) fprintf(stderr, "Unrecognized character: %s\n", ipfwtext); %% void ipfw_parse_start(char *input) { int retval, day, hour, minute, second; char smonth[4]; retval = sscanf(input, "%3s %2d %2d:%2d:%2d %32s", smonth, &day, &hour, &minute, &second, opt.line->hostname); if (retval != 6) { return; } build_time(smonth, day, hour, minute, second); opt.parser=opt.parser|IPFW_DATE; } void ipfw_parse_label(char *input) { int retval; retval = sscanf(input, "%*s ipfw: %5s %121[a-zA-Z0-9 .:]", opt.line->log_label, opt.line->branchname); if (retval != 2) return; strcat(opt.line->log_label, " "); strcat(opt.line->log_label, opt.line->branchname); opt.parser=opt.parser|IPFW_CHAIN; } void ipfw_parse_proto(char *input, unsigned char mode) { int retval; char *pnt; if(mode == IPFW_OPT_NONE) { if(strncmp(input, "ICMP", 4) == 0) opt.line->protocol = 1; if(strncmp(input, "TCP" , 3) == 0) opt.line->protocol = 6; if(strncmp(input, "UDP" , 3) == 0) opt.line->protocol = 17; } else if(mode == IPFW_OPT_ICMP) { opt.line->protocol = 1; pnt = strstr(input, "."); *pnt = ' '; retval = sscanf(input, "%2d %2d", &opt.line->icmp_type, &opt.line->icmp_code); if (retval != 2) { return; } } else if (mode == IPFW_OPT_OTHER) { retval = sscanf(input, "P:%5d", &opt.line->protocol); if (retval != 1) return; } if(opt.line->protocol != 0) { opt.parser=opt.parser|IPFW_PROTO; } } void ipfw_parse_ips(char *input, unsigned char mode) { int retval; char src[16], dst[16], *pnt; if (mode == IPFW_OPT_PORTS) { pnt = strstr(input, ":"); *pnt = ' '; pnt = strstr(input, ":"); *pnt = ' '; retval = sscanf(input, "%15s %5d %15s %5d", src, &opt.line->sport, dst, &opt.line->dport); if (retval != 4) { return; } } else if (mode == IPFW_OPT_NONE) { retval = sscanf(input, "%15s %15s", src, dst); if (retval != 2) { return; } } if(convert_ip(src, &opt.line->shost) == IN_ADDR_ERROR) return; if(convert_ip(dst, &opt.line->dhost) == IN_ADDR_ERROR) return; opt.parser=opt.parser|IPFW_IPS; } void ipfw_parse_frag(char *input) { int retval; unsigned int frag; char *pnt; unsigned char mf = '\0'; pnt = strstr(input, ")"); *pnt = '\0'; retval = sscanf(input, "%d:%d@%d%c", &opt.line->ipid, &opt.line->datalen, &frag, &mf); opt.line->fragoff = frag >> 3; if (mf == '+') opt.line->fragoff |= IP_MF; } unsigned char flex_ipfw(char *input, int linenum) { struct yy_buffer_state *state; opt.parser = 0; init_line(); state = ipfw_scan_string(input); ipfwlex(); ipfw_delete_buffer(state); opt.line->count = 1; if (opt.parser & IPFW_NO_HIT) return PARSE_NO_HIT; if ((opt.parser & (IPFW_DATE|IPFW_CHAIN|IPFW_PROTO|IPFW_IPS|IPFW_IF)) == (IPFW_DATE|IPFW_CHAIN|IPFW_PROTO|IPFW_IPS|IPFW_IF)) { opt.line->flags |= TCP_FLAGS_MATCH; return PARSE_OK; } if(opt.verbose) fprintf(stderr, "ipfw parse error in line %d, ignoring.\n", linenum); if(opt.verbose == 2) fprintf(stderr, "input was: \"%s\"\n", input); return PARSE_WRONG_FORMAT; }