summaryrefslogtreecommitdiffstats
path: root/tools/ipmon_y.y
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ipmon_y.y')
-rw-r--r--tools/ipmon_y.y698
1 files changed, 698 insertions, 0 deletions
diff --git a/tools/ipmon_y.y b/tools/ipmon_y.y
new file mode 100644
index 0000000..bc3ec6d
--- /dev/null
+++ b/tools/ipmon_y.y
@@ -0,0 +1,698 @@
+/*
+ * Copyright (C) 2001-2004 by Darren Reed.
+ *
+ * See the IPFILTER.LICENCE file for details on licencing.
+ */
+%{
+#include "ipf.h"
+#include <syslog.h>
+#undef OPT_NAT
+#undef OPT_VERBOSE
+#include "ipmon_l.h"
+#include "ipmon.h"
+
+#define YYDEBUG 1
+
+extern void yyerror __P((char *));
+extern int yyparse __P((void));
+extern int yylex __P((void));
+extern int yydebug;
+extern FILE *yyin;
+extern int yylineNum;
+
+typedef struct opt {
+ struct opt *o_next;
+ int o_line;
+ int o_type;
+ int o_num;
+ char *o_str;
+ struct in_addr o_ip;
+} opt_t;
+
+static void build_action __P((struct opt *));
+static opt_t *new_opt __P((int));
+static void free_action __P((ipmon_action_t *));
+
+static ipmon_action_t *alist = NULL;
+%}
+
+%union {
+ char *str;
+ u_32_t num;
+ struct in_addr addr;
+ struct opt *opt;
+ union i6addr ip6;
+}
+
+%token <num> YY_NUMBER YY_HEX
+%token <str> YY_STR
+%token <ip6> YY_IPV6
+%token YY_COMMENT
+%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
+%token YY_RANGE_OUT YY_RANGE_IN
+
+%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
+%token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT
+%token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
+%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
+%token IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT
+%token IPM_STATE IPM_NATTAG IPM_IPF
+%type <addr> ipv4
+%type <opt> direction dstip dstport every execute group interface
+%type <opt> protocol result rule srcip srcport logtag matching
+%type <opt> matchopt nattag type doopt doing save syslog nothing
+%type <num> saveopts saveopt typeopt
+
+%%
+file: line
+ | assign
+ | file line
+ | file assign
+ ;
+
+line: IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';'
+ { build_action($3); resetlexer(); }
+ | IPM_COMMENT
+ | YY_COMMENT
+ ;
+
+assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
+ resetlexer();
+ free($1);
+ free($3);
+ yyvarnext = 0;
+ }
+ ;
+
+assigning:
+ '=' { yyvarnext = 1; }
+ ;
+
+matching:
+ matchopt { $$ = $1; }
+ | matchopt ',' matching { $1->o_next = $3; $$ = $1; }
+ ;
+
+matchopt:
+ direction { $$ = $1; }
+ | dstip { $$ = $1; }
+ | dstport { $$ = $1; }
+ | every { $$ = $1; }
+ | group { $$ = $1; }
+ | interface { $$ = $1; }
+ | protocol { $$ = $1; }
+ | result { $$ = $1; }
+ | rule { $$ = $1; }
+ | srcip { $$ = $1; }
+ | srcport { $$ = $1; }
+ | logtag { $$ = $1; }
+ | nattag { $$ = $1; }
+ | type { $$ = $1; }
+ ;
+
+doing:
+ doopt { $$ = $1; }
+ | doopt ',' doing { $1->o_next = $3; $$ = $1; }
+ ;
+
+doopt:
+ execute { $$ = $1; }
+ | save { $$ = $1; }
+ | syslog { $$ = $1; }
+ | nothing { $$ = $1; }
+ ;
+
+direction:
+ IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION);
+ $$->o_num = IPM_IN; }
+ | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION);
+ $$->o_num = IPM_OUT; }
+ ;
+
+dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP);
+ $$->o_ip = $3;
+ $$->o_num = $5; }
+ ;
+
+dstport:
+ IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT);
+ $$->o_num = $3; }
+ | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT);
+ $$->o_str = $3; }
+ ;
+
+every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND);
+ $$->o_num = 1; }
+ | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND);
+ $$->o_num = $2; }
+ | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET);
+ $$->o_num = 1; }
+ | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET);
+ $$->o_num = $2; }
+ ;
+
+group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP);
+ $$->o_num = $3; }
+ | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP);
+ $$->o_str = $3; }
+ ;
+
+interface:
+ IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE);
+ $$->o_str = $3; }
+ ;
+
+logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG);
+ $$->o_num = $3; }
+ ;
+
+nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG);
+ $$->o_str = $3; }
+ ;
+
+protocol:
+ IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL);
+ $$->o_num = $3; }
+ | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL);
+ $$->o_num = getproto($3);
+ free($3);
+ }
+ ;
+
+result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT);
+ $$->o_str = $3; }
+ ;
+
+rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE);
+ $$->o_num = YY_NUMBER; }
+ ;
+
+srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP);
+ $$->o_ip = $3;
+ $$->o_num = $5; }
+ ;
+
+srcport:
+ IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT);
+ $$->o_num = $3; }
+ | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT);
+ $$->o_str = $3; }
+ ;
+
+type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE);
+ $$->o_num = $3; }
+ ;
+
+typeopt:
+ IPM_IPF { $$ = IPL_MAGIC; }
+ | IPM_NAT { $$ = IPL_MAGIC_NAT; }
+ | IPM_STATE { $$ = IPL_MAGIC_STATE; }
+ ;
+
+execute:
+ IPM_EXECUTE YY_STR { $$ = new_opt(IPM_EXECUTE);
+ $$->o_str = $2; }
+ ;
+
+save: IPM_SAVE saveopts YY_STR { $$ = new_opt(IPM_SAVE);
+ $$->o_num = $2;
+ $$->o_str = $3; }
+ ;
+
+saveopts: { $$ = 0; }
+ | saveopt { $$ = $1; }
+ | saveopt ',' saveopts { $$ = $1 | $3; }
+ ;
+
+saveopt:
+ IPM_RAW { $$ = IPMDO_SAVERAW; }
+ ;
+
+syslog: IPM_SYSLOG { $$ = new_opt(IPM_SYSLOG); }
+ ;
+
+nothing:
+ IPM_NOTHING { $$ = 0; }
+ ;
+
+ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
+ { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
+ yyerror("Invalid octet string for IP address");
+ return 0;
+ }
+ $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
+ $$.s_addr = htonl($$.s_addr);
+ }
+%%
+static struct wordtab yywords[] = {
+ { "body", IPM_BODY },
+ { "direction", IPM_DIRECTION },
+ { "do", IPM_DO },
+ { "dstip", IPM_DSTIP },
+ { "dstport", IPM_DSTPORT },
+ { "every", IPM_EVERY },
+ { "execute", IPM_EXECUTE },
+ { "group", IPM_GROUP },
+ { "in", IPM_IN },
+ { "interface", IPM_INTERFACE },
+ { "ipf", IPM_IPF },
+ { "logtag", IPM_LOGTAG },
+ { "match", IPM_MATCH },
+ { "nat", IPM_NAT },
+ { "nattag", IPM_NATTAG },
+ { "no", IPM_NO },
+ { "nothing", IPM_NOTHING },
+ { "out", IPM_OUT },
+ { "packet", IPM_PACKET },
+ { "packets", IPM_PACKETS },
+ { "protocol", IPM_PROTOCOL },
+ { "result", IPM_RESULT },
+ { "rule", IPM_RULE },
+ { "save", IPM_SAVE },
+ { "second", IPM_SECOND },
+ { "seconds", IPM_SECONDS },
+ { "srcip", IPM_SRCIP },
+ { "srcport", IPM_SRCPORT },
+ { "state", IPM_STATE },
+ { "syslog", IPM_SYSLOG },
+ { "with", IPM_WITH },
+ { NULL, 0 }
+};
+
+static int macflags[17][2] = {
+ { IPM_DIRECTION, IPMAC_DIRECTION },
+ { IPM_DSTIP, IPMAC_DSTIP },
+ { IPM_DSTPORT, IPMAC_DSTPORT },
+ { IPM_GROUP, IPMAC_GROUP },
+ { IPM_INTERFACE, IPMAC_INTERFACE },
+ { IPM_LOGTAG, IPMAC_LOGTAG },
+ { IPM_NATTAG, IPMAC_NATTAG },
+ { IPM_PACKET, IPMAC_EVERY },
+ { IPM_PROTOCOL, IPMAC_PROTOCOL },
+ { IPM_RESULT, IPMAC_RESULT },
+ { IPM_RULE, IPMAC_RULE },
+ { IPM_SECOND, IPMAC_EVERY },
+ { IPM_SRCIP, IPMAC_SRCIP },
+ { IPM_SRCPORT, IPMAC_SRCPORT },
+ { IPM_TYPE, IPMAC_TYPE },
+ { IPM_WITH, IPMAC_WITH },
+ { 0, 0 }
+};
+
+static opt_t *new_opt(type)
+int type;
+{
+ opt_t *o;
+
+ o = (opt_t *)malloc(sizeof(*o));
+ o->o_type = type;
+ o->o_line = yylineNum;
+ o->o_num = 0;
+ o->o_str = (char *)0;
+ o->o_next = NULL;
+ return o;
+}
+
+static void build_action(olist)
+opt_t *olist;
+{
+ ipmon_action_t *a;
+ opt_t *o;
+ char c;
+ int i;
+
+ a = (ipmon_action_t *)calloc(1, sizeof(*a));
+ if (a == NULL)
+ return;
+ while ((o = olist) != NULL) {
+ /*
+ * Check to see if the same comparator is being used more than
+ * once per matching statement.
+ */
+ for (i = 0; macflags[i][0]; i++)
+ if (macflags[i][0] == o->o_type)
+ break;
+ if (macflags[i][1] & a->ac_mflag) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ if (o->o_str != NULL)
+ free(o->o_str);
+ olist = o->o_next;
+ free(o);
+ continue;
+ }
+
+ a->ac_mflag |= macflags[i][1];
+
+ switch (o->o_type)
+ {
+ case IPM_DIRECTION :
+ a->ac_direction = o->o_num;
+ break;
+ case IPM_DSTIP :
+ a->ac_dip = o->o_ip.s_addr;
+ a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
+ break;
+ case IPM_DSTPORT :
+ a->ac_dport = htons(o->o_num);
+ break;
+ case IPM_EXECUTE :
+ a->ac_exec = o->o_str;
+ c = *o->o_str;
+ if (c== '"'|| c == '\'') {
+ if (o->o_str[strlen(o->o_str) - 1] == c) {
+ a->ac_run = strdup(o->o_str + 1);
+ a->ac_run[strlen(a->ac_run) - 1] ='\0';
+ } else
+ a->ac_run = o->o_str;
+ } else
+ a->ac_run = o->o_str;
+ o->o_str = NULL;
+ break;
+ case IPM_INTERFACE :
+ a->ac_iface = o->o_str;
+ o->o_str = NULL;
+ break;
+ case IPM_GROUP :
+ if (o->o_str != NULL)
+ strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
+ else
+ sprintf(a->ac_group, "%d", o->o_num);
+ break;
+ case IPM_LOGTAG :
+ a->ac_logtag = o->o_num;
+ break;
+ case IPM_NATTAG :
+ strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
+ break;
+ case IPM_PACKET :
+ a->ac_packet = o->o_num;
+ break;
+ case IPM_PROTOCOL :
+ a->ac_proto = o->o_num;
+ break;
+ case IPM_RULE :
+ a->ac_rule = o->o_num;
+ break;
+ case IPM_RESULT :
+ if (!strcasecmp(o->o_str, "pass"))
+ a->ac_result = IPMR_PASS;
+ else if (!strcasecmp(o->o_str, "block"))
+ a->ac_result = IPMR_BLOCK;
+ else if (!strcasecmp(o->o_str, "nomatch"))
+ a->ac_result = IPMR_NOMATCH;
+ else if (!strcasecmp(o->o_str, "log"))
+ a->ac_result = IPMR_LOG;
+ break;
+ case IPM_SECOND :
+ a->ac_second = o->o_num;
+ break;
+ case IPM_SRCIP :
+ a->ac_sip = o->o_ip.s_addr;
+ a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
+ break;
+ case IPM_SRCPORT :
+ a->ac_sport = htons(o->o_num);
+ break;
+ case IPM_SAVE :
+ if (a->ac_savefile != NULL) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ break;
+ }
+ a->ac_savefile = strdup(o->o_str);
+ a->ac_savefp = fopen(o->o_str, "a");
+ a->ac_dflag |= o->o_num & IPMDO_SAVERAW;
+ break;
+ case IPM_SYSLOG :
+ if (a->ac_syslog != 0) {
+ fprintf(stderr, "%s redfined on line %d\n",
+ yykeytostr(o->o_type), yylineNum);
+ break;
+ }
+ a->ac_syslog = 1;
+ break;
+ case IPM_TYPE :
+ a->ac_type = o->o_num;
+ break;
+ case IPM_WITH :
+ break;
+ default :
+ break;
+ }
+
+ olist = o->o_next;
+ if (o->o_str != NULL)
+ free(o->o_str);
+ free(o);
+ }
+ a->ac_next = alist;
+ alist = a;
+}
+
+
+int check_action(buf, log, opts, lvl)
+char *buf, *log;
+int opts, lvl;
+{
+ ipmon_action_t *a;
+ struct timeval tv;
+ ipflog_t *ipf;
+ tcphdr_t *tcp;
+ iplog_t *ipl;
+ int matched;
+ u_long t1;
+ ip_t *ip;
+
+ matched = 0;
+ ipl = (iplog_t *)buf;
+ ipf = (ipflog_t *)(ipl +1);
+ ip = (ip_t *)(ipf + 1);
+ tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
+
+ for (a = alist; a != NULL; a = a->ac_next) {
+ if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
+ if (a->ac_direction == IPM_IN) {
+ if ((ipf->fl_flags & FR_INQUE) == 0)
+ continue;
+ } else if (a->ac_direction == IPM_OUT) {
+ if ((ipf->fl_flags & FR_OUTQUE) == 0)
+ continue;
+ }
+ }
+
+ if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic))
+ continue;
+
+ if ((a->ac_mflag & IPMAC_EVERY) != 0) {
+ gettimeofday(&tv, NULL);
+ t1 = tv.tv_sec - a->ac_lastsec;
+ if (tv.tv_usec <= a->ac_lastusec)
+ t1--;
+ if (a->ac_second != 0) {
+ if (t1 < a->ac_second)
+ continue;
+ a->ac_lastsec = tv.tv_sec;
+ a->ac_lastusec = tv.tv_usec;
+ }
+
+ if (a->ac_packet != 0) {
+ if (a->ac_pktcnt == 0)
+ a->ac_pktcnt++;
+ else if (a->ac_pktcnt == a->ac_packet) {
+ a->ac_pktcnt = 0;
+ continue;
+ } else {
+ a->ac_pktcnt++;
+ continue;
+ }
+ }
+ }
+
+ if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
+ if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
+ if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
+ continue;
+ if (tcp->th_dport != a->ac_dport)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_GROUP) != 0) {
+ if (strncmp(a->ac_group, ipf->fl_group,
+ FR_GROUPLEN) != 0)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
+ if (strcmp(a->ac_iface, ipf->fl_ifname))
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
+ if (a->ac_proto != ip->ip_p)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_RESULT) != 0) {
+ if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
+ if (a->ac_result != IPMR_NOMATCH)
+ continue;
+ } else if (FR_ISPASS(ipf->fl_flags)) {
+ if (a->ac_result != IPMR_PASS)
+ continue;
+ } else if (FR_ISBLOCK(ipf->fl_flags)) {
+ if (a->ac_result != IPMR_BLOCK)
+ continue;
+ } else { /* Log only */
+ if (a->ac_result != IPMR_LOG)
+ continue;
+ }
+ }
+
+ if ((a->ac_mflag & IPMAC_RULE) != 0) {
+ if (a->ac_rule != ipf->fl_rule)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
+ if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
+ if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP)
+ continue;
+ if (tcp->th_sport != a->ac_sport)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
+ if (a->ac_logtag != ipf->fl_logtag)
+ continue;
+ }
+
+ if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
+ if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
+ IPFTAG_LEN) != 0)
+ continue;
+ }
+
+ matched = 1;
+
+ /*
+ * It matched so now execute the command
+ */
+ if (a->ac_syslog != 0) {
+ syslog(lvl, "%s", log);
+ }
+
+ if (a->ac_savefp != NULL) {
+ if (a->ac_dflag & IPMDO_SAVERAW)
+ fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp);
+ else
+ fputs(log, a->ac_savefp);
+ }
+
+ if (a->ac_exec != NULL) {
+ switch (fork())
+ {
+ case 0 :
+ {
+ FILE *pi;
+
+ pi = popen(a->ac_run, "w");
+ if (pi != NULL) {
+ fprintf(pi, "%s\n", log);
+ if ((opts & OPT_HEXHDR) != 0) {
+ dumphex(pi, 0, buf,
+ sizeof(*ipl) +
+ sizeof(*ipf));
+ }
+ if ((opts & OPT_HEXBODY) != 0) {
+ dumphex(pi, 0, (char *)ip,
+ ipf->fl_hlen +
+ ipf->fl_plen);
+ }
+ pclose(pi);
+ }
+ exit(1);
+ }
+ case -1 :
+ break;
+ default :
+ break;
+ }
+ }
+ }
+
+ return matched;
+}
+
+
+static void free_action(a)
+ipmon_action_t *a;
+{
+ if (a->ac_savefile != NULL) {
+ free(a->ac_savefile);
+ a->ac_savefile = NULL;
+ }
+ if (a->ac_savefp != NULL) {
+ fclose(a->ac_savefp);
+ a->ac_savefp = NULL;
+ }
+ if (a->ac_exec != NULL) {
+ free(a->ac_exec);
+ if (a->ac_run == a->ac_exec)
+ a->ac_run = NULL;
+ a->ac_exec = NULL;
+ }
+ if (a->ac_run != NULL) {
+ free(a->ac_run);
+ a->ac_run = NULL;
+ }
+ if (a->ac_iface != NULL) {
+ free(a->ac_iface);
+ a->ac_iface = NULL;
+ }
+ a->ac_next = NULL;
+ free(a);
+}
+
+
+int load_config(file)
+char *file;
+{
+ ipmon_action_t *a;
+ FILE *fp;
+ char *s;
+
+ s = getenv("YYDEBUG");
+ if (s != NULL)
+ yydebug = atoi(s);
+ else
+ yydebug = 0;
+
+ while ((a = alist) != NULL) {
+ alist = a->ac_next;
+ free_action(a);
+ }
+
+ yylineNum = 1;
+
+ (void) yysettab(yywords);
+
+ fp = fopen(file, "r");
+ if (!fp) {
+ perror("load_config:fopen:");
+ return -1;
+ }
+ yyin = fp;
+ while (!feof(fp))
+ yyparse();
+ fclose(fp);
+ return 0;
+}
OpenPOWER on IntegriCloud