precompile ppp active filter (reduces libpcap overhead to only a few k), enable by...
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 18 Mar 2006 17:27:20 +0000 (17:27 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 18 Mar 2006 17:27:20 +0000 (17:27 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@3401 3c298f89-4303-0410-b956-a3cf2f4a3e73

package/ppp/Config.in
package/ppp/Makefile
package/ppp/files/etc/ppp/filter [new file with mode: 0644]
package/ppp/files/ifup.pppoa
package/ppp/files/ifup.pppoe
package/ppp/patches/310-precompiled_filter.patch [new file with mode: 0644]
package/ppp/utils/pfc.c [new file with mode: 0644]
package/pptp/files/ifup.pptp

index 0dda3cc..21139ad 100644 (file)
@@ -8,10 +8,9 @@ config BR2_PACKAGE_PPP
        select BR2_PACKAGE_KMOD_PPP
 
 config BR2_PACKAGE_PPP_WITH_FILTER
-        prompt "Enable filter support"
+       prompt "Enable filter support"
        bool
-       default n
-       depends BR2_PACKAGE_LIBPCAP
+       default y
 
 config BR2_PACKAGE_PPP_MOD_PPPOA
        prompt   "ppp-mod-pppoa................... PPPoA (PPP over ATM) plugin"
index d98d7e5..e63fa4c 100644 (file)
@@ -41,8 +41,7 @@ $(eval $(call PKG_mod_template,PPP_MOD_RADIUS,radius))
 
 PKG_DEPEND:="kmod-ppp"
 ifeq ($(BR2_PACKAGE_PPP_WITH_FILTER),y)
-ENABLE_FILTER:="FILTER=1"
-PKG_DEPEND += ", libpcap"
+ENABLE_FILTER:="PRECOMPILED_FILTER=1"
 endif
 
 $(PKG_BUILD_DIR)/.configured:
@@ -85,11 +84,16 @@ $(PKG_BUILD_DIR)/.built:
                all install
        touch $@
 
+ifeq ($(BR2_PACKAGE_PPP_WITH_FILTER),y)
+INSTALL_FILTER=install -m0644 ./files/etc/ppp/filter $(IDIR_PPP)/etc/ppp/
+endif
+
 $(IPKG_PPP):
        install -d -m0755 $(IDIR_PPP)/etc/ppp
        ln -sf /tmp/resolv.conf $(IDIR_PPP)/etc/ppp/resolv.conf
        install -m0600 ./files/etc/ppp/chap-secrets $(IDIR_PPP)/etc/ppp/
        install -m0644 ./files/etc/ppp/options $(IDIR_PPP)/etc/ppp/
+       $(INSTALL_FILTER)
        install -m0755 ./files/etc/ppp/ip-up $(IDIR_PPP)/etc/ppp/
        install -m0755 ./files/etc/ppp/ip-down $(IDIR_PPP)/etc/ppp/
        install -d -m0755 $(IDIR_PPP)/usr/sbin
diff --git a/package/ppp/files/etc/ppp/filter b/package/ppp/files/etc/ppp/filter
new file mode 100644 (file)
index 0000000..ec72a81
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Expression: outbound and not icmp[0] != 8 and not tcp[13] & 4 != 0
+#
+19
+48 0 0 0
+21 0 16 1
+40 0 0 2
+21 0 13 33
+48 0 0 13
+21 0 5 1
+40 0 0 10
+69 9 0 8191
+177 0 0 4
+80 0 0 4
+21 6 7 8
+21 0 5 6
+40 0 0 10
+69 3 0 8191
+177 0 0 4
+80 0 0 17
+69 1 0 4
+6 0 0 4
+6 0 0 0
index 2ae6019..baea25e 100644 (file)
@@ -25,6 +25,7 @@ case "$DEMAND" in
        on|1|enabled)
                DEMAND=$(nvram get ppp_idletime)
                DEMAND=${IDLETIME:+demand idle $IDLETIME}
+               [ -f /etc/ppp/filter ] && DEMAND=${DEMAND:+precompiled-active-filter /etc/ppp/filter $DEMAND}
        ;;
        *) DEMAND="persist";;
 esac
index d4a79ae..1f9cd73 100644 (file)
@@ -24,6 +24,7 @@ case "$DEMAND" in
        on|1|enabled)
                DEMAND=$(nvram get ppp_idletime)
                DEMAND=${IDLETIME:+demand idle $IDLETIME}
+               [ -f /etc/ppp/filter ] && DEMAND=${DEMAND:+precompiled-active-filter /etc/ppp/filter $DEMAND}
        ;;
        *) DEMAND="persist";;
 esac
