Files
seta75D 2e8a93c394 Init
2021-10-11 18:20:23 -03:00

204 lines
4.6 KiB
C

#ifndef lint
static char sccsid[] = "@(#)packetfilt.c 1.1 92/07/30 SMI";
#endif
#include <sys/param.h>
#include <net/packetfilt.h>
/* #define DEBUG 1 */
/* #define INNERDEBUG 1 */ /* define only when debugging enDoFilter()
or enInputDone() */
#ifdef INNERDEBUG
#define enprintf(flags) if (enDebug&(flags)) printf
/*
* Symbolic definitions for enDebug flag bits
* ENDBG_TRACE should be 1 because it is the most common
* use in the code, and the compiler generates faster code
* for testing the low bit in a word.
*/
#define ENDBG_TRACE 1 /* trace most operations */
#define ENDBG_DESQ 2 /* trace descriptor queues */
#define ENDBG_INIT 4 /* initialization info */
#define ENDBG_SCAV 8 /* scavenger operation */
#define ENDBG_ABNORM 16 /* abnormal events */
int enDebug = /* ENDBG_ABNORM | ENDBG_INIT | ENDBG_TRACE */ -1;
#endif /* INNERDEBUG */
/*
* Apply the packet filter given by pfp to the packet given by
* pp. Return nonzero iff the filter accepts the packet.
*
* The packet comes in two pieces, a header and a body, since
* that's the most convenient form for our caller. The header
* is in contiguous memory, whereas the body is in a mbuf.
* Our caller will have adjusted the mbuf chain so that its first
* min(MLEN, length(body)) bytes are guaranteed contiguous. For
* the sake of efficiency (and some laziness) the filter is prepared
* to examine only these two contiguous pieces. Furthermore, it
* assumes that the header length is even, so that there's no need
* to glue the last byte of header to the first byte of data.
*/
#define opx(i) ((i) >> ENF_NBPA)
int
FilterPacket(pp, pfp)
struct packdesc *pp;
struct epacketfilt *pfp;
{
register int maxhdr = pp->pd_hdrlen;
int maxword = maxhdr + pp->pd_bodylen;
register u_short *sp;
register u_short *fp;
register u_short *fpe;
register unsigned op;
register unsigned arg;
u_short stack[ENMAXFILTERS+1];
fp = &pfp->pf_Filter[0];
fpe = pfp->pf_FilterEnd;
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("FilterPacket(%x, %x, %x, %x):\n", pp, pfp, fp, fpe);
#endif
/*
* Push TRUE on stack to start. The stack size is chosen such
* that overflow can't occur -- each operation can push at most
* one item on the stack, and the stack size equals the maximum
* program length.
*/
sp = &stack[ENMAXFILTERS];
*sp = 1;
for ( ; fp < fpe; ) {
op = *fp >> ENF_NBPA;
arg = *fp & ((1 << ENF_NBPA) - 1);
fp++;
switch (arg) {
default:
arg -= ENF_PUSHWORD;
/*
* Since arg is unsigned,
* if it were less than ENF_PUSHWORD before,
* it would now be huge.
*/
if (arg < maxhdr)
*--sp = pp->pd_hdr[arg];
else if (arg < maxword)
*--sp = pp->pd_body[arg - maxhdr];
else {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>0(len)\n");
#endif
return (0);
}
break;
case ENF_PUSHLIT:
*--sp = *fp++;
break;
case ENF_PUSHZERO:
*--sp = 0;
case ENF_NOPUSH:
break;
}
if (sp < &stack[2]) { /* check stack overflow: small yellow zone */
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>0(--sp)\n");
#endif
return (0);
}
if (op == ENF_NOP)
continue;
/*
* all non-NOP operators binary, must have at least two operands
* on stack to evaluate.
*/
if (sp > &stack[ENMAXFILTERS-2]) {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>0(sp++)\n");
#endif
return (0);
}
arg = *sp++;
switch (op) {
default:
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>0(def)\n");
#endif
return (0);
case opx(ENF_AND):
*sp &= arg;
break;
case opx(ENF_OR):
*sp |= arg;
break;
case opx(ENF_XOR):
*sp ^= arg;
break;
case opx(ENF_EQ):
*sp = (*sp == arg);
break;
case opx(ENF_NEQ):
*sp = (*sp != arg);
break;
case opx(ENF_LT):
*sp = (*sp < arg);
break;
case opx(ENF_LE):
*sp = (*sp <= arg);
break;
case opx(ENF_GT):
*sp = (*sp > arg);
break;
case opx(ENF_GE):
*sp = (*sp >= arg);
break;
/* short-circuit operators */
case opx(ENF_COR):
if (*sp++ == arg) {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>COR %x\n", *sp);
#endif
return (1);
}
break;
case opx(ENF_CAND):
if (*sp++ != arg) {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>CAND %x\n", *sp);
#endif
return (0);
}
break;
case opx(ENF_CNOR):
if (*sp++ == arg) {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>COR %x\n", *sp);
#endif
return (0);
}
break;
case opx(ENF_CNAND):
if (*sp++ != arg) {
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>CNAND %x\n", *sp);
#endif
return (1);
}
break;
}
}
#ifdef INNERDEBUG
enprintf(ENDBG_TRACE)("=>%x\n", *sp);
#endif
return (*sp);
}