You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/package/network/services/ppp/patches/310-precompile_filter.patch

197 lines
5.1 KiB
Diff

pppd: Implement support for precompiled pcap filters
This patch implements support for precompiled pcap filters which is useful to
support dial-on-demand on memory constrained embedded devices without having
to link the full libpcap into pppd to generate the filters during runtime.
Two new options are introduced; "precompiled-pass-filter" specifies a pre-
compiled filter file containing rules to match packets which should be passed,
"precompiled-active-filter" specifies a filter file containing rules to match
packets which are treated as active.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
--- a/pppd/Makefile.linux
+++ b/pppd/Makefile.linux
@@ -50,6 +50,9 @@ MPPE=y
# 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!
@@ -183,6 +186,14 @@ CFLAGS += -DPPP_FILTER -I$(STAGING_DIR)
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
--- a/pppd/options.c
+++ b/pppd/options.c
@@ -57,6 +57,7 @@
#ifdef PPP_FILTER
#include <pcap.h>
+#include <pcap-bpf.h>
/*
* There have been 3 or 4 different names for this in libpcap CVS, but
* this seems to be what they have settled on...
@@ -165,6 +166,13 @@ static int setlogfile __P((char **));
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 **));
@@ -344,6 +352,14 @@ option_t general_options[] = {
"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",
@@ -1493,6 +1509,29 @@ callfile(argv)
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
--- /dev/null
+++ b/pppd/pcap_pcc.c
@@ -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;
+}
--- /dev/null
+++ b/pppd/pcap_pcc.h
@@ -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 */