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 --- 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 +#include /* * 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 +#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; +} --- /dev/null +++ b/pppd/pcap_pcc.h @@ -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 */