* Copyright (c) 1991 The Regents of the University of California.
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne of Lawrence Berkeley Laboratory.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)bpf_filter.c 7.2 (Berkeley) 5/14/91
* "@(#) $Header: bpf_filter.c,v 1.10 91/04/24 22:07:07 mccanne Locked $ (LBL)";
#if defined(sparc) || defined(mips)
#define EXTRACT_SHORT(p) (ntohs(*(u_short *)p))
#define EXTRACT_LONG(p) (ntohl(*(u_long *)p))
#define EXTRACT_SHORT(p)\
(*((u_char *)(p)+0)<<24|\
register int len = m->m_len; \
register u_char
*cp
, *np
;
register struct mbuf
*m0
;
cp
= mtod(m
, u_char
*) + k
;
if (m0
== 0 || m0
->m_len
+ len
- k
< 4)
return (cp
[k
] << 24) | (np
[0] << 16) | (np
[1] << 8) | np
[2];
return (cp
[k
] << 24) | (cp
[k
+ 1] << 16) | (np
[0] << 8) |
return (cp
[k
] << 24) | (cp
[k
+ 1] << 16) | (cp
[k
+ 2] << 8) |
register u_char
*cp
, *np
;
register struct mbuf
*m0
;
cp
= mtod(m
, u_char
*) + k
;
return EXTRACT_SHORT(cp
);
return (cp
[k
] << 8) | mtod(m0
, u_char
*)[0];
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
* buflen is the amount of data present
bpf_filter(pc
, p
, wirelen
, buflen
)
register struct bpf_insn
*pc
;
* No filter means accept all.
case BPF_LD
|BPF_W
|BPF_ABS
:
if (k
+ sizeof(long) > buflen
) {
A
= m_xword((struct mbuf
*)p
, k
, &merr
);
if (((int)(p
+ k
) & 3) != 0)
case BPF_LD
|BPF_H
|BPF_ABS
:
if (k
+ sizeof(short) > buflen
) {
A
= m_xhalf((struct mbuf
*)p
, k
, &merr
);
A
= EXTRACT_SHORT(&p
[k
]);
case BPF_LD
|BPF_B
|BPF_ABS
:
A
= mtod(m
, u_char
*)[k
];
case BPF_LD
|BPF_W
|BPF_LEN
:
case BPF_LDX
|BPF_W
|BPF_LEN
:
case BPF_LD
|BPF_W
|BPF_IND
:
if (k
+ sizeof(long) > buflen
) {
A
= m_xword((struct mbuf
*)p
, k
, &merr
);
if (((int)(p
+ k
) & 3) != 0)
case BPF_LD
|BPF_H
|BPF_IND
:
if (k
+ sizeof(short) > buflen
) {
A
= m_xhalf((struct mbuf
*)p
, k
, &merr
);
A
= EXTRACT_SHORT(&p
[k
]);
case BPF_LD
|BPF_B
|BPF_IND
:
case BPF_LDX
|BPF_MSH
|BPF_B
:
X
= (mtod(m
, char *)[k
] & 0xf) << 2;
X
= (p
[pc
->k
] & 0xf) << 2;
case BPF_JMP
|BPF_JGT
|BPF_K
:
pc
+= (A
> pc
->k
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JGE
|BPF_K
:
pc
+= (A
>= pc
->k
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JEQ
|BPF_K
:
pc
+= (A
== pc
->k
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JSET
|BPF_K
:
pc
+= (A
& pc
->k
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JGT
|BPF_X
:
pc
+= (A
> X
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JGE
|BPF_X
:
pc
+= (A
>= X
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JEQ
|BPF_X
:
pc
+= (A
== X
) ? pc
->jt
: pc
->jf
;
case BPF_JMP
|BPF_JSET
|BPF_X
:
pc
+= (A
& X
) ? pc
->jt
: pc
->jf
;
case BPF_ALU
|BPF_ADD
|BPF_X
:
case BPF_ALU
|BPF_SUB
|BPF_X
:
case BPF_ALU
|BPF_MUL
|BPF_X
:
case BPF_ALU
|BPF_DIV
|BPF_X
:
case BPF_ALU
|BPF_AND
|BPF_X
:
case BPF_ALU
|BPF_OR
|BPF_X
:
case BPF_ALU
|BPF_LSH
|BPF_X
:
case BPF_ALU
|BPF_RSH
|BPF_X
:
case BPF_ALU
|BPF_ADD
|BPF_K
:
case BPF_ALU
|BPF_SUB
|BPF_K
:
case BPF_ALU
|BPF_MUL
|BPF_K
:
case BPF_ALU
|BPF_DIV
|BPF_K
:
case BPF_ALU
|BPF_AND
|BPF_K
:
case BPF_ALU
|BPF_OR
|BPF_K
:
case BPF_ALU
|BPF_LSH
|BPF_K
:
case BPF_ALU
|BPF_RSH
|BPF_K
:
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
* code. The code must terminate with either an accept or reject.
* 'valid' is an array for use by the routine (it must be at least
* The kernel needs to be able to verify an application's filter code.
* Otherwise, a bogus program could easily crash the system.
register struct bpf_insn
*p
;
for (i
= 0; i
< len
; ++i
) {
* Check that that jumps are forward, and within
if (BPF_CLASS(p
->code
) == BPF_JMP
) {
register int from
= i
+ 1;
if (BPF_OP(p
->code
) == BPF_JA
) {
else if (from
+ p
->jt
>= len
|| from
+ p
->jf
>= len
)
* Check that memory operations use valid addresses.
if ((BPF_CLASS(p
->code
) == BPF_ST
||
(BPF_CLASS(p
->code
) == BPF_LD
&&
(p
->code
& 0xe0) == BPF_MEM
)) &&
(p
->k
>= BPF_MEMWORDS
|| p
->k
< 0))
* Check for constant division by 0.
if (p
->code
== BPF_ALU
|BPF_DIV
|BPF_K
&& p
->k
== 0)
return BPF_CLASS(f
[len
- 1].code
) == BPF_RET
;