]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/bpf/bpf_filter/bpf_test.c
Merge ath_hal 0.10.5.10 to head.
[FreeBSD/FreeBSD.git] / tools / regression / bpf / bpf_filter / bpf_test.c
1 /*-
2  * Copyright (C) 2008 Jung-uk Kim <jkim@FreeBSD.org>. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include <sys/types.h>
34
35 #include <net/bpf.h>
36
37 #include BPF_TEST_H
38
39 #define PASSED          0
40 #define FAILED          1
41 #define FATAL           -1
42
43 #ifndef LOG_LEVEL
44 #define LOG_LEVEL       1
45 #endif
46
47 #ifdef BPF_BENCHMARK
48 #define BPF_NRUNS       10000000
49 #else
50 #define BPF_NRUNS       1
51 #endif
52
53 static void     sig_handler(int);
54
55 static int      nins = sizeof(pc) / sizeof(pc[0]);
56 static int      verbose = LOG_LEVEL;
57
58 #ifdef BPF_JIT_COMPILER
59
60 #include <net/bpf_jitter.h>
61
62 static u_int
63 bpf_compile_and_filter(void)
64 {
65         bpf_jit_filter  *filter;
66         u_int           i, ret;
67
68         /* Compile the BPF filter program and generate native code. */
69         if ((filter = bpf_jitter(pc, nins)) == NULL) {
70                 if (verbose > 1)
71                         printf("Failed to allocate memory:\t");
72                 if (verbose > 0)
73                         printf("FATAL\n");
74                 exit(FATAL);
75         }
76
77         for (i = 0; i < BPF_NRUNS; i++)
78                 ret = (*(filter->func))(pkt, wirelen, buflen);
79
80         bpf_destroy_jit_filter(filter);
81
82         return (ret);
83 }
84
85 #else
86
87 u_int   bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
88
89 #endif
90
91 #ifdef BPF_VALIDATE
92 /*
93  * XXX Copied from sys/net/bpf_filter.c and modified.
94  *
95  * Return true if the 'fcode' is a valid filter program.
96  * The constraints are that each jump be forward and to a valid
97  * code.  The code must terminate with either an accept or reject.
98  *
99  * The kernel needs to be able to verify an application's filter code.
100  * Otherwise, a bogus program could easily crash the system.
101  */
102 static int
103 bpf_validate(const struct bpf_insn *f, int len)
104 {
105         register int i;
106         register const struct bpf_insn *p;
107
108         /* Do not accept negative length filter. */
109         if (len < 0)
110                 return (0);
111
112         /* An empty filter means accept all. */
113         if (len == 0)
114                 return (1);
115
116         for (i = 0; i < len; ++i) {
117                 /*
118                  * Check that that jumps are forward, and within
119                  * the code block.
120                  */
121                 p = &f[i];
122 #if BPF_VALIDATE > 1
123                 /*
124                  * XXX JK: Illegal instructions must be checked here.
125                  */
126                 switch (p->code) {
127                 default:
128                         return (0);
129                 case BPF_RET|BPF_K:
130                 case BPF_RET|BPF_A:
131                 case BPF_LD|BPF_W|BPF_ABS:
132                 case BPF_LD|BPF_H|BPF_ABS:
133                 case BPF_LD|BPF_B|BPF_ABS:
134                 case BPF_LD|BPF_W|BPF_LEN:
135                 case BPF_LDX|BPF_W|BPF_LEN:
136                 case BPF_LD|BPF_W|BPF_IND:
137                 case BPF_LD|BPF_H|BPF_IND:
138                 case BPF_LD|BPF_B|BPF_IND:
139                 case BPF_LDX|BPF_MSH|BPF_B:
140                 case BPF_LD|BPF_IMM:
141                 case BPF_LDX|BPF_IMM:
142                 case BPF_LD|BPF_MEM:
143                 case BPF_LDX|BPF_MEM:
144                 case BPF_ST:
145                 case BPF_STX:
146                 case BPF_JMP|BPF_JA:
147                 case BPF_JMP|BPF_JGT|BPF_K:
148                 case BPF_JMP|BPF_JGE|BPF_K:
149                 case BPF_JMP|BPF_JEQ|BPF_K:
150                 case BPF_JMP|BPF_JSET|BPF_K:
151                 case BPF_JMP|BPF_JGT|BPF_X:
152                 case BPF_JMP|BPF_JGE|BPF_X:
153                 case BPF_JMP|BPF_JEQ|BPF_X:
154                 case BPF_JMP|BPF_JSET|BPF_X:
155                 case BPF_ALU|BPF_ADD|BPF_X:
156                 case BPF_ALU|BPF_SUB|BPF_X:
157                 case BPF_ALU|BPF_MUL|BPF_X:
158                 case BPF_ALU|BPF_DIV|BPF_X:
159                 case BPF_ALU|BPF_AND|BPF_X:
160                 case BPF_ALU|BPF_OR|BPF_X:
161                 case BPF_ALU|BPF_LSH|BPF_X:
162                 case BPF_ALU|BPF_RSH|BPF_X:
163                 case BPF_ALU|BPF_ADD|BPF_K:
164                 case BPF_ALU|BPF_SUB|BPF_K:
165                 case BPF_ALU|BPF_MUL|BPF_K:
166                 case BPF_ALU|BPF_DIV|BPF_K:
167                 case BPF_ALU|BPF_AND|BPF_K:
168                 case BPF_ALU|BPF_OR|BPF_K:
169                 case BPF_ALU|BPF_LSH|BPF_K:
170                 case BPF_ALU|BPF_RSH|BPF_K:
171                 case BPF_ALU|BPF_NEG:
172                 case BPF_MISC|BPF_TAX:
173                 case BPF_MISC|BPF_TXA:
174                         break;
175                 }
176 #endif
177                 if (BPF_CLASS(p->code) == BPF_JMP) {
178                         register int from = i + 1;
179
180                         if (BPF_OP(p->code) == BPF_JA) {
181                                 if (from >= len || p->k >= (u_int)len - from)
182                                         return (0);
183                         }
184                         else if (from >= len || p->jt >= len - from ||
185                                  p->jf >= len - from)
186                                 return (0);
187                 }
188                 /*
189                  * Check that memory operations use valid addresses.
190                  */
191                 if ((BPF_CLASS(p->code) == BPF_ST ||
192                     (BPF_CLASS(p->code) == BPF_LD &&
193                     (p->code & 0xe0) == BPF_MEM)) &&
194                     p->k >= BPF_MEMWORDS)
195                         return (0);
196 #if BPF_VALIDATE > 1
197                 /*
198                  * XXX JK: BPF_STX and BPF_LDX|BPF_MEM must be checked.
199                  */
200                 if ((BPF_CLASS(p->code) == BPF_STX ||
201                     (BPF_CLASS(p->code) == BPF_LDX &&
202                     (p->code & 0xe0) == BPF_MEM)) &&
203                     p->k >= BPF_MEMWORDS)
204                         return (0);
205 #endif
206                 /*
207                  * Check for constant division by 0.
208                  */
209                 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
210                         return (0);
211         }
212         return (BPF_CLASS(f[len - 1].code) == BPF_RET);
213 }
214 #endif
215
216 int
217 main(void)
218 {
219 #ifndef BPF_JIT_COMPILER
220         u_int   i;
221 #endif
222         u_int   ret;
223         int     sig;
224 #ifdef BPF_VALIDATE
225         int     valid;
226 #endif
227
228         /* Try to catch all signals */
229         for (sig = SIGHUP; sig <= SIGUSR2; sig++)
230                 signal(sig, sig_handler);
231
232 #ifdef BPF_VALIDATE
233         valid = bpf_validate(pc, nins);
234         if (valid != 0 && invalid != 0) {
235                 if (verbose > 1)
236                         printf("Validated invalid instruction(s):\t");
237                 if (verbose > 0)
238                         printf("FAILED\n");
239                 return (FAILED);
240         } else if (valid == 0 && invalid == 0) {
241                 if (verbose > 1)
242                         printf("Invalidated valid instruction(s):\t");
243                 if (verbose > 0)
244                         printf("FAILED\n");
245                 return (FAILED);
246         } else if (invalid != 0) {
247                 if (verbose > 1)
248                         printf("Expected and invalidated:\t");
249                 if (verbose > 0)
250                         printf("PASSED\n");
251                 return (PASSED);
252         }
253 #endif
254
255 #ifdef BPF_JIT_COMPILER
256         ret = bpf_compile_and_filter();
257 #else
258         for (i = 0; i < BPF_NRUNS; i++)
259                 ret = bpf_filter(nins != 0 ? pc : NULL, pkt, wirelen, buflen);
260 #endif
261         if (ret != expect) {
262                 if (verbose > 1)
263                         printf("Expected 0x%x but got 0x%x:\t", expect, ret);
264                 if (verbose > 0)
265                         printf("FAILED\n");
266                 return (FAILED);
267         }
268         if (verbose > 1)
269                 printf("Expected and got 0x%x:\t", ret);
270         if (verbose > 0)
271                 printf("PASSED\n");
272
273         return (PASSED);
274 }
275
276 static void
277 sig_handler(int sig)
278 {
279
280         if (expect_signal == 0) {
281                 if (verbose > 1)
282                         printf("Received unexpected signal %d:\t", sig);
283                 if (verbose > 0)
284                         printf("FATAL\n");
285                 exit(FATAL);
286         }
287         if (expect_signal != sig) {
288                 if (verbose > 1)
289                         printf("Expected signal %d but got %d:\t",
290                             expect_signal, sig);
291                 if (verbose > 0)
292                         printf("FAILED\n");
293                 exit(FAILED);
294         }
295
296         if (verbose > 1)
297                 printf("Expected and got signal %d:\t", sig);
298         if (verbose > 0)
299                 printf("PASSED\n");
300
301         exit(PASSED);
302 }