Add support for packet filtering
authorPaul Mackerras <paulus@samba.org>
Thu, 4 Apr 1996 02:46:59 +0000 (02:46 +0000)
committerPaul Mackerras <paulus@samba.org>
Thu, 4 Apr 1996 02:46:59 +0000 (02:46 +0000)
include/net/bpf.h [new file with mode: 0644]
include/net/pppio.h
modules/bpf_filter.c [new file with mode: 0644]
modules/ppp.c

diff --git a/include/net/bpf.h b/include/net/bpf.h
new file mode 100644 (file)
index 0000000..c5f7c1f
--- /dev/null
@@ -0,0 +1,147 @@
+/*     From: NetBSD: bpf.h,v 1.12 1995/09/27 18:30:40 thorpej Exp */
+
+/*
+ * Copyright (c) 1990, 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)bpf.h       8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NET_BPF_H_
+#define _NET_BPF_H_
+
+/*
+ * Alignment macros.  BPF_WORDALIGN rounds up to the next 
+ * even multiple of BPF_ALIGNMENT. 
+ */
+#define BPF_ALIGNMENT sizeof(long)
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ *  Structure for BIOCSETF.
+ */
+struct bpf_program {
+       unsigned int bf_len;
+       struct bpf_insn *bf_insns;
+};
+
+/*
+ * The instruction encondings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define                BPF_LD          0x00
+#define                BPF_LDX         0x01
+#define                BPF_ST          0x02
+#define                BPF_STX         0x03
+#define                BPF_ALU         0x04
+#define                BPF_JMP         0x05
+#define                BPF_RET         0x06
+#define                BPF_MISC        0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define                BPF_W           0x00
+#define                BPF_H           0x08
+#define                BPF_B           0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define                BPF_IMM         0x00
+#define                BPF_ABS         0x20
+#define                BPF_IND         0x40
+#define                BPF_MEM         0x60
+#define                BPF_LEN         0x80
+#define                BPF_MSH         0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code)   ((code) & 0xf0)
+#define                BPF_ADD         0x00
+#define                BPF_SUB         0x10
+#define                BPF_MUL         0x20
+#define                BPF_DIV         0x30
+#define                BPF_OR          0x40
+#define                BPF_AND         0x50
+#define                BPF_LSH         0x60
+#define                BPF_RSH         0x70
+#define                BPF_NEG         0x80
+#define                BPF_JA          0x00
+#define                BPF_JEQ         0x10
+#define                BPF_JGT         0x20
+#define                BPF_JGE         0x30
+#define                BPF_JSET        0x40
+#define BPF_SRC(code)  ((code) & 0x08)
+#define                BPF_K           0x00
+#define                BPF_X           0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define                BPF_A           0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define                BPF_TAX         0x00
+#define                BPF_TXA         0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+       unsigned short  code;
+       unsigned char   jt;
+       unsigned char   jf;
+       int             k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
+
+#ifdef _KERNEL
+int     bpf_validate __P((struct bpf_insn *, int));
+u_int   bpf_filter __P((struct bpf_insn *, u_char *, u_int, u_int));
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#endif /* _NET_BPF_H_ */
index 547b79864e4e9e48494427ff1370fbffee50998a..d364aeaff73b01cad2668a3960cd68d0471733c6 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: pppio.h,v 1.6 1995/10/27 03:36:58 paulus Exp $
+ * $Id: pppio.h,v 1.7 1996/04/04 02:46:59 paulus Exp $
  */
 
 #define _PPPIO(n)      (('p' << 8) + (n))
@@ -47,6 +47,8 @@
 #define PPPIO_BIND     _PPPIO(145)     /* bind to SAP */
 #define PPPIO_NPMODE   _PPPIO(146)     /* set mode for handling data pkts */
 #define PPPIO_GIDLE    _PPPIO(147)     /* get time since last data pkt */
