/* extract - A network log processor Copyright (C) 1993 Douglas Lee Schales, David K. Hess, David R. Safford Please see the file `COPYING' for the complete copyright notice. interp.c - 03/20/93 */ #include #include #include #include #include "extract.h" #include "parser.h" #include "y.tab.h" #include "interp.h" #define CONTINUE 0 #define RETURN 1 static unsigned long evaluate(char *, struct ftver *, struct parsenode *); static unsigned long checkcond(unsigned long, unsigned long, int); static int perform(char *, struct ftver *, struct actionlist *, struct ftio *, int); extern void writebuf(char *, struct ftver *, int, struct ftio *, int); static unsigned long rectime = 0; void interp(char *rec, struct ftver *ftv, struct parsetree *pt, struct ftio *ftio_out, int oldflow) { struct parsetree *rove; int status; rectime = 0; for(rove = pt;rove;rove=rove->next){ if(!rove->conditions || evaluate(rec, ftv, rove->conditions)){ status = perform(rec, ftv, rove->actions, ftio_out, oldflow); if(status == RETURN) return; } } } unsigned long evaluate(char *rec, struct ftver *ftv, struct parsenode *pn) { unsigned long lhs, rhs; struct tm *tmb; struct fts3rec_gen *genrec; struct fttime ftt; void *recptr; time_t secs; switch (ftv->d_version) { case 1: case 5: case 6: case 7: genrec = (struct fts3rec_gen *)rec; break; default: break; } if(pn->nodetype == KEY){ switch(pn->nodeval){ case SRCADDR: case SRCNET: return genrec->srcaddr; break; case DSTADDR: case DSTNET: return genrec->dstaddr; break; case SRCPORT: return genrec->srcport; break; case DSTPORT: return genrec->dstport; break; case NEXTHOP: return genrec->nexthop; case DATE: ftt = ftltime(genrec->sysUpTime, genrec->unix_secs, genrec->unix_nsecs, genrec->First); return ftt.secs; break; case PROTO: return genrec->prot; break; case PKTS: return genrec->dPkts; break; case OCTETS: return genrec->dOctets; break; case FLAG: case FLAGS: return genrec->tcp_flags; break; case SRCIFACE: return genrec->input; break; case DSTIFACE: return genrec->output; break; case TIME: if(!rectime){ ftt = ftltime(genrec->sysUpTime, genrec->unix_secs, genrec->unix_nsecs, genrec->First); tmb = localtime(&ftt.secs); rectime = tmb->tm_hour*3600 + tmb->tm_min*60 + tmb->tm_sec; } return rectime; break; default: /* hmmmm... */ break; } } else if(pn->nodetype == VAL) return pn->nodeval; else if(pn->nodetype == UOPER){ rhs = evaluate(rec, ftv, pn->rhs); switch(pn->nodeval){ case '!': return !rhs; break; default: break; } } else { switch(pn->nodeval){ case OR: if((lhs = evaluate(rec, ftv, pn->lhs))) return lhs; else return evaluate(rec, ftv, pn->rhs); break; case AND: if(!(lhs = evaluate(rec, ftv, pn->lhs))) return lhs; else return evaluate(rec, ftv, pn->rhs); break; case MASKOPER: case '&': lhs = evaluate(rec, ftv, pn->lhs); rhs = evaluate(rec, ftv, pn->rhs); return lhs & rhs; break; default: lhs = evaluate(rec, ftv, pn->lhs); rhs = evaluate(rec, ftv, pn->rhs); return checkcond(lhs, rhs, pn->nodeval); } } return 0; } unsigned long checkcond(unsigned long lhs, unsigned long rhs, int cond) { switch(cond){ case '=': return lhs == rhs; break; case '>': return lhs > rhs; break; case '<': return lhs < rhs; break; case NEQ: return lhs != rhs; break; case LEQ: return lhs <= rhs; break; case GEQ: return lhs >= rhs; break; } return 0; } int perform(char *rec, struct ftver *ftv, struct actionlist *al, struct ftio *ftio_out, int oldflow) { int topaction = CONTINUE; struct actionlist *rove; for(rove=al;topaction != RETURN && rove;rove=rove->next) switch(rove->action){ case PRINT: writebuf(rec, ftv, 0, ftio_out, oldflow); break; case PRINTALL: writebuf(rec, ftv, 1, ftio_out, oldflow); break; case NEXT: topaction = RETURN; break; default: /* Hmmmm */ break; } return topaction; }