add chaos_calmer branch
[15.05/openwrt.git] / package / network / services / ppp / patches / 310-precompile_filter.patch
1 pppd: Implement support for precompiled pcap filters
2
3 This patch implements support for precompiled pcap filters which is useful to
4 support dial-on-demand on memory constrained embedded devices without having
5 to link the full libpcap into pppd to generate the filters during runtime.
6
7 Two new options are introduced; "precompiled-pass-filter" specifies a pre-
8 compiled filter file containing rules to match packets which should be passed,
9 "precompiled-active-filter" specifies a filter file containing rules to match
10 packets which are treated as active.
11
12 Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
13
14 --- a/pppd/Makefile.linux
15 +++ b/pppd/Makefile.linux
16 @@ -50,6 +50,9 @@ MPPE=y
17  # and that the kernel driver support PPP packet filtering.
18  #FILTER=y
19  
20 +# Support for precompiled filters
21 +PRECOMPILED_FILTER=y
22 +
23  # Uncomment the next line to enable multilink PPP (enabled by default)
24  # Linux distributions: Please leave multilink ENABLED in your builds
25  # of pppd!
26 @@ -183,6 +186,14 @@ CFLAGS  += -DPPP_FILTER -I$(STAGING_DIR)
27  endif
28  endif
29  
30 +ifdef PRECOMPILED_FILTER
31 +PPPDSRCS += pcap_pcc.c
32 +HEADERS  += pcap_pcc.h
33 +PPPDOBJS += pcap_pcc.o
34 +LIBS   += $(STAGING_DIR)/usr/lib/libpcap.a
35 +CFLAGS += -DPPP_FILTER -DPPP_PRECOMPILED_FILTER -I$(STAGING_DIR)/usr/include
36 +endif
37 +
38  ifdef HAVE_INET6
39       PPPDSRCS += ipv6cp.c eui64.c
40       HEADERS  += ipv6cp.h eui64.h
41 --- a/pppd/options.c
42 +++ b/pppd/options.c
43 @@ -57,6 +57,7 @@
44  
45  #ifdef PPP_FILTER
46  #include <pcap.h>
47 +#include <pcap-bpf.h>
48  /*
49   * There have been 3 or 4 different names for this in libpcap CVS, but
50   * this seems to be what they have settled on...
51 @@ -165,6 +166,13 @@ static int setlogfile __P((char **));
52  static int loadplugin __P((char **));
53  #endif
54  
55 +#ifdef PPP_PRECOMPILED_FILTER
56 +#include "pcap_pcc.h"
57 +static int setprecompiledpassfilter __P((char **));
58 +static int setprecompiledactivefilter __P((char **));
59 +#undef PPP_FILTER
60 +#endif
61 +
62  #ifdef PPP_FILTER
63  static int setpassfilter __P((char **));
64  static int setactivefilter __P((char **));
65 @@ -344,6 +352,14 @@ option_t general_options[] = {
66        "set filter for active pkts", OPT_PRIO },
67  #endif
68  
69 +#ifdef PPP_PRECOMPILED_FILTER
70 +    { "precompiled-pass-filter", 1, setprecompiledpassfilter,
71 +      "set precompiled filter for packets to pass", OPT_PRIO },
72 +
73 +    { "precompiled-active-filter", 1, setprecompiledactivefilter,
74 +      "set precompiled filter for active pkts", OPT_PRIO },
75 +#endif
76 +
77  #ifdef MAXOCTETS
78      { "maxoctets", o_int, &maxoctets,
79        "Set connection traffic limit",
80 @@ -1493,6 +1509,29 @@ callfile(argv)
81      return ok;
82  }
83  
84 +#ifdef PPP_PRECOMPILED_FILTER
85 +/*
86 + * setprecompiledpassfilter - Set the pass filter for packets using a
87 + * precompiled expression
88 + */
89 +static int
90 +setprecompiledpassfilter(argv)
91 +    char **argv;
92 +{
93 +    return pcap_pre_compiled (*argv, &pass_filter);
94 +}
95 +
96 +/*
97 + * setactivefilter - Set the active filter for packets
98 + */
99 +static int
100 +setprecompiledactivefilter(argv)
101 +    char **argv;
102 +{
103 +    return pcap_pre_compiled (*argv, &active_filter);
104 +}
105 +#endif
106 +
107  #ifdef PPP_FILTER
108  /*
109   * setpassfilter - Set the pass filter for packets
110 --- /dev/null
111 +++ b/pppd/pcap_pcc.c
112 @@ -0,0 +1,74 @@
113 +#include <pcap.h>
114 +#include <pcap-bpf.h>
115 +#include <stdio.h>
116 +#include <stdlib.h>
117 +#include <string.h>
118 +#include <errno.h>
119 +#include "pppd.h"
120 +
121 +int pcap_pre_compiled (char * fname, struct bpf_program *p)
122 +{
123 +    char buf[128];
124 +    int line = 0, size = 0, index=0, ret=1;
125 +    FILE *f = fopen (fname, "r");
126 +    if (!f)
127 +    {
128 +       option_error("error opening precompiled active-filter '%s': %s",
129 +                    fname, strerror (errno));
130 +       return 0;
131 +    }
132 +    while (fgets (buf, 127, f))
133 +    {
134 +       line++;
135 +       if (*buf == '#')
136 +           continue;
137 +       if (size)
138 +       {
139 +           /*
140 +             struct bpf_insn {
141 +             u_short   code;
142 +             u_char    jt;
143 +             u_char    jf;
144 +             bpf_int32 k;
145 +             }
146 +           */
147 +           struct bpf_insn * insn = & p->bf_insns[index];
148 +           unsigned code, jt, jf, k;
149 +           if (sscanf (buf, "%u %u %u %u", &code, &jt, &jf, &k) != 4)
150 +           {
151 +               goto err;
152 +           }
153 +           insn->code = code;
154 +           insn->jt = jt;
155 +           insn->jf = jf;
156 +           insn->k  = k;
157 +           index++;
158 +       }
159 +       else
160 +       {
161 +           if (sscanf (buf, "%u", &size) != 1)
162 +           {
163 +               goto err;
164 +           }
165 +           p->bf_len = size;
166 +           p->bf_insns = (struct bpf_insn *) 
167 +               malloc (size * sizeof (struct bpf_insn));
168 +       }
169 +    } 
170 +    if (size != index)
171 +    {
172 +       option_error("error in precompiled active-filter,"
173 +                    " expected %d expressions, got %dn",
174 +                    size, index);
175 +       ret = 0;
176 +    }
177 +    fclose(f);
178 +    return ret;
179 +
180 +err:
181 +  option_error("error in precompiled active-filter"
182 +              " expression line %s:%d (wrong size)\n", 
183 +              fname, line);
184 +  fclose (f);
185 +  return 0;
186 +}
187 --- /dev/null
188 +++ b/pppd/pcap_pcc.h
189 @@ -0,0 +1,7 @@
190 +#ifndef PCAP_PCC_H
191 +#define PCAP_PCC_H
192 +
193 +#include <pcap.h>
194 +
195 +int pcap_pre_compiled (char * fname, struct bpf_program *p);
196 +#endif /* PCAP_PCC_H */