From 6bb334c1e3a2df28539aaaa0bd88f4876b2fc561 Mon Sep 17 00:00:00 2001 From: nbd Date: Sat, 18 Mar 2006 17:27:20 +0000 Subject: [PATCH] precompile ppp active filter (reduces libpcap overhead to only a few k), enable by default to support proper demand dialling, fixes #307 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@3401 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- openwrt/package/ppp/Config.in | 5 +- openwrt/package/ppp/Makefile | 8 +- openwrt/package/ppp/files/etc/ppp/filter | 23 ++ openwrt/package/ppp/files/ifup.pppoa | 1 + openwrt/package/ppp/files/ifup.pppoe | 1 + .../ppp/patches/310-precompiled_filter.patch | 231 ++++++++++++++++++ openwrt/package/ppp/utils/pfc.c | 51 ++++ openwrt/package/pptp/files/ifup.pptp | 1 + 8 files changed, 316 insertions(+), 5 deletions(-) create mode 100644 openwrt/package/ppp/files/etc/ppp/filter create mode 100644 openwrt/package/ppp/patches/310-precompiled_filter.patch create mode 100644 openwrt/package/ppp/utils/pfc.c diff --git a/openwrt/package/ppp/Config.in b/openwrt/package/ppp/Config.in index 0dda3cc83..21139adf7 100644 --- a/openwrt/package/ppp/Config.in +++ b/openwrt/package/ppp/Config.in @@ -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" diff --git a/openwrt/package/ppp/Makefile b/openwrt/package/ppp/Makefile index d98d7e5cb..e63fa4cf5 100644 --- a/openwrt/package/ppp/Makefile +++ b/openwrt/package/ppp/Makefile @@ -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/openwrt/package/ppp/files/etc/ppp/filter b/openwrt/package/ppp/files/etc/ppp/filter new file mode 100644 index 000000000..ec72a81a0 --- /dev/null +++ b/openwrt/package/ppp/files/etc/ppp/filter @@ -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 diff --git a/openwrt/package/ppp/files/ifup.pppoa b/openwrt/package/ppp/files/ifup.pppoa index 2ae6019c5..baea25ebf 100644 --- a/openwrt/package/ppp/files/ifup.pppoa +++ b/openwrt/package/ppp/files/ifup.pppoa @@ -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 diff --git a/openwrt/package/ppp/files/ifup.pppoe b/openwrt/package/ppp/files/ifup.pppoe index d4a79aedd..1f9cd739c 100644 --- a/openwrt/package/ppp/files/ifup.pppoe +++ b/openwrt/package/ppp/files/ifup.pppoe @@ -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/openwrt/package/ppp/patches/310-precompiled_filter.patch b/openwrt/package/ppp/patches/310-precompiled_filter.patch new file mode 100644 index 000000000..df9452c37 --- /dev/null +++ b/openwrt/package/ppp/patches/310-precompiled_filter.patch @@ -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 +-/* +- * 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 + #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 ++#include ++#include ++#include ++#include ++#include ++#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 ++ ++int pcap_pre_compiled (char * fname, struct bpf_program *p); ++#endif /* PCAP_PCC_H */ diff --git a/openwrt/package/ppp/utils/pfc.c b/openwrt/package/ppp/utils/pfc.c new file mode 100644 index 000000000..5476be170 --- /dev/null +++ b/openwrt/package/ppp/utils/pfc.c @@ -0,0 +1,51 @@ +/* + * Taken from fli4l 3.0 + * Make sure you compile it against the same libpcap version used in OpenWrt + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +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 ] 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; +} diff --git a/openwrt/package/pptp/files/ifup.pptp b/openwrt/package/pptp/files/ifup.pptp index fe04d9784..9b1ac07c2 100644 --- a/openwrt/package/pptp/files/ifup.pptp +++ b/openwrt/package/pptp/files/ifup.pptp @@ -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