File: bpf.c

package info (click to toggle)
vblade 20-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, squeeze, wheezy
  • size: 204 kB
  • ctags: 256
  • sloc: ansic: 1,239; makefile: 71; sh: 1
file content (132 lines) | stat: -rw-r--r-- 3,586 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// bpf.c: bpf packet filter for linux/freebsd

#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "dat.h"
#include "fns.h"

struct bpf_insn {
	ushort code;
	uchar jt;
	uchar jf;
	u_int32_t k;
};

struct bpf_program {
	uint bf_len;
	struct bpf_insn *bf_insns;
};

/* instruction classes */
#define		BPF_CLASS(code) ((code) & 0x07)
#define		BPF_LD		0x00
#define		BPF_LDX		0x01
#define		BPF_ST		0x02
#define		BPF_STX		0x03
#define		BPF_ALU		0x04
#define		BPF_JMP		0x05
#define		BPF_RET		0x06
#define		BPF_MISC	0x07

/* ld/ldx fields */
#define		BPF_SIZE(code)	((code) & 0x18)
#define		BPF_W		0x00
#define		BPF_H		0x08
#define		BPF_B		0x10
#define		BPF_MODE(code)	((code) & 0xe0)
#define		BPF_IMM 	0x00
#define		BPF_ABS		0x20
#define		BPF_IND		0x40
#define		BPF_MEM		0x60
#define		BPF_LEN		0x80
#define		BPF_MSH		0xa0

/* alu/jmp fields */
#define		BPF_OP(code)	((code) & 0xf0)
#define		BPF_ADD		0x00
#define		BPF_SUB		0x10
#define		BPF_MUL		0x20
#define		BPF_DIV		0x30
#define		BPF_OR		0x40
#define		BPF_AND		0x50
#define		BPF_LSH		0x60
#define		BPF_RSH		0x70
#define		BPF_NEG		0x80
#define		BPF_JA		0x00
#define		BPF_JEQ		0x10
#define		BPF_JGT		0x20
#define		BPF_JGE		0x30
#define		BPF_JSET	0x40
#define		BPF_SRC(code)	((code) & 0x08)
#define		BPF_K		0x00
#define		BPF_X		0x08

/* ret - BPF_K and BPF_X also apply */
#define		BPF_RVAL(code)	((code) & 0x18)
#define		BPF_A		0x10

/* misc */
#define		BPF_MISCOP(code) ((code) & 0xf8)
#define		BPF_TAX		0x00
#define		BPF_TXA		0x80

/* macros for insn array initializers */
#define BPF_STMT(code, k) { (ushort)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (ushort)(code), jt, jf, k }

void *
create_bpf_program(int shelf, int slot)
{
	struct bpf_program *bpf_program;
	struct bpf_insn insns[] = {
		/* Load the type into register */
		BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
		/* Does it match AoE Type (0x88a2)? No, goto INVALID */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x88a2, 0, 12),
		/* Load the flags into register */
		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 14),
		/* Check to see if the Resp flag is set */
		BPF_STMT(BPF_ALU+BPF_AND+BPF_K, Resp),
		/* Yes, goto INVALID */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 9),
		/* Load the shelf number into register */
		BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
		/* Does it match shelf number? No, goto CHECKBROADCAST */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, shelf, 0, 2),
		/* Load the slot number into register */
		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
		/* Does it match shelf number? Yes, goto VALID */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, slot, 4, 0),
		/* CHECKBROADCAST: is (shelf, slot) == (0xffff, 0xff)? */
		/* Load the shelf number into register */
		BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
		/* Is it 0xffff? No, goto INVALID */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xffff, 0, 3),
		/* Load the slot number into register */
		BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
		/* Is it 0xff? No, goto INVALID */
		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xff, 0, 1),
		/* VALID: return -1 (allow the packet to be read) */
		BPF_STMT(BPF_RET+BPF_K, -1),
		/* INVALID: return 0 (ignore the packet) */
		BPF_STMT(BPF_RET+BPF_K, 0),
	};
	if ((bpf_program = malloc(sizeof(struct bpf_program))) == NULL
	    || (bpf_program->bf_insns = malloc(sizeof(insns))) == NULL) {
		perror("malloc");
		exit(1);
	}
	bpf_program->bf_len = sizeof(insns)/sizeof(struct bpf_insn);
	memcpy(bpf_program->bf_insns, insns, sizeof(insns));
	return (void *)bpf_program;
}

void
free_bpf_program(void *bpf_program)
{
	free(((struct bpf_program *) bpf_program)->bf_insns);
	free(bpf_program);
}