diff --git a/package/ppp/patches/310-precompiled_filter.patch b/package/ppp/patches/310-precompiled_filter.patch
new file mode 100644 (file)
index 0000000..df9452c
--- /dev/null
@@ -0,0 +1,231 @@
+diff -urN ppp.old/pppd/Makefile.linux ppp.dev/pppd/Makefile.linux
+--- ppp.old/pppd/Makefile.linux        2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/Makefile.linux        2006-03-18 16:52:01.000000000 +0100
+@@ -50,6 +50,9 @@
+ # and that the kernel driver support PPP packet filtering.
+ #FILTER=y
++# Support for precompiled filters
++PRECOMPILED_FILTER=y
++
+ # Uncomment the next line to enable multilink PPP (enabled by default)
+ # Linux distributions: Please leave multilink ENABLED in your builds
+ # of pppd!
+@@ -177,6 +180,14 @@
+ endif
+ endif
++ifdef PRECOMPILED_FILTER
++PPPDSRCS += pcap_pcc.c
++HEADERS  += pcap_pcc.h
++PPPDOBJS += pcap_pcc.o
++LIBS  += $(STAGING_DIR)/usr/lib/libpcap.a
++CFLAGS        += -DPPP_FILTER -DPPP_PRECOMPILED_FILTER -I$(STAGING_DIR)/usr/include
++endif
++
+ ifdef HAVE_INET6
+      PPPDSRCS += ipv6cp.c eui64.c
+      HEADERS  += ipv6cp.h eui64.h
+diff -urN ppp.old/pppd/demand.c ppp.dev/pppd/demand.c
+--- ppp.old/pppd/demand.c      2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/demand.c      2006-03-18 18:09:16.000000000 +0100
+@@ -438,12 +438,14 @@
+       return 0;
+     proto = PPP_PROTOCOL(p);
+ #ifdef PPP_FILTER
++      *p = 1; /* set outbound for the filter rule */
+     if (pass_filter.bf_len != 0
+       && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
+       return 0;
+     if (active_filter.bf_len != 0
+       && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
+       return 0;
++      *p = 0xff; /* restore original ppp header */
+ #endif
+     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+       if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
+diff -urN ppp.old/pppd/options.c ppp.dev/pppd/options.c
+--- ppp.old/pppd/options.c     2006-03-18 15:58:00.000000000 +0100
++++ ppp.dev/pppd/options.c     2006-03-18 18:05:58.000000000 +0100
+@@ -57,14 +57,7 @@
+ #ifdef PPP_FILTER
+ #include <pcap.h>
+-/*
+- * DLT_PPP_WITH_DIRECTION is in current libpcap cvs, and should be in
+- * libpcap-0.8.4.  Until that is released, use DLT_PPP - but that means
+- * we lose the inbound and outbound qualifiers.
+- */
+-#ifndef DLT_PPP_WITH_DIRECTION
+-#define DLT_PPP_WITH_DIRECTION        DLT_PPP
+-#endif
++#include <pcap-bpf.h>
+ #endif
+ #include "pppd.h"
+@@ -155,6 +148,13 @@
+ static int loadplugin __P((char **));
+ #endif
++#ifdef PPP_PRECOMPILED_FILTER
++#include "pcap_pcc.h"
++static int setprecompiledpassfilter __P((char **));
++static int setprecompiledactivefilter __P((char **));
++#undef PPP_FILTER
++#endif
++
+ #ifdef PPP_FILTER
+ static int setpassfilter __P((char **));
+ static int setactivefilter __P((char **));
+@@ -312,6 +312,14 @@
+       "set filter for active pkts", OPT_PRIO },
+ #endif
++#ifdef PPP_PRECOMPILED_FILTER
++    { "precompiled-pass-filter", 1, setprecompiledpassfilter,
++      "set precompiled filter for packets to pass", OPT_PRIO },
++
++    { "precompiled-active-filter", 1, setprecompiledactivefilter,
++      "set precompiled filter for active pkts", OPT_PRIO },
++#endif
++
+ #ifdef MAXOCTETS
+     { "maxoctets", o_int, &maxoctets,
+       "Set connection traffic limit",
+@@ -1447,6 +1455,29 @@
+     return ok;
+ }
++#ifdef PPP_PRECOMPILED_FILTER
++/*
++ * setprecompiledpassfilter - Set the pass filter for packets using a
++ * precompiled expression
++ */
++static int
++setprecompiledpassfilter(argv)
++    char **argv;
++{
++    return pcap_pre_compiled (*argv, &pass_filter);
++}
++
++/*
++ * setactivefilter - Set the active filter for packets
++ */
++static int
++setprecompiledactivefilter(argv)
++    char **argv;
++{
++    return pcap_pre_compiled (*argv, &active_filter);
++}
++#endif
++
+ #ifdef PPP_FILTER
+ /*
+  * setpassfilter - Set the pass filter for packets
+@@ -1458,7 +1489,7 @@
+     pcap_t *pc;
+     int ret = 0;
+-    pc = pcap_open_dead(DLT_PPP_WITH_DIRECTION, 65535);
++    pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+     if (pcap_compile(pc, &pass_filter, *argv, 1, netmask) == -1) {
+       option_error("error in pass-filter expression: %s\n",
+                    pcap_geterr(pc));
+@@ -1479,7 +1510,7 @@
+     pcap_t *pc;
+     int ret = 0;
+-    pc = pcap_open_dead(DLT_PPP_WITH_DIRECTION, 65535);
++    pc = pcap_open_dead(DLT_PPP_PPPD, 65535);
+     if (pcap_compile(pc, &active_filter, *argv, 1, netmask) == -1) {
+       option_error("error in active-filter expression: %s\n",
+                    pcap_geterr(pc));
+diff -urN ppp.old/pppd/pcap_pcc.c ppp.dev/pppd/pcap_pcc.c
+--- ppp.old/pppd/pcap_pcc.c    1970-01-01 01:00:00.000000000 +0100
++++ ppp.dev/pppd/pcap_pcc.c    2006-03-18 16:51:31.000000000 +0100
+@@ -0,0 +1,74 @@
++#include <pcap.h>
++#include <pcap-bpf.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include "pppd.h"
++
++int pcap_pre_compiled (char * fname, struct bpf_program *p)
++{
++    char buf[128];
++    int line = 0, size = 0, index=0, ret=1;
++    FILE *f = fopen (fname, "r");
++    if (!f)
++    {
++       option_error("error opening precompiled active-filter '%s': %s",
++                    fname, strerror (errno));
++       return 0;
++    }
++    while (fgets (buf, 127, f))
++    {
++       line++;
++       if (*buf == '#')
++           continue;
++       if (size)
++       {
++           /*
++             struct bpf_insn {
++             u_short   code;
++             u_char    jt;
++             u_char    jf;
++             bpf_int32 k;
++             }
++           */
++           struct bpf_insn * insn = & p->bf_insns[index];
++           unsigned code, jt, jf, k;
++           if (sscanf (buf, "%u %u %u %u", &code, &jt, &jf, &k) != 4)
++           {
++               goto err;
++           }
++           insn->code = code;
++           insn->jt = jt;
++           insn->jf = jf;
++           insn->k  = k;
++           index++;
++       }
++       else
++       {
++           if (sscanf (buf, "%u", &size) != 1)
++           {
++               goto err;
++           }
++           p->bf_len = size;
++           p->bf_insns = (struct bpf_insn *) 
++               malloc (size * sizeof (struct bpf_insn));
++       }
++    } 
++    if (size != index)
++    {
++       option_error("error in precompiled active-filter,"
++                    " expected %d expressions, got %dn",
++                    size, index);
++       ret = 0;
++    }
++    fclose(f);
++    return ret;
++
++err:
++  option_error("error in precompiled active-filter"
++              " expression line %s:%d (wrong size)\n", 
++              fname, line);
++  fclose (f);
++  return 0;
++}
+diff -urN ppp.old/pppd/pcap_pcc.h ppp.dev/pppd/pcap_pcc.h
+--- ppp.old/pppd/pcap_pcc.h    1970-01-01 01:00:00.000000000 +0100
++++ ppp.dev/pppd/pcap_pcc.h    2006-03-18 15:59:14.000000000 +0100
+@@ -0,0 +1,7 @@
++#ifndef PCAP_PCC_H
++#define PCAP_PCC_H
++
++#include <pcap.h>
++
++int pcap_pre_compiled (char * fname, struct bpf_program *p);
++#endif /* PCAP_PCC_H */
diff --git a/package/ppp/utils/pfc.c b/package/ppp/utils/pfc.c
new file mode 100644 (file)
index 0000000..5476be1
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+ * Taken from fli4l 3.0
+ * Make sure you compile it against the same libpcap version used in OpenWrt
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <string.h>
+
+#include <linux/types.h>
+#include <linux/ppp_defs.h>
+
+#include <pcap.h>
+#include <pcap-bpf.h>
+
+int main (int argc, char ** argv)
+{
+    pcap_t  *pc; /* Fake struct pcap so we can compile expr */
+    struct  bpf_program filter; /* Filter program for link-active pkts */
+    u_int32_t netmask=0;
+
+    int dflag = 3;
+    if (argc == 4)
+    {
+       if (!strcmp (argv[1], "-d"))
+       {
+           dflag = atoi (argv[2]);
+           argv += 2;
+           argc -=2;
+       }
+    }
+    if (argc != 2)
+    {
+       printf ("usage; %s [ -d <debug_level> ] expression\n", argv[0]);
+       return 1;
+    }
+
+    pc = pcap_open_dead(DLT_PPP_PPPD, PPP_HDRLEN);
+    if (pcap_compile(pc, &filter, argv[1], 1, netmask) == 0)
+    {
+       printf ("#\n# Expression: %s\n#\n", argv[1]);
+       bpf_dump (&filter, dflag);
+       return 0;
+    }
+    else
+    {
+       printf("error in active-filter expression: %s\n", pcap_geterr(pc));
+    }
+    return 1;
+}
index fe04d97..9b1ac07 100644 (file)
@@ -23,6 +23,7 @@ case "$DEMAND" in
        on|1|enabled)
                DEMAND=$(nvram get ppp_idletime)
                DEMAND=${IDLETIME:+demand idle $IDLETIME}
+               [ -f /etc/ppp/filter ] && DEMAND=${DEMAND:+precompiled-active-filter /etc/ppp/filter $DEMAND}
        ;;
        *) DEMAND="persist";;
 esac