Implement BPF_MOD and BPF_XOR instructions.
These two ALU instructions first appeared on Linux. Then, libpcap adopted and made them available since 1.6.2. Now more platforms including NetBSD have them in kernel. So do we. --이 줄 이하는 자동으로 제거됩니다--
This commit is contained in:
parent
ffaa5deb38
commit
69d410eeb1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=307707
@ -49,7 +49,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 15, 2010
|
||||
.Dd October 21, 2016
|
||||
.Dt BPF 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -881,16 +881,20 @@ BPF_ALU+BPF_ADD+BPF_K A <- A + k
|
||||
BPF_ALU+BPF_SUB+BPF_K A <- A - k
|
||||
BPF_ALU+BPF_MUL+BPF_K A <- A * k
|
||||
BPF_ALU+BPF_DIV+BPF_K A <- A / k
|
||||
BPF_ALU+BPF_MOD+BPF_K A <- A % k
|
||||
BPF_ALU+BPF_AND+BPF_K A <- A & k
|
||||
BPF_ALU+BPF_OR+BPF_K A <- A | k
|
||||
BPF_ALU+BPF_XOR+BPF_K A <- A ^ k
|
||||
BPF_ALU+BPF_LSH+BPF_K A <- A << k
|
||||
BPF_ALU+BPF_RSH+BPF_K A <- A >> k
|
||||
BPF_ALU+BPF_ADD+BPF_X A <- A + X
|
||||
BPF_ALU+BPF_SUB+BPF_X A <- A - X
|
||||
BPF_ALU+BPF_MUL+BPF_X A <- A * X
|
||||
BPF_ALU+BPF_DIV+BPF_X A <- A / X
|
||||
BPF_ALU+BPF_MOD+BPF_X A <- A % X
|
||||
BPF_ALU+BPF_AND+BPF_X A <- A & X
|
||||
BPF_ALU+BPF_OR+BPF_X A <- A | X
|
||||
BPF_ALU+BPF_XOR+BPF_X A <- A ^ X
|
||||
BPF_ALU+BPF_LSH+BPF_X A <- A << X
|
||||
BPF_ALU+BPF_RSH+BPF_X A <- A >> X
|
||||
BPF_ALU+BPF_NEG A <- -A
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* Copyright (C) 2005-2016 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -494,6 +494,7 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
case BPF_ALU|BPF_MOD|BPF_X:
|
||||
TESTrd(EDX, EDX);
|
||||
if (fmem) {
|
||||
JNEb(4);
|
||||
@ -507,6 +508,8 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
MOVrd(EDX, ECX);
|
||||
ZEROrd(EDX);
|
||||
DIVrd(ECX);
|
||||
if (BPF_OP(ins->code) == BPF_MOD)
|
||||
MOVrd(EDX, EAX);
|
||||
MOVrd(ECX, EDX);
|
||||
break;
|
||||
|
||||
@ -518,6 +521,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
ORrd(EDX, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_X:
|
||||
XORrd(EDX, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
MOVrd(EDX, ECX);
|
||||
SHL_CLrb(EAX);
|
||||
@ -544,10 +551,13 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
case BPF_ALU|BPF_MOD|BPF_K:
|
||||
MOVrd(EDX, ECX);
|
||||
ZEROrd(EDX);
|
||||
MOVid(ins->k, ESI);
|
||||
DIVrd(ESI);
|
||||
if (BPF_OP(ins->code) == BPF_MOD)
|
||||
MOVrd(EDX, EAX);
|
||||
MOVrd(ECX, EDX);
|
||||
break;
|
||||
|
||||
@ -559,6 +569,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
ORid(ins->k, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_K:
|
||||
XORid(ins->k, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
SHLib((ins->k) & 0xff, EAX);
|
||||
break;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* Copyright (C) 2005-2016 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -357,6 +357,24 @@ typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
|
||||
emitm(&stream, i32, 4); \
|
||||
} while (0)
|
||||
|
||||
/* xorl sr32,dr32 */
|
||||
#define XORrd(sr32, dr32) do { \
|
||||
emitm(&stream, 0x31, 1); \
|
||||
emitm(&stream, \
|
||||
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
|
||||
} while (0)
|
||||
|
||||
/* xorl i32,r32 */
|
||||
#define XORid(i32, r32) do { \
|
||||
if (r32 == EAX) { \
|
||||
emitm(&stream, 0x35, 1); \
|
||||
} else { \
|
||||
emitm(&stream, 0x81, 1); \
|
||||
emitm(&stream, (25 << 3) | r32, 1); \
|
||||
} \
|
||||
emitm(&stream, i32, 4); \
|
||||
} while (0)
|
||||
|
||||
/* shll i8,r32 */
|
||||
#define SHLib(i8, r32) do { \
|
||||
emitm(&stream, 0xc1, 1); \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* Copyright (C) 2005-2016 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -139,6 +139,7 @@ bpf_jit_optimize(struct bpf_insn *prog, u_int nins)
|
||||
flags |= BPF_JIT_FJMP;
|
||||
break;
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
case BPF_ALU|BPF_MOD|BPF_K:
|
||||
flags |= BPF_JIT_FADK;
|
||||
break;
|
||||
}
|
||||
@ -515,6 +516,7 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
case BPF_ALU|BPF_MOD|BPF_X:
|
||||
TESTrd(EDX, EDX);
|
||||
if (save_esp) {
|
||||
if (fpkt) {
|
||||
@ -536,6 +538,8 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
MOVrd(EDX, ECX);
|
||||
ZEROrd(EDX);
|
||||
DIVrd(ECX);
|
||||
if (BPF_OP(ins->code) == BPF_MOD)
|
||||
MOVrd(EDX, EAX);
|
||||
MOVrd(ECX, EDX);
|
||||
break;
|
||||
|
||||
@ -547,6 +551,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
ORrd(EDX, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_X:
|
||||
XORrd(EDX, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
MOVrd(EDX, ECX);
|
||||
SHL_CLrb(EAX);
|
||||
@ -573,10 +581,13 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
case BPF_ALU|BPF_MOD|BPF_K:
|
||||
MOVrd(EDX, ECX);
|
||||
ZEROrd(EDX);
|
||||
MOVid(ins->k, ESI);
|
||||
DIVrd(ESI);
|
||||
if (BPF_OP(ins->code) == BPF_MOD)
|
||||
MOVrd(EDX, EAX);
|
||||
MOVrd(ECX, EDX);
|
||||
break;
|
||||
|
||||
@ -588,6 +599,10 @@ bpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size)
|
||||
ORid(ins->k, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_K:
|
||||
XORid(ins->k, EAX);
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
SHLib((ins->k) & 0xff, EAX);
|
||||
break;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* Copyright (C) 2005-2016 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -302,6 +302,24 @@ typedef void (*emit_func)(bpf_bin_stream *stream, u_int value, u_int n);
|
||||
emitm(&stream, i32, 4); \
|
||||
} while (0)
|
||||
|
||||
/* xorl sr32,dr32 */
|
||||
#define XORrd(sr32, dr32) do { \
|
||||
emitm(&stream, 0x31, 1); \
|
||||
emitm(&stream, \
|
||||
(3 << 6) | ((sr32 & 0x7) << 3) | (dr32 & 0x7), 1); \
|
||||
} while (0)
|
||||
|
||||
/* xorl i32,r32 */
|
||||
#define XORid(i32, r32) do { \
|
||||
if (r32 == EAX) { \
|
||||
emitm(&stream, 0x35, 1); \
|
||||
} else { \
|
||||
emitm(&stream, 0x81, 1); \
|
||||
emitm(&stream, (25 << 3) | r32, 1); \
|
||||
} \
|
||||
emitm(&stream, i32, 4); \
|
||||
} while (0)
|
||||
|
||||
/* shll i8,r32 */
|
||||
#define SHLib(i8, r32) do { \
|
||||
emitm(&stream, 0xc1, 1); \
|
||||
|
@ -434,6 +434,12 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
|
||||
A /= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MOD|BPF_X:
|
||||
if (X == 0)
|
||||
return (0);
|
||||
A %= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
A &= X;
|
||||
continue;
|
||||
@ -442,6 +448,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
|
||||
A |= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_X:
|
||||
A ^= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
A <<= X;
|
||||
continue;
|
||||
@ -466,6 +476,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
|
||||
A /= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MOD|BPF_K:
|
||||
A %= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
A &= pc->k;
|
||||
continue;
|
||||
@ -474,6 +488,10 @@ bpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
|
||||
A |= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_XOR|BPF_K:
|
||||
A ^= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
A <<= pc->k;
|
||||
continue;
|
||||
@ -508,8 +526,8 @@ static const u_short bpf_code_map[] = {
|
||||
0x1013, /* 0x60-0x6f: 1100100000001000 */
|
||||
0x1010, /* 0x70-0x7f: 0000100000001000 */
|
||||
0x0093, /* 0x80-0x8f: 1100100100000000 */
|
||||
0x0000, /* 0x90-0x9f: 0000000000000000 */
|
||||
0x0000, /* 0xa0-0xaf: 0000000000000000 */
|
||||
0x1010, /* 0x90-0x9f: 0000100000001000 */
|
||||
0x1010, /* 0xa0-0xaf: 0000100000001000 */
|
||||
0x0002, /* 0xb0-0xbf: 0100000000000000 */
|
||||
0x0000, /* 0xc0-0xcf: 0000000000000000 */
|
||||
0x0000, /* 0xd0-0xdf: 0000000000000000 */
|
||||
@ -577,7 +595,8 @@ bpf_validate(const struct bpf_insn *f, int len)
|
||||
/*
|
||||
* Check for constant division by 0.
|
||||
*/
|
||||
if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
|
||||
if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) ||
|
||||
p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0)
|
||||
return (0);
|
||||
}
|
||||
return (BPF_CLASS(f[len - 1].code) == BPF_RET);
|
||||
|
Loading…
Reference in New Issue
Block a user