2005-04-16 15:20:36 -07:00
|
|
|
/*
|
|
|
|
|
* Linux Socket Filter Data Structures
|
|
|
|
|
*/
|
|
|
|
|
#ifndef __LINUX_FILTER_H__
|
|
|
|
|
#define __LINUX_FILTER_H__
|
|
|
|
|
|
2011-07-26 16:09:06 -07:00
|
|
|
#include <linux/atomic.h>
|
2012-04-12 16:47:53 -05:00
|
|
|
#include <linux/compat.h>
|
2013-10-04 00:14:06 -07:00
|
|
|
#include <linux/workqueue.h>
|
2012-10-13 10:46:48 +01:00
|
|
|
#include <uapi/linux/filter.h>
|
2011-05-22 07:08:11 +00:00
|
|
|
|
2014-03-28 18:58:25 +01:00
|
|
|
/* Internally used and optimized filter representation with extended
|
|
|
|
|
* instruction set based on top of classic BPF.
|
2012-04-12 16:47:53 -05:00
|
|
|
*/
|
2014-03-28 18:58:25 +01:00
|
|
|
|
|
|
|
|
/* instruction classes */
|
|
|
|
|
#define BPF_ALU64 0x07 /* alu mode in double word width */
|
|
|
|
|
|
|
|
|
|
/* ld/ldx fields */
|
|
|
|
|
#define BPF_DW 0x18 /* double word */
|
|
|
|
|
#define BPF_XADD 0xc0 /* exclusive add */
|
|
|
|
|
|
|
|
|
|
/* alu/jmp fields */
|
|
|
|
|
#define BPF_MOV 0xb0 /* mov reg to reg */
|
|
|
|
|
#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
|
|
|
|
|
|
|
|
|
|
/* change endianness of a register */
|
|
|
|
|
#define BPF_END 0xd0 /* flags for endianness conversion: */
|
|
|
|
|
#define BPF_TO_LE 0x00 /* convert to little-endian */
|
|
|
|
|
#define BPF_TO_BE 0x08 /* convert to big-endian */
|
|
|
|
|
#define BPF_FROM_LE BPF_TO_LE
|
|
|
|
|
#define BPF_FROM_BE BPF_TO_BE
|
|
|
|
|
|
|
|
|
|
#define BPF_JNE 0x50 /* jump != */
|
|
|
|
|
#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
|
|
|
|
|
#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
|
|
|
|
|
#define BPF_CALL 0x80 /* function call */
|
|
|
|
|
#define BPF_EXIT 0x90 /* function return */
|
|
|
|
|
|
2014-05-01 18:34:19 +02:00
|
|
|
/* Register numbers */
|
|
|
|
|
enum {
|
|
|
|
|
BPF_REG_0 = 0,
|
|
|
|
|
BPF_REG_1,
|
|
|
|
|
BPF_REG_2,
|
|
|
|
|
BPF_REG_3,
|
|
|
|
|
BPF_REG_4,
|
|
|
|
|
BPF_REG_5,
|
|
|
|
|
BPF_REG_6,
|
|
|
|
|
BPF_REG_7,
|
|
|
|
|
BPF_REG_8,
|
|
|
|
|
BPF_REG_9,
|
|
|
|
|
BPF_REG_10,
|
|
|
|
|
__MAX_BPF_REG,
|
|
|
|
|
};
|
|
|
|
|
|
2014-03-28 18:58:25 +01:00
|
|
|
/* BPF has 10 general purpose 64-bit registers and stack frame. */
|
2014-05-01 18:34:19 +02:00
|
|
|
#define MAX_BPF_REG __MAX_BPF_REG
|
|
|
|
|
|
|
|
|
|
/* ArgX, context and stack frame pointer register positions. Note,
|
|
|
|
|
* Arg1, Arg2, Arg3, etc are used as argument mappings of function
|
|
|
|
|
* calls in BPF_CALL instruction.
|
|
|
|
|
*/
|
|
|
|
|
#define BPF_REG_ARG1 BPF_REG_1
|
|
|
|
|
#define BPF_REG_ARG2 BPF_REG_2
|
|
|
|
|
#define BPF_REG_ARG3 BPF_REG_3
|
|
|
|
|
#define BPF_REG_ARG4 BPF_REG_4
|
|
|
|
|
#define BPF_REG_ARG5 BPF_REG_5
|
|
|
|
|
#define BPF_REG_CTX BPF_REG_6
|
|
|
|
|
#define BPF_REG_FP BPF_REG_10
|
|
|
|
|
|
|
|
|
|
/* Additional register mappings for converted user programs. */
|
|
|
|
|
#define BPF_REG_A BPF_REG_0
|
|
|
|
|
#define BPF_REG_X BPF_REG_7
|
|
|
|
|
#define BPF_REG_TMP BPF_REG_8
|
2014-03-28 18:58:25 +01:00
|
|
|
|
|
|
|
|
/* BPF program can access up to 512 bytes of stack space. */
|
|
|
|
|
#define MAX_BPF_STACK 512
|
|
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
/* Helper macros for filter block array initializers. */
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
/* ALU ops on registers, bpf_add|sub|...: A += X */
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
#define BPF_ALU64_REG(OP, A, X) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = 0 })
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
#define BPF_ALU32_REG(OP, A, X) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_OP(OP) | BPF_X, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = 0 })
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
/* ALU ops on immediates, bpf_add|sub|...: A += IMM */
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
#define BPF_ALU64_IMM(OP, A, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
#define BPF_ALU32_IMM(OP, A, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_OP(OP) | BPF_K, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
/* Endianess conversion, cpu_to_{l,b}e(), {l,b}e_to_cpu() */
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-29 10:22:51 +02:00
|
|
|
#define BPF_ENDIAN(TYPE, A, LEN) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_END | BPF_SRC(TYPE), \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = LEN })
|
|
|
|
|
|
|
|
|
|
/* Short form of mov, A = X */
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV64_REG(A, X) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV32_REG(A, X) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_MOV | BPF_X, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
/* Short form of mov, A = IMM */
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV64_IMM(A, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV32_IMM(A, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_MOV | BPF_K, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
/* Short form of mov based on type, BPF_X: A = X, BPF_K: A = IMM */
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV64_RAW(TYPE, A, X, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU64 | BPF_MOV | BPF_SRC(TYPE), \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
#define BPF_MOV32_RAW(TYPE, A, X, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_ALU | BPF_MOV | BPF_SRC(TYPE), \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
/* Direct packet access, R0 = *(uint *) (skb->data + OFF) */
|
|
|
|
|
|
|
|
|
|
#define BPF_LD_ABS(SIZE, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \
|
|
|
|
|
.a_reg = 0, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = OFF })
|
|
|
|
|
|
|
|
|
|
/* Indirect packet access, R0 = *(uint *) (skb->data + X + OFF) */
|
|
|
|
|
|
|
|
|
|
#define BPF_LD_IND(SIZE, X, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_LD | BPF_SIZE(SIZE) | BPF_IND, \
|
|
|
|
|
.a_reg = 0, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = OFF })
|
|
|
|
|
|
|
|
|
|
/* Memory store, A = *(uint *) (X + OFF), and vice versa */
|
|
|
|
|
|
|
|
|
|
#define BPF_LDX_MEM(SIZE, A, X, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = OFF, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
#define BPF_STX_MEM(SIZE, A, X, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = OFF, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
/* Conditional jumps against registers, if (A 'op' X) goto pc + OFF */
|
|
|
|
|
|
|
|
|
|
#define BPF_JMP_REG(OP, A, X, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_JMP | BPF_OP(OP) | BPF_X, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = OFF, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
/* Conditional jumps against immediates, if (A 'op' IMM) goto pc + OFF */
|
|
|
|
|
|
|
|
|
|
#define BPF_JMP_IMM(OP, A, IMM, OFF) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = OFF, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
/* Function call */
|
|
|
|
|
|
|
|
|
|
#define BPF_EMIT_CALL(FUNC) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_JMP | BPF_CALL, \
|
|
|
|
|
.a_reg = 0, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = ((FUNC) - __bpf_call_base) })
|
|
|
|
|
|
|
|
|
|
/* Raw code statement block */
|
|
|
|
|
|
|
|
|
|
#define BPF_RAW_INSN(CODE, A, X, OFF, IMM) \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = CODE, \
|
|
|
|
|
.a_reg = A, \
|
|
|
|
|
.x_reg = X, \
|
|
|
|
|
.off = OFF, \
|
|
|
|
|
.imm = IMM })
|
|
|
|
|
|
|
|
|
|
/* Program exit */
|
|
|
|
|
|
|
|
|
|
#define BPF_EXIT_INSN() \
|
|
|
|
|
((struct sock_filter_int) { \
|
|
|
|
|
.code = BPF_JMP | BPF_EXIT, \
|
|
|
|
|
.a_reg = 0, \
|
|
|
|
|
.x_reg = 0, \
|
|
|
|
|
.off = 0, \
|
|
|
|
|
.imm = 0 })
|
|
|
|
|
|
|
|
|
|
#define bytes_to_bpf_size(bytes) \
|
|
|
|
|
({ \
|
|
|
|
|
int bpf_size = -EINVAL; \
|
|
|
|
|
\
|
|
|
|
|
if (bytes == sizeof(u8)) \
|
|
|
|
|
bpf_size = BPF_B; \
|
|
|
|
|
else if (bytes == sizeof(u16)) \
|
|
|
|
|
bpf_size = BPF_H; \
|
|
|
|
|
else if (bytes == sizeof(u32)) \
|
|
|
|
|
bpf_size = BPF_W; \
|
|
|
|
|
else if (bytes == sizeof(u64)) \
|
|
|
|
|
bpf_size = BPF_DW; \
|
|
|
|
|
\
|
|
|
|
|
bpf_size; \
|
|
|
|
|
})
|
2014-05-08 14:10:51 -07:00
|
|
|
|
2014-05-01 18:34:19 +02:00
|
|
|
/* Macro to invoke filter function. */
|
|
|
|
|
#define SK_RUN_FILTER(filter, ctx) (*filter->bpf_func)(ctx, filter->insnsi)
|
2014-03-28 18:58:25 +01:00
|
|
|
|
|
|
|
|
struct sock_filter_int {
|
|
|
|
|
__u8 code; /* opcode */
|
|
|
|
|
__u8 a_reg:4; /* dest register */
|
|
|
|
|
__u8 x_reg:4; /* source register */
|
|
|
|
|
__s16 off; /* signed offset */
|
|
|
|
|
__s32 imm; /* signed immediate constant */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
|
/* A struct sock_filter is architecture independent. */
|
2012-04-12 16:47:53 -05:00
|
|
|
struct compat_sock_fprog {
|
|
|
|
|
u16 len;
|
2014-03-28 18:58:25 +01:00
|
|
|
compat_uptr_t filter; /* struct sock_filter * */
|
2012-04-12 16:47:53 -05:00
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-03-28 18:58:19 +01:00
|
|
|
struct sock_fprog_kern {
|
|
|
|
|
u16 len;
|
|
|
|
|
struct sock_filter *filter;
|
|
|
|
|
};
|
|
|
|
|
|
2011-05-22 07:08:11 +00:00
|
|
|
struct sk_buff;
|
|
|
|
|
struct sock;
|
2014-03-28 18:58:25 +01:00
|
|
|
struct seccomp_data;
|
2011-05-22 07:08:11 +00:00
|
|
|
|
2014-03-28 18:58:19 +01:00
|
|
|
struct sk_filter {
|
2008-04-10 01:33:47 -07:00
|
|
|
atomic_t refcnt;
|
2014-03-28 18:58:18 +01:00
|
|
|
u32 jited:1, /* Is our filter JIT'ed? */
|
|
|
|
|
len:31; /* Number of filter blocks */
|
2014-03-28 18:58:19 +01:00
|
|
|
struct sock_fprog_kern *orig_prog; /* Original BPF program */
|
2013-10-04 00:14:06 -07:00
|
|
|
struct rcu_head rcu;
|
2011-04-20 09:27:32 +00:00
|
|
|
unsigned int (*bpf_func)(const struct sk_buff *skb,
|
2014-03-28 18:58:25 +01:00
|
|
|
const struct sock_filter_int *filter);
|
2013-10-04 00:14:06 -07:00
|
|
|
union {
|
2014-03-28 18:58:25 +01:00
|
|
|
struct sock_filter insns[0];
|
|
|
|
|
struct sock_filter_int insnsi[0];
|
2013-10-04 00:14:06 -07:00
|
|
|
struct work_struct work;
|
|
|
|
|
};
|
2008-04-10 01:33:47 -07:00
|
|
|
};
|
|
|
|
|
|
2013-10-04 00:14:06 -07:00
|
|
|
static inline unsigned int sk_filter_size(unsigned int proglen)
|
2008-04-10 01:33:47 -07:00
|
|
|
{
|
2013-10-04 00:14:06 -07:00
|
|
|
return max(sizeof(struct sk_filter),
|
|
|
|
|
offsetof(struct sk_filter, insns[proglen]));
|
2008-04-10 01:33:47 -07:00
|
|
|
}
|
|
|
|
|
|
2014-03-28 18:58:19 +01:00
|
|
|
#define sk_filter_proglen(fprog) \
|
|
|
|
|
(fprog->len * sizeof(fprog->filter[0]))
|
|
|
|
|
|
2014-03-28 18:58:20 +01:00
|
|
|
int sk_filter(struct sock *sk, struct sk_buff *skb);
|
2014-03-28 18:58:25 +01:00
|
|
|
|
2014-05-19 14:56:14 -07:00
|
|
|
void sk_filter_select_runtime(struct sk_filter *fp);
|
|
|
|
|
void sk_filter_free(struct sk_filter *fp);
|
2014-03-28 18:58:25 +01:00
|
|
|
|
|
|
|
|
int sk_convert_filter(struct sock_filter *prog, int len,
|
|
|
|
|
struct sock_filter_int *new_prog, int *new_len);
|
2014-03-28 18:58:19 +01:00
|
|
|
|
2014-03-28 18:58:20 +01:00
|
|
|
int sk_unattached_filter_create(struct sk_filter **pfp,
|
2014-05-23 18:43:58 +02:00
|
|
|
struct sock_fprog_kern *fprog);
|
2014-03-28 18:58:20 +01:00
|
|
|
void sk_unattached_filter_destroy(struct sk_filter *fp);
|
2014-03-28 18:58:19 +01:00
|
|
|
|
2014-03-28 18:58:20 +01:00
|
|
|
int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
|
|
|
|
|
int sk_detach_filter(struct sock *sk);
|
2014-03-28 18:58:19 +01:00
|
|
|
|
2014-03-28 18:58:20 +01:00
|
|
|
int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
|
|
|
|
|
int sk_get_filter(struct sock *sk, struct sock_filter __user *filter,
|
|
|
|
|
unsigned int len);
|
|
|
|
|
|
|
|
|
|
void sk_filter_charge(struct sock *sk, struct sk_filter *fp);
|
|
|
|
|
void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
|
2011-04-20 09:27:32 +00:00
|
|
|
|
2014-05-13 19:50:46 -07:00
|
|
|
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
|
|
|
|
|
void bpf_int_jit_compile(struct sk_filter *fp);
|
|
|
|
|
|
2014-05-29 10:22:50 +02:00
|
|
|
#define BPF_ANC BIT(15)
|
|
|
|
|
|
|
|
|
|
static inline u16 bpf_anc_helper(const struct sock_filter *ftest)
|
|
|
|
|
{
|
|
|
|
|
BUG_ON(ftest->code & BPF_ANC);
|
|
|
|
|
|
|
|
|
|
switch (ftest->code) {
|
|
|
|
|
case BPF_LD | BPF_W | BPF_ABS:
|
|
|
|
|
case BPF_LD | BPF_H | BPF_ABS:
|
|
|
|
|
case BPF_LD | BPF_B | BPF_ABS:
|
|
|
|
|
#define BPF_ANCILLARY(CODE) case SKF_AD_OFF + SKF_AD_##CODE: \
|
|
|
|
|
return BPF_ANC | SKF_AD_##CODE
|
|
|
|
|
switch (ftest->k) {
|
|
|
|
|
BPF_ANCILLARY(PROTOCOL);
|
|
|
|
|
BPF_ANCILLARY(PKTTYPE);
|
|
|
|
|
BPF_ANCILLARY(IFINDEX);
|
|
|
|
|
BPF_ANCILLARY(NLATTR);
|
|
|
|
|
BPF_ANCILLARY(NLATTR_NEST);
|
|
|
|
|
BPF_ANCILLARY(MARK);
|
|
|
|
|
BPF_ANCILLARY(QUEUE);
|
|
|
|
|
BPF_ANCILLARY(HATYPE);
|
|
|
|
|
BPF_ANCILLARY(RXHASH);
|
|
|
|
|
BPF_ANCILLARY(CPU);
|
|
|
|
|
BPF_ANCILLARY(ALU_XOR_X);
|
|
|
|
|
BPF_ANCILLARY(VLAN_TAG);
|
|
|
|
|
BPF_ANCILLARY(VLAN_TAG_PRESENT);
|
|
|
|
|
BPF_ANCILLARY(PAY_OFFSET);
|
|
|
|
|
BPF_ANCILLARY(RANDOM);
|
|
|
|
|
}
|
|
|
|
|
/* Fallthrough. */
|
|
|
|
|
default:
|
|
|
|
|
return ftest->code;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-20 09:27:32 +00:00
|
|
|
#ifdef CONFIG_BPF_JIT
|
2013-05-01 16:24:08 -04:00
|
|
|
#include <stdarg.h>
|
2013-03-28 15:24:53 +00:00
|
|
|
#include <linux/linkage.h>
|
|
|
|
|
#include <linux/printk.h>
|
|
|
|
|
|
2014-03-28 18:58:20 +01:00
|
|
|
void bpf_jit_compile(struct sk_filter *fp);
|
|
|
|
|
void bpf_jit_free(struct sk_filter *fp);
|
2013-03-21 22:22:03 +01:00
|
|
|
|
|
|
|
|
static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
|
|
|
|
|
u32 pass, void *image)
|
|
|
|
|
{
|
2013-05-17 16:57:37 +00:00
|
|
|
pr_err("flen=%u proglen=%u pass=%u image=%pK\n",
|
2013-03-21 22:22:03 +01:00
|
|
|
flen, proglen, pass, image);
|
|
|
|
|
if (image)
|
2013-05-17 16:57:37 +00:00
|
|
|
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET,
|
2013-03-21 22:22:03 +01:00
|
|
|
16, 1, image, proglen, false);
|
|
|
|
|
}
|
2011-04-20 09:27:32 +00:00
|
|
|
#else
|
2013-10-04 00:14:06 -07:00
|
|
|
#include <linux/slab.h>
|
2014-05-29 10:22:50 +02:00
|
|
|
|
2011-04-20 09:27:32 +00:00
|
|
|
static inline void bpf_jit_compile(struct sk_filter *fp)
|
|
|
|
|
{
|
|
|
|
|
}
|
2014-05-29 10:22:50 +02:00
|
|
|
|
2011-04-20 09:27:32 +00:00
|
|
|
static inline void bpf_jit_free(struct sk_filter *fp)
|
|
|
|
|
{
|
2013-10-04 00:14:06 -07:00
|
|
|
kfree(fp);
|
2011-04-20 09:27:32 +00:00
|
|
|
}
|
2014-05-29 10:22:50 +02:00
|
|
|
#endif /* CONFIG_BPF_JIT */
|
2011-04-20 09:27:32 +00:00
|
|
|
|
2014-01-17 17:09:45 +01:00
|
|
|
static inline int bpf_tell_extensions(void)
|
|
|
|
|
{
|
2014-01-21 00:19:37 +01:00
|
|
|
return SKF_AD_MAX;
|
2014-01-17 17:09:45 +01:00
|
|
|
}
|
|
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
#endif /* __LINUX_FILTER_H__ */
|