+#define PPPIO_PASSFILT _PPPIO(148)     /* set filter for packets to pass */
+#define PPPIO_ACTIVEFILT _PPPIO(149)   /* set filter for "link active" pkts */
 
 /*
  * Values for PPPIO_CFLAGS
diff --git a/modules/bpf_filter.c b/modules/bpf_filter.c
new file mode 100644 (file)
index 0000000..f47ed2c
--- /dev/null
@@ -0,0 +1,542 @@
+/*     From NetBSD: bpf_filter.c,v 1.12 1996/02/13 22:00:00 christos Exp */
+
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     From: @(#)bpf_filter.c  8.1 (Berkeley) 6/10/93
+ *     $Id: bpf_filter.c,v 1.1 1996/04/04 02:45:45 paulus Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <net/ppp_defs.h>
+#include "ppp_mod.h"
+
+#ifdef SVR4
+#ifndef __GNUC__
+#include <sys/byteorder.h>     /* for ntohl, etc. */
+#else
+/* make sure we don't get the gnu "fixed" one! */
+#include "/usr/include/sys/byteorder.h"
+#endif
+#endif
+
+#ifdef OSF1
+#include <net/net_globals.h>
+#endif
+#include <netinet/in.h>
+
+#ifdef AIX4
+#define _NETINET_IN_SYSTM_H_
+typedef u_long  n_long;
+#else
+#include <netinet/in_systm.h>
+#endif
+
+#if !(defined(__i386__) || defined(__m68k__))  /* any others? */
+#define BPF_ALIGN
+#endif
+
+#ifndef BPF_ALIGN
+#define EXTRACT_SHORT(p)       ((ushort)ntohs(*(ushort *)p))
+#define EXTRACT_LONG(p)                (ntohl(*(uint *)p))
+#else
+#define EXTRACT_SHORT(p)\
+       ((ushort)\
+               ((ushort)*((u_char *)p+0)<<8|\
+                (ushort)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+               ((uint)*((u_char *)p+0)<<24|\
+                (uint)*((u_char *)p+1)<<16|\
+                (uint)*((u_char *)p+2)<<8|\
+                (uint)*((u_char *)p+3)<<0)
+#endif
+
+#ifdef _KERNEL
+#define MINDEX(len, m, k) \
+{ \
+       len = m->b_wptr - m->b_rptr; \
+       while (k >= len) { \
+               k -= len; \
+               m = m->b_cont; \
+               if (m == 0) \
+                       return 0; \
+               len = m->b_wptr - m->b_rptr; \
+       } \
+}
+
+static int m_xword __P((mblk_t *, int, int *));
+static int m_xhalf __P((mblk_t *, int, int *));
+
+static int
+m_xword(m, k, err)
+       register mblk_t *m;
+       register int k, *err;
+{
+       register int len;
+       register uchar_t *cp, *np;
+       register mblk_t *m0;
+
+       MINDEX(len, m, k);
+       cp = m->b_rptr + k;
+       if (len - k >= 4) {
+               *err = 0;
+               return EXTRACT_LONG(cp);
+       }
+       m0 = m->b_cont;
+       if (m0 == 0 || m0->b_wptr - m0->b_rptr + len - k < 4)
+               goto bad;
+       *err = 0;
+       np = m0->b_rptr;
+       switch (len - k) {
+
+       case 1:
+               return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
+
+       case 2:
+               return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
+
+       default:
+               return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
+       }
+    bad:
+       *err = 1;
+       return 0;
+}
+
+static int
+m_xhalf(m, k, err)
+       register mblk_t *m;
+       register int k, *err;
+{
+       register int len;
+       register uchar_t *cp;
+       register mblk_t *m0;
+
+       MINDEX(len, m, k);
+       cp = m->b_rptr + k;
+       if (len - k >= 2) {
+               *err = 0;
+               return EXTRACT_SHORT(cp);
+       }
+       m0 = m->b_cont;
+       if (m0 == 0)
+               goto bad;
+       *err = 0;
+       return (cp[0] << 8) | m0->b_rptr[0];
+ bad:
+       *err = 1;
+       return 0;
+}
+#endif
+
+#include <net/bpf.h>
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ */
+uint
+bpf_filter(pc, p, wirelen, buflen)
+       register struct bpf_insn *pc;
+       register uchar_t *p;
+       uint wirelen;
+       register uint buflen;
+{
+       register uint A = 0, X = 0;
+       register int k;
+       int mem[BPF_MEMWORDS];
+
+       if (pc == 0)
+               /*
+                * No filter means accept all.
+                */
+               return (uint)-1;
+       --pc;
+       while (1) {
+               ++pc;
+               switch (pc->code) {
+
+               default:
+#ifdef _KERNEL
+                       return 0;
+#else
+                       abort();
+#endif                 
+               case BPF_RET|BPF_K:
+                       return (uint)pc->k;
+
+               case BPF_RET|BPF_A:
+                       return (uint)A;
+
+               case BPF_LD|BPF_W|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(int) > buflen) {
+#ifdef _KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((mblk_t *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_ABS:
+                       k = pc->k;
+                       if (k + sizeof(short int) > buflen) {
+#ifdef _KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((mblk_t *)p, k, &merr);
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_ABS:
+                       k = pc->k;
+                       if (k >= buflen) {
+#ifdef _KERNEL
+                               register mblk_t *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (mblk_t *)p;
+                               MINDEX(len, m, k);
+                               A = m->b_rptr[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_LEN:
+                       A = wirelen;
+                       continue;
+
+               case BPF_LDX|BPF_W|BPF_LEN:
+                       X = wirelen;
+                       continue;
+
+               case BPF_LD|BPF_W|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(int) > buflen) {
+#ifdef _KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xword((mblk_t *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_LONG(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_H|BPF_IND:
+                       k = X + pc->k;
+                       if (k + sizeof(short int) > buflen) {
+#ifdef _KERNEL
+                               int merr;
+
+                               if (buflen != 0)
+                                       return 0;
+                               A = m_xhalf((mblk_t *)p, k, &merr);
+                               if (merr != 0)
+                                       return 0;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = EXTRACT_SHORT(&p[k]);
+                       continue;
+
+               case BPF_LD|BPF_B|BPF_IND:
+                       k = X + pc->k;
+                       if (k >= buflen) {
+#ifdef _KERNEL
+                               register mblk_t *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (mblk_t *)p;
+                               MINDEX(len, m, k);
+                               A = m->b_rptr[k];
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       A = p[k];
+                       continue;
+
+               case BPF_LDX|BPF_MSH|BPF_B:
+                       k = pc->k;
+                       if (k >= buflen) {
+#ifdef _KERNEL
+                               register mblk_t *m;
+                               register int len;
+
+                               if (buflen != 0)
+                                       return 0;
+                               m = (mblk_t *)p;
+                               MINDEX(len, m, k);
+                               X = (m->b_rptr[k] & 0xf) << 2;
+                               continue;
+#else
+                               return 0;
+#endif
+                       }
+                       X = (p[pc->k] & 0xf) << 2;
+                       continue;
+
+               case BPF_LD|BPF_IMM:
+                       A = pc->k;
+                       continue;
+
+               case BPF_LDX|BPF_IMM:
+                       X = pc->k;
+                       continue;
+
+               case BPF_LD|BPF_MEM:
+                       A = mem[pc->k];
+                       continue;
+                       
+               case BPF_LDX|BPF_MEM:
+                       X = mem[pc->k];
+                       continue;
+
+               case BPF_ST:
+                       mem[pc->k] = A;
+                       continue;
+
+               case BPF_STX:
+                       mem[pc->k] = X;
+                       continue;
+
+               case BPF_JMP|BPF_JA:
+                       pc += pc->k;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_K:
+                       pc += (A > pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_K:
+                       pc += (A >= pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_K:
+                       pc += (A == pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_K:
+                       pc += (A & pc->k) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGT|BPF_X:
+                       pc += (A > X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JGE|BPF_X:
+                       pc += (A >= X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JEQ|BPF_X:
+                       pc += (A == X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_JMP|BPF_JSET|BPF_X:
+                       pc += (A & X) ? pc->jt : pc->jf;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_X:
+                       A += X;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_X:
+                       A -= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_X:
+                       A *= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_X:
+                       if (X == 0)
+                               return 0;
+                       A /= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_X:
+                       A &= X;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_X:
+                       A |= X;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_X:
+                       A <<= X;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_X:
+                       A >>= X;
+                       continue;
+
+               case BPF_ALU|BPF_ADD|BPF_K:
+                       A += pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_SUB|BPF_K:
+                       A -= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_MUL|BPF_K:
+                       A *= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_DIV|BPF_K:
+                       A /= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_AND|BPF_K:
+                       A &= pc->k;
+                       continue;
+                       
+               case BPF_ALU|BPF_OR|BPF_K:
+                       A |= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_LSH|BPF_K:
+                       A <<= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_RSH|BPF_K:
+                       A >>= pc->k;
+                       continue;
+
+               case BPF_ALU|BPF_NEG:
+                       A = -A;
+                       continue;
+
+               case BPF_MISC|BPF_TAX:
+                       X = A;
+                       continue;
+
+               case BPF_MISC|BPF_TXA:
+                       A = X;
+                       continue;
+               }
+       }
+}
+
+#ifdef _KERNEL
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code.  The code must terminate with either an accept or reject. 
+ * 'valid' is an array for use by the routine (it must be at least
+ * 'len' bytes long).  
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(f, len)
+       struct bpf_insn *f;
+       int len;
+{
+       register int i;
+       register struct bpf_insn *p;
+
+       for (i = 0; i < len; ++i) {
+               /*
+                * Check that that jumps are forward, and within 
+                * the code block.
+                */
+               p = &f[i];
+               if (BPF_CLASS(p->code) == BPF_JMP) {
+                       register int from = i + 1;
+
+                       if (BPF_OP(p->code) == BPF_JA) {
+                               if (from + p->k >= len)
+                                       return 0;
+                       }
+                       else if (from + p->jt >= len || from + p->jf >= len)
+                               return 0;
+               }
+               /*
+                * Check that memory operations use valid addresses.
+                */
+               if ((BPF_CLASS(p->code) == BPF_ST ||
+                    (BPF_CLASS(p->code) == BPF_LD && 
+                     (p->code & 0xe0) == BPF_MEM)) &&
+                   (p->k >= BPF_MEMWORDS || p->k < 0))
+                       return 0;
+               /*
+                * Check for constant division by 0.
+                */
+               if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+                       return 0;
+       }
+       return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
+#endif
index 0000cb147ac319d7500dd48da87543742ceafd7e..97c40ddef5e407a28ee61901f99cb2a8ae62fe7f 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp.c,v 1.3 1996/01/01 22:48:39 paulus Exp $
+ * $Id: ppp.c,v 1.4 1996/04/04 02:45:29 paulus Exp $
  */
 
 /*
@@ -58,6 +58,7 @@
 #endif /* SVR4 */
 #include <net/ppp_defs.h>
 #include <net/pppio.h>
+#include <net/bpf.h>
 #include "ppp_mod.h"
 
 #ifdef __STDC__
@@ -106,6 +107,8 @@ typedef struct upperstr {
     struct pppstat stats;      /* statistics */
     time_t last_sent;          /* time last NP packet sent */
     time_t last_recv;          /* time last NP packet rcvd */
+    struct bpf_program active_f;/* filter for active packets */
+    struct bpf_program pass_f; /* filter for packets to pass */
 #ifdef SOL2
     kstat_t *kstats;           /* stats for netstat */
 #endif /* SOL2 */
@@ -378,6 +381,15 @@ pppclose(q, flag)
        kstat_delete(up->kstats);
 #endif
 
+    if (up->active_f.bf_insns) {
+       kmem_free(up->active_f.bf_insns, up->active_f.bf_len);
+       up->active_f.bf_insns = 0;
+    }
+    if (up->pass_f.bf_insns) {
+       kmem_free(up->pass_f.bf_insns, up->pass_f.bf_len);
+       up->pass_f.bf_insns = 0;
+    }
+
     q->q_ptr = NULL;
     WR(q)->q_ptr = NULL;
 
@@ -415,6 +427,9 @@ pppuwput(q, mp)
     int error, n, sap;
     mblk_t *mq;
     struct ppp_idle *pip;
+    int len;
+    struct bpf_insn *ip;
+    struct bpf_program *dest;
 
     us = (upperstr_t *) q->q_ptr;
     switch (mp->b_datap->db_type) {
@@ -439,8 +454,10 @@ pppuwput(q, mp)
            break;
        }
 #ifdef NO_DLPI
-       if ((us->flags & US_CONTROL) == 0)
-           us->ppa->last_sent = time;
+       if (!pass_packet(us->ppa, mp, 1)) {
+           freemsg(mp);
+           break;
+       }
 #endif
        if (!send_data(mp, us))
            putq(q, mp);
@@ -652,6 +669,34 @@ pppuwput(q, mp)
            error = 0;
            break;
 
+       case PPPIO_PASSFILT:
+       case PPPIO_ACTIVEFILT:
+           if ((us->flags & US_CONTROL) == 0)
+               break;
+           len = iop->ioc_count;
+           if (len > BPF_MAXINSNS * sizeof(struct bpf_insn)
+               || len % sizeof(struct bpf_insn) != 0)
+               break;
+           if (len > 0) {
+               if (!bpf_validate((struct bpf_insn *) mp->b_cont->b_rptr,
+                                 len / sizeof(struct bpf_insn)))
+                   break;
+               ip = (struct bpf_insn *) ALLOC_NOSLEEP(len);
+               if (ip == 0) {
+                   error = ENOSR;
+                   break;
+               }
+               bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)ip, len);
+           } else
+               ip = 0;
+           dest = iop->ioc_cmd == PPPIO_ACTIVEFILT?
+               &us->active_f: &us->pass_f;
+           if (dest->bf_insns != 0)
+               kmem_free((caddr_t) dest->bf_insns, dest->bf_len);
+           dest->bf_len = len;
+           dest->bf_insns = ip;
+           break;
+
 #ifdef LACHTCP
        case SIOCSIFNAME:
            printf("SIOCSIFNAME\n");
@@ -960,7 +1005,6 @@ dlpi_request(q, mp, us)
            DPRINT2("dlpi data too large (%d > %d)\n", len, ppa->mtu);
            break;
        }
-       ppa->last_sent = time;
        /* this assumes PPP_HDRLEN <= sizeof(dl_unitdata_req_t) */
        if (mp->b_datap->db_ref > 1) {
            np = allocb(PPP_HDRLEN, BPRI_HI);
@@ -979,8 +1023,12 @@ dlpi_request(q, mp, us)
        mp->b_rptr[1] = PPP_UI;
        mp->b_rptr[2] = us->sap >> 8;
        mp->b_rptr[3] = us->sap;
-       if (!send_data(mp, us))
-           putq(q, mp);
+       if (!pass_packet(ppa, mp, 1))
+           freemsg(mp);
+       else {
+           if (!send_data(mp, us))
+               putq(q, mp);
+       }
        return;
 
 #if DL_CURRENT_VERSION >= 2
@@ -1071,6 +1119,33 @@ dlpi_ok(q, prim)
 }
 #endif /* NO_DLPI */
 
+static int
+pass_packet(ppa, mp, outbound)
+    upperstr_t *ppa;
+    mblk_t *mp;
+    int outbound;
+{
+    int len, adr, pass;
+
+    if (PPP_PROTOCOL(mp->b_rptr) >= 0x8000
+       || (ppa->pass_f.bf_insns == 0 && ppa->active_f.bf_insns == 0))
+       return 1;
+    len = msgdsize(mp);
+    adr = *mp->b_rptr;
+    *mp->b_rptr = outbound;
+    pass = ppa->pass_f.bf_insns == 0
+       || bpf_filter(ppa->pass_f.bf_insns, mp, len, 0);
+    if (pass && (ppa->active_f.bf_insns == 0
+                || bpf_filter(ppa->active_f.bf_insns, mp, len, 0))) {
+       if (outbound)
+           ppa->last_sent = time;
+       else
+           ppa->last_recv = time;
+    }
+    *mp->b_rptr = adr;
+    return pass;
+}
+
 static int
 send_data(mp, us)
     mblk_t *mp;
@@ -1444,6 +1519,10 @@ ppplrput(q, mp)
 #ifdef INCR_IPACKETS
            INCR_IPACKETS(ppa);
 #endif
+           if (!pass_packet(ppa, mp, 0)) {
+               freemsg(mp);
+               break;
+           }
            proto = PPP_PROTOCOL(mp->b_rptr);
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
                /*
@@ -1454,7 +1533,6 @@ ppplrput(q, mp)
                    putq(us->q, mp);
                else
                    putq(q, mp);
-               ppa->last_recv = time;
                break;
            }
        }