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