trafgen: Don't duplicate copyright/bug report/license string
[netsniff-ng.git] / bpf.c
blob6239af94cffd9b18482df3962b6b41012fd98e33
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009 - 2012 Daniel Borkmann.
4 * Copyright 2009, 2010 Emmanuel Roullit.
5 * Copyright 1990-1996 The Regents of the University of
6 * California. All rights reserved. (3-clause BSD license)
7 * Subject to the GPL, version 2.
8 */
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <arpa/inet.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
17 #include "bpf.h"
18 #include "xmalloc.h"
19 #include "die.h"
20 #include "str.h"
22 #define EXTRACT_SHORT(packet) \
23 ((unsigned short) ntohs(*(unsigned short *) packet))
24 #define EXTRACT_LONG(packet) \
25 (ntohl(*(unsigned long *) packet))
27 #ifndef BPF_MEMWORDS
28 # define BPF_MEMWORDS 16
29 #endif
31 #define BPF_LD_B (BPF_LD | BPF_B)
32 #define BPF_LD_H (BPF_LD | BPF_H)
33 #define BPF_LD_W (BPF_LD | BPF_W)
34 #define BPF_LDX_B (BPF_LDX | BPF_B)
35 #define BPF_LDX_W (BPF_LDX | BPF_W)
36 #define BPF_JMP_JA (BPF_JMP | BPF_JA)
37 #define BPF_JMP_JEQ (BPF_JMP | BPF_JEQ)
38 #define BPF_JMP_JGT (BPF_JMP | BPF_JGT)
39 #define BPF_JMP_JGE (BPF_JMP | BPF_JGE)
40 #define BPF_JMP_JSET (BPF_JMP | BPF_JSET)
41 #define BPF_ALU_ADD (BPF_ALU | BPF_ADD)
42 #define BPF_ALU_SUB (BPF_ALU | BPF_SUB)
43 #define BPF_ALU_MUL (BPF_ALU | BPF_MUL)
44 #define BPF_ALU_DIV (BPF_ALU | BPF_DIV)
45 #define BPF_ALU_MOD (BPF_ALU | BPF_MOD)
46 #define BPF_ALU_NEG (BPF_ALU | BPF_NEG)
47 #define BPF_ALU_AND (BPF_ALU | BPF_AND)
48 #define BPF_ALU_OR (BPF_ALU | BPF_OR)
49 #define BPF_ALU_XOR (BPF_ALU | BPF_XOR)
50 #define BPF_ALU_LSH (BPF_ALU | BPF_LSH)
51 #define BPF_ALU_RSH (BPF_ALU | BPF_RSH)
52 #define BPF_MISC_TAX (BPF_MISC | BPF_TAX)
53 #define BPF_MISC_TXA (BPF_MISC | BPF_TXA)
55 static const char *op_table[] = {
56 [BPF_LD_B] = "ldb",
57 [BPF_LD_H] = "ldh",
58 [BPF_LD_W] = "ld",
59 [BPF_LDX] = "ldx",
60 [BPF_LDX_B] = "ldxb",
61 [BPF_ST] = "st",
62 [BPF_STX] = "stx",
63 [BPF_JMP_JA] = "ja",
64 [BPF_JMP_JEQ] = "jeq",
65 [BPF_JMP_JGT] = "jgt",
66 [BPF_JMP_JGE] = "jge",
67 [BPF_JMP_JSET] = "jset",
68 [BPF_ALU_ADD] = "add",
69 [BPF_ALU_SUB] = "sub",
70 [BPF_ALU_MUL] = "mul",
71 [BPF_ALU_DIV] = "div",
72 [BPF_ALU_MOD] = "mod",
73 [BPF_ALU_NEG] = "neg",
74 [BPF_ALU_AND] = "and",
75 [BPF_ALU_OR] = "or",
76 [BPF_ALU_XOR] = "xor",
77 [BPF_ALU_LSH] = "lsh",
78 [BPF_ALU_RSH] = "rsh",
79 [BPF_RET] = "ret",
80 [BPF_MISC_TAX] = "tax",
81 [BPF_MISC_TXA] = "txa",
84 void bpf_dump_op_table(void)
86 size_t i;
87 for (i = 0; i < array_size(op_table); ++i) {
88 if (op_table[i])
89 printf("%s\n", op_table[i]);
93 static const char *bpf_dump_linux_k(uint32_t k)
95 switch (k) {
96 default:
97 return "[%d]";
98 case SKF_AD_OFF + SKF_AD_PROTOCOL:
99 return "proto";
100 case SKF_AD_OFF + SKF_AD_PKTTYPE:
101 return "type";
102 case SKF_AD_OFF + SKF_AD_IFINDEX:
103 return "ifidx";
104 case SKF_AD_OFF + SKF_AD_NLATTR:
105 return "nla";
106 case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
107 return "nlan";
108 case SKF_AD_OFF + SKF_AD_MARK:
109 return "mark";
110 case SKF_AD_OFF + SKF_AD_QUEUE:
111 return "queue";
112 case SKF_AD_OFF + SKF_AD_HATYPE:
113 return "hatype";
114 case SKF_AD_OFF + SKF_AD_RXHASH:
115 return "rxhash";
116 case SKF_AD_OFF + SKF_AD_CPU:
117 return "cpu";
118 case SKF_AD_OFF + SKF_AD_VLAN_TAG:
119 return "vlant";
120 case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
121 return "vlanp";
122 case SKF_AD_OFF + SKF_AD_PAY_OFFSET:
123 return "poff";
127 static char *__bpf_dump(const struct sock_filter bpf, int n)
129 int v;
130 const char *fmt, *op;
131 static char image[256];
132 char operand[64];
134 v = bpf.k;
135 switch (bpf.code) {
136 default:
137 op = "unimp";
138 fmt = "0x%x";
139 v = bpf.code;
140 break;
141 case BPF_RET | BPF_K:
142 op = op_table[BPF_RET];
143 fmt = "#0x%x";
144 break;
145 case BPF_RET | BPF_A:
146 op = op_table[BPF_RET];
147 fmt = "a";
148 break;
149 case BPF_RET | BPF_X:
150 op = op_table[BPF_RET];
151 fmt = "x";
152 break;
153 case BPF_LD_W | BPF_ABS:
154 op = op_table[BPF_LD_W];
155 fmt = bpf_dump_linux_k(bpf.k);
156 break;
157 case BPF_LD_H | BPF_ABS:
158 op = op_table[BPF_LD_H];
159 fmt = bpf_dump_linux_k(bpf.k);
160 break;
161 case BPF_LD_B | BPF_ABS:
162 op = op_table[BPF_LD_B];
163 fmt = bpf_dump_linux_k(bpf.k);
164 break;
165 case BPF_LD_W | BPF_LEN:
166 op = op_table[BPF_LD_W];
167 fmt = "#len";
168 break;
169 case BPF_LD_W | BPF_IND:
170 op = op_table[BPF_LD_W];
171 fmt = "[x + %d]";
172 break;
173 case BPF_LD_H | BPF_IND:
174 op = op_table[BPF_LD_H];
175 fmt = "[x + %d]";
176 break;
177 case BPF_LD_B | BPF_IND:
178 op = op_table[BPF_LD_B];
179 fmt = "[x + %d]";
180 break;
181 case BPF_LD | BPF_IMM:
182 op = op_table[BPF_LD_W];
183 fmt = "#0x%x";
184 break;
185 case BPF_LDX | BPF_IMM:
186 op = op_table[BPF_LDX];
187 fmt = "#0x%x";
188 break;
189 case BPF_LDX_B | BPF_MSH:
190 op = op_table[BPF_LDX_B];
191 fmt = "4*([%d]&0xf)";
192 break;
193 case BPF_LD | BPF_MEM:
194 op = op_table[BPF_LD_W];
195 fmt = "M[%d]";
196 break;
197 case BPF_LDX | BPF_MEM:
198 op = op_table[BPF_LDX];
199 fmt = "M[%d]";
200 break;
201 case BPF_ST:
202 op = op_table[BPF_ST];
203 fmt = "M[%d]";
204 break;
205 case BPF_STX:
206 op = op_table[BPF_STX];
207 fmt = "M[%d]";
208 break;
209 case BPF_JMP_JA:
210 op = op_table[BPF_JMP_JA];
211 fmt = "%d";
212 v = n + 1 + bpf.k;
213 break;
214 case BPF_JMP_JGT | BPF_K:
215 op = op_table[BPF_JMP_JGT];
216 fmt = "#0x%x";
217 break;
218 case BPF_JMP_JGE | BPF_K:
219 op = op_table[BPF_JMP_JGE];
220 fmt = "#0x%x";
221 break;
222 case BPF_JMP_JEQ | BPF_K:
223 op = op_table[BPF_JMP_JEQ];
224 fmt = "#0x%x";
225 break;
226 case BPF_JMP_JSET | BPF_K:
227 op = op_table[BPF_JMP_JSET];
228 fmt = "#0x%x";
229 break;
230 case BPF_JMP_JGT | BPF_X:
231 op = op_table[BPF_JMP_JGT];
232 fmt = "x";
233 break;
234 case BPF_JMP_JGE | BPF_X:
235 op = op_table[BPF_JMP_JGE];
236 fmt = "x";
237 break;
238 case BPF_JMP_JEQ | BPF_X:
239 op = op_table[BPF_JMP_JEQ];
240 fmt = "x";
241 break;
242 case BPF_JMP_JSET | BPF_X:
243 op = op_table[BPF_JMP_JSET];
244 fmt = "x";
245 break;
246 case BPF_ALU_ADD | BPF_X:
247 op = op_table[BPF_ALU_ADD];
248 fmt = "x";
249 break;
250 case BPF_ALU_SUB | BPF_X:
251 op = op_table[BPF_ALU_SUB];
252 fmt = "x";
253 break;
254 case BPF_ALU_MUL | BPF_X:
255 op = op_table[BPF_ALU_MUL];
256 fmt = "x";
257 break;
258 case BPF_ALU_DIV | BPF_X:
259 op = op_table[BPF_ALU_DIV];
260 fmt = "x";
261 break;
262 case BPF_ALU_MOD | BPF_X:
263 op = op_table[BPF_ALU_MOD];
264 fmt = "x";
265 break;
266 case BPF_ALU_AND | BPF_X:
267 op = op_table[BPF_ALU_AND];
268 fmt = "x";
269 break;
270 case BPF_ALU_OR | BPF_X:
271 op = op_table[BPF_ALU_OR];
272 fmt = "x";
273 break;
274 case BPF_ALU_XOR | BPF_X:
275 op = op_table[BPF_ALU_XOR];
276 fmt = "x";
277 break;
278 case BPF_ALU_LSH | BPF_X:
279 op = op_table[BPF_ALU_LSH];
280 fmt = "x";
281 break;
282 case BPF_ALU_RSH | BPF_X:
283 op = op_table[BPF_ALU_RSH];
284 fmt = "x";
285 break;
286 case BPF_ALU_ADD | BPF_K:
287 op = op_table[BPF_ALU_ADD];
288 fmt = "#%d";
289 break;
290 case BPF_ALU_SUB | BPF_K:
291 op = op_table[BPF_ALU_SUB];
292 fmt = "#%d";
293 break;
294 case BPF_ALU_MUL | BPF_K:
295 op = op_table[BPF_ALU_MUL];
296 fmt = "#%d";
297 break;
298 case BPF_ALU_DIV | BPF_K:
299 op = op_table[BPF_ALU_DIV];
300 fmt = "#%d";
301 break;
302 case BPF_ALU_MOD | BPF_K:
303 op = op_table[BPF_ALU_MOD];
304 fmt = "#%d";
305 break;
306 case BPF_ALU_AND | BPF_K:
307 op = op_table[BPF_ALU_AND];
308 fmt = "#0x%x";
309 break;
310 case BPF_ALU_OR | BPF_K:
311 op = op_table[BPF_ALU_OR];
312 fmt = "#0x%x";
313 break;
314 case BPF_ALU_XOR | BPF_K:
315 op = op_table[BPF_ALU_XOR];
316 fmt = "#0x%x";
317 break;
318 case BPF_ALU_LSH | BPF_K:
319 op = op_table[BPF_ALU_LSH];
320 fmt = "#%d";
321 break;
322 case BPF_ALU_RSH | BPF_K:
323 op = op_table[BPF_ALU_RSH];
324 fmt = "#%d";
325 break;
326 case BPF_ALU_NEG:
327 op = op_table[BPF_ALU_NEG];
328 fmt = "";
329 break;
330 case BPF_MISC_TAX:
331 op = op_table[BPF_MISC_TAX];
332 fmt = "";
333 break;
334 case BPF_MISC_TXA:
335 op = op_table[BPF_MISC_TXA];
336 fmt = "";
337 break;
340 slprintf_nocheck(operand, sizeof(operand), fmt, v);
341 slprintf_nocheck(image, sizeof(image),
342 (BPF_CLASS(bpf.code) == BPF_JMP &&
343 BPF_OP(bpf.code) != BPF_JA) ?
344 " L%d: %s %s, L%d, L%d" : " L%d: %s %s",
345 n, op, operand, n + 1 + bpf.jt, n + 1 + bpf.jf);
346 return image;
349 void bpf_dump_all(struct sock_fprog *bpf)
351 int i;
353 for (i = 0; i < bpf->len; ++i)
354 printf("%s\n", __bpf_dump(bpf->filter[i], i));
357 void bpf_attach_to_sock(int sock, struct sock_fprog *bpf)
359 int ret;
361 if (bpf->filter[0].code == BPF_RET &&
362 bpf->filter[0].k == 0xFFFFFFFF)
363 return;
365 ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER,
366 bpf, sizeof(*bpf));
367 if (unlikely(ret < 0))
368 panic("Cannot attach filter to socket!\n");
371 void bpf_detach_from_sock(int sock)
373 int ret, empty = 0;
375 ret = setsockopt(sock, SOL_SOCKET, SO_DETACH_FILTER,
376 &empty, sizeof(empty));
377 if (unlikely(ret < 0))
378 panic("Cannot detach filter from socket!\n");
381 int enable_kernel_bpf_jit_compiler(void)
383 int fd;
384 ssize_t ret;
385 char *file = "/proc/sys/net/core/bpf_jit_enable";
387 fd = open(file, O_WRONLY);
388 if (unlikely(fd < 0))
389 return -1;
391 ret = write(fd, "1", strlen("1"));
393 close(fd);
394 return ret;
397 int __bpf_validate(const struct sock_fprog *bpf)
399 uint32_t i, from;
400 const struct sock_filter *p;
402 if (!bpf)
403 return 0;
404 if (bpf->len < 1)
405 return 0;
407 for (i = 0; i < bpf->len; ++i) {
408 p = &bpf->filter[i];
409 switch (BPF_CLASS(p->code)) {
410 /* Check that memory operations use valid addresses. */
411 case BPF_LD:
412 case BPF_LDX:
413 switch (BPF_MODE(p->code)) {
414 case BPF_IMM:
415 break;
416 case BPF_ABS:
417 case BPF_IND:
418 case BPF_MSH:
419 /* There's no maximum packet data size
420 * in userland. The runtime packet length
421 * check suffices.
423 break;
424 case BPF_MEM:
425 if (p->k >= BPF_MEMWORDS)
426 return 0;
427 break;
428 case BPF_LEN:
429 break;
430 default:
431 return 0;
433 break;
434 case BPF_ST:
435 case BPF_STX:
436 if (p->k >= BPF_MEMWORDS)
437 return 0;
438 break;
439 case BPF_ALU:
440 switch (BPF_OP(p->code)) {
441 case BPF_ADD:
442 case BPF_SUB:
443 case BPF_MUL:
444 case BPF_OR:
445 case BPF_XOR:
446 case BPF_AND:
447 case BPF_LSH:
448 case BPF_RSH:
449 case BPF_NEG:
450 break;
451 case BPF_DIV:
452 case BPF_MOD:
453 /* Check for constant division by 0 (undefined
454 * for div and mod).
456 if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
457 return 0;
458 break;
459 default:
460 return 0;
462 break;
463 case BPF_JMP:
464 /* Check that jumps are within the code block,
465 * and that unconditional branches don't go
466 * backwards as a result of an overflow.
467 * Unconditional branches have a 32-bit offset,
468 * so they could overflow; we check to make
469 * sure they don't. Conditional branches have
470 * an 8-bit offset, and the from address is <=
471 * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
472 * is sufficiently small that adding 255 to it
473 * won't overflow.
475 * We know that len is <= BPF_MAXINSNS, and we
476 * assume that BPF_MAXINSNS is < the maximum size
477 * of a u_int, so that i + 1 doesn't overflow.
479 * For userland, we don't know that the from
480 * or len are <= BPF_MAXINSNS, but we know that
481 * from <= len, and, except on a 64-bit system,
482 * it's unlikely that len, if it truly reflects
483 * the size of the program we've been handed,
484 * will be anywhere near the maximum size of
485 * a u_int. We also don't check for backward
486 * branches, as we currently support them in
487 * userland for the protochain operation.
489 from = i + 1;
490 switch (BPF_OP(p->code)) {
491 case BPF_JA:
492 if (from + p->k >= bpf->len)
493 return 0;
494 break;
495 case BPF_JEQ:
496 case BPF_JGT:
497 case BPF_JGE:
498 case BPF_JSET:
499 if (from + p->jt >= bpf->len ||
500 from + p->jf >= bpf->len)
501 return 0;
502 break;
503 default:
504 return 0;
506 break;
507 case BPF_RET:
508 break;
509 case BPF_MISC:
510 break;
514 return BPF_CLASS(bpf->filter[bpf->len - 1].code) == BPF_RET;
517 uint32_t bpf_run_filter(const struct sock_fprog * fcode, uint8_t * packet,
518 size_t plen)
520 /* XXX: caplen == len */
521 uint32_t A, X;
522 uint32_t k;
523 struct sock_filter *bpf;
524 int32_t mem[BPF_MEMWORDS] = { 0, };
526 if (fcode == NULL || fcode->filter == NULL || fcode->len == 0)
527 return 0xFFFFFFFF;
529 A = 0;
530 X = 0;
532 bpf = fcode->filter;
533 --bpf;
534 while (1) {
535 ++bpf;
536 switch (bpf->code) {
537 default:
538 return 0;
539 case BPF_RET | BPF_K:
540 return (uint32_t) bpf->k;
541 case BPF_RET | BPF_A:
542 return (uint32_t) A;
543 case BPF_LD_W | BPF_ABS:
544 /* No Linux extensions supported here! */
545 k = bpf->k;
546 if (k + sizeof(int32_t) > plen)
547 return 0;
548 A = EXTRACT_LONG(&packet[k]);
549 continue;
550 case BPF_LD_H | BPF_ABS:
551 /* No Linux extensions supported here! */
552 k = bpf->k;
553 if (k + sizeof(short) > plen)
554 return 0;
555 A = EXTRACT_SHORT(&packet[k]);
556 continue;
557 case BPF_LD_B | BPF_ABS:
558 /* No Linux extensions supported here! */
559 k = bpf->k;
560 if (k >= plen)
561 return 0;
562 A = packet[k];
563 continue;
564 case BPF_LD_W | BPF_LEN:
565 A = plen;
566 continue;
567 case BPF_LDX_W | BPF_LEN:
568 X = plen;
569 continue;
570 case BPF_LD_W | BPF_IND:
571 k = X + bpf->k;
572 if (k + sizeof(int32_t) > plen)
573 return 0;
574 A = EXTRACT_LONG(&packet[k]);
575 continue;
576 case BPF_LD_H | BPF_IND:
577 k = X + bpf->k;
578 if (k + sizeof(short) > plen)
579 return 0;
580 A = EXTRACT_SHORT(&packet[k]);
581 continue;
582 case BPF_LD_B | BPF_IND:
583 k = X + bpf->k;
584 if (k >= plen)
585 return 0;
586 A = packet[k];
587 continue;
588 case BPF_LDX_B | BPF_MSH:
589 k = bpf->k;
590 if (k >= plen)
591 return 0;
592 X = (packet[bpf->k] & 0xf) << 2;
593 continue;
594 case BPF_LD | BPF_IMM:
595 A = bpf->k;
596 continue;
597 case BPF_LDX | BPF_IMM:
598 X = bpf->k;
599 continue;
600 case BPF_LD | BPF_MEM:
601 A = mem[bpf->k];
602 continue;
603 case BPF_LDX | BPF_MEM:
604 X = mem[bpf->k];
605 continue;
606 case BPF_ST:
607 mem[bpf->k] = A;
608 continue;
609 case BPF_STX:
610 mem[bpf->k] = X;
611 continue;
612 case BPF_JMP_JA:
613 bpf += bpf->k;
614 continue;
615 case BPF_JMP_JGT | BPF_K:
616 bpf += (A > bpf->k) ? bpf->jt : bpf->jf;
617 continue;
618 case BPF_JMP_JGE | BPF_K:
619 bpf += (A >= bpf->k) ? bpf->jt : bpf->jf;
620 continue;
621 case BPF_JMP_JEQ | BPF_K:
622 bpf += (A == bpf->k) ? bpf->jt : bpf->jf;
623 continue;
624 case BPF_JMP_JSET | BPF_K:
625 bpf += (A & bpf->k) ? bpf->jt : bpf->jf;
626 continue;
627 case BPF_JMP_JGT | BPF_X:
628 bpf += (A > X) ? bpf->jt : bpf->jf;
629 continue;
630 case BPF_JMP_JGE | BPF_X:
631 bpf += (A >= X) ? bpf->jt : bpf->jf;
632 continue;
633 case BPF_JMP_JEQ | BPF_X:
634 bpf += (A == X) ? bpf->jt : bpf->jf;
635 continue;
636 case BPF_JMP_JSET | BPF_X:
637 bpf += (A & X) ? bpf->jt : bpf->jf;
638 continue;
639 case BPF_ALU_ADD | BPF_X:
640 A += X;
641 continue;
642 case BPF_ALU_SUB | BPF_X:
643 A -= X;
644 continue;
645 case BPF_ALU_MUL | BPF_X:
646 A *= X;
647 continue;
648 case BPF_ALU_DIV | BPF_X:
649 if (X == 0)
650 return 0;
651 A /= X;
652 continue;
653 case BPF_ALU_MOD | BPF_X:
654 if (X == 0)
655 return 0;
656 A %= X;
657 continue;
658 case BPF_ALU_AND | BPF_X:
659 A &= X;
660 continue;
661 case BPF_ALU_OR | BPF_X:
662 A |= X;
663 continue;
664 case BPF_ALU_XOR | BPF_X:
665 A ^= X;
666 continue;
667 case BPF_ALU_LSH | BPF_X:
668 A <<= X;
669 continue;
670 case BPF_ALU_RSH | BPF_X:
671 A >>= X;
672 continue;
673 case BPF_ALU_ADD | BPF_K:
674 A += bpf->k;
675 continue;
676 case BPF_ALU_SUB | BPF_K:
677 A -= bpf->k;
678 continue;
679 case BPF_ALU_MUL | BPF_K:
680 A *= bpf->k;
681 continue;
682 case BPF_ALU_DIV | BPF_K:
683 A /= bpf->k;
684 continue;
685 case BPF_ALU_MOD | BPF_K:
686 A %= bpf->k;
687 continue;
688 case BPF_ALU_AND | BPF_K:
689 A &= bpf->k;
690 continue;
691 case BPF_ALU_OR | BPF_K:
692 A |= bpf->k;
693 continue;
694 case BPF_ALU_XOR | BPF_K:
695 A ^= bpf->k;
696 continue;
697 case BPF_ALU_LSH | BPF_K:
698 A <<= bpf->k;
699 continue;
700 case BPF_ALU_RSH | BPF_K:
701 A >>= bpf->k;
702 continue;
703 case BPF_ALU_NEG:
704 A = -A;
705 continue;
706 case BPF_MISC_TAX:
707 X = A;
708 continue;
709 case BPF_MISC_TXA:
710 A = X;
711 continue;
716 void bpf_parse_rules(char *rulefile, struct sock_fprog *bpf, uint32_t link_type)
718 int ret;
719 char buff[256];
720 struct sock_filter sf_single = { 0x06, 0, 0, 0xFFFFFFFF };
721 FILE *fp;
723 fmemset(bpf, 0, sizeof(*bpf));
725 if (rulefile == NULL) {
726 bpf->len = 1;
727 bpf->filter = xmalloc(sizeof(sf_single));
729 fmemcpy(&bpf->filter[0], &sf_single, sizeof(sf_single));
730 return;
733 fp = fopen(rulefile, "r");
734 if (!fp) {
735 bpf_try_compile(rulefile, bpf, link_type);
736 return;
739 fmemset(buff, 0, sizeof(buff));
740 while (fgets(buff, sizeof(buff), fp) != NULL) {
741 buff[sizeof(buff) - 1] = 0;
743 if (buff[0] != '{') {
744 fmemset(buff, 0, sizeof(buff));
745 continue;
748 fmemset(&sf_single, 0, sizeof(sf_single));
749 ret = sscanf(buff, "{ 0x%x, %u, %u, 0x%08x },",
750 (unsigned int *) &sf_single.code,
751 (unsigned int *) &sf_single.jt,
752 (unsigned int *) &sf_single.jf,
753 (unsigned int *) &sf_single.k);
754 if (unlikely(ret != 4))
755 panic("BPF syntax error!\n");
757 bpf->len++;
758 bpf->filter = xrealloc(bpf->filter, 1,
759 bpf->len * sizeof(sf_single));
761 fmemcpy(&bpf->filter[bpf->len - 1], &sf_single,
762 sizeof(sf_single));
763 fmemset(buff, 0, sizeof(buff));
766 fclose(fp);
768 if (unlikely(__bpf_validate(bpf) == 0))
769 panic("This is not a valid BPF program!\n");