1139823Simp/*- 21541Srgrimes * Copyright (c) 1990, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from the Stanford/CMU enet packet filter, 61541Srgrimes * (net/enet.c) distributed as part of 4.3BSD, and code contributed 71541Srgrimes * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 81541Srgrimes * Berkeley Laboratory. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 341541Srgrimes * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93 351541Srgrimes */ 361541Srgrimes 37174895Srwatson#include <sys/cdefs.h> 38174895Srwatson__FBSDID("$FreeBSD$"); 39174895Srwatson 401541Srgrimes#include <sys/param.h> 411541Srgrimes 42264457Sjmmv#if !defined(_KERNEL) 43264457Sjmmv#include <strings.h> 44264457Sjmmv#endif 45182184Sjkim#if !defined(_KERNEL) || defined(sun) 461541Srgrimes#include <netinet/in.h> 471541Srgrimes#endif 481541Srgrimes 4999419Speter#ifndef __i386__ 501541Srgrimes#define BPF_ALIGN 511541Srgrimes#endif 521541Srgrimes 531541Srgrimes#ifndef BPF_ALIGN 5440779Sdfr#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p)) 5540779Sdfr#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) 561541Srgrimes#else 571541Srgrimes#define EXTRACT_SHORT(p)\ 5840779Sdfr ((u_int16_t)\ 5940779Sdfr ((u_int16_t)*((u_char *)p+0)<<8|\ 6040779Sdfr (u_int16_t)*((u_char *)p+1)<<0)) 611541Srgrimes#define EXTRACT_LONG(p)\ 6240779Sdfr ((u_int32_t)*((u_char *)p+0)<<24|\ 6340779Sdfr (u_int32_t)*((u_char *)p+1)<<16|\ 6440779Sdfr (u_int32_t)*((u_char *)p+2)<<8|\ 6540779Sdfr (u_int32_t)*((u_char *)p+3)<<0) 661541Srgrimes#endif 671541Srgrimes 6855205Speter#ifdef _KERNEL 691541Srgrimes#include <sys/mbuf.h> 70182184Sjkim#else 71182184Sjkim#include <stdlib.h> 7241588Seivind#endif 7341588Seivind#include <net/bpf.h> 7455205Speter#ifdef _KERNEL 751541Srgrimes#define MINDEX(m, k) \ 761541Srgrimes{ \ 771541Srgrimes register int len = m->m_len; \ 781541Srgrimes \ 791541Srgrimes while (k >= len) { \ 801541Srgrimes k -= len; \ 811541Srgrimes m = m->m_next; \ 821541Srgrimes if (m == 0) \ 83182455Sjkim return (0); \ 841541Srgrimes len = m->m_len; \ 851541Srgrimes } \ 861541Srgrimes} 871541Srgrimes 8892725Salfredstatic u_int16_t m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err); 8992725Salfredstatic u_int32_t m_xword(struct mbuf *m, bpf_u_int32 k, int *err); 9012579Sbde 9141588Seivindstatic u_int32_t 92177003Srwatsonm_xword(struct mbuf *m, bpf_u_int32 k, int *err) 931541Srgrimes{ 94177003Srwatson size_t len; 95177003Srwatson u_char *cp, *np; 96177003Srwatson struct mbuf *m0; 971541Srgrimes 981541Srgrimes len = m->m_len; 991541Srgrimes while (k >= len) { 1001541Srgrimes k -= len; 1011541Srgrimes m = m->m_next; 1021541Srgrimes if (m == 0) 1031541Srgrimes goto bad; 1041541Srgrimes len = m->m_len; 1051541Srgrimes } 1061541Srgrimes cp = mtod(m, u_char *) + k; 1071541Srgrimes if (len - k >= 4) { 1081541Srgrimes *err = 0; 109182456Sjkim return (EXTRACT_LONG(cp)); 1101541Srgrimes } 1111541Srgrimes m0 = m->m_next; 1121541Srgrimes if (m0 == 0 || m0->m_len + len - k < 4) 1131541Srgrimes goto bad; 1141541Srgrimes *err = 0; 1151541Srgrimes np = mtod(m0, u_char *); 1161541Srgrimes switch (len - k) { 1171541Srgrimes case 1: 118182455Sjkim return (((u_int32_t)cp[0] << 24) | 11941588Seivind ((u_int32_t)np[0] << 16) | 12041588Seivind ((u_int32_t)np[1] << 8) | 121182455Sjkim (u_int32_t)np[2]); 1221541Srgrimes 1231541Srgrimes case 2: 124182455Sjkim return (((u_int32_t)cp[0] << 24) | 12541588Seivind ((u_int32_t)cp[1] << 16) | 12641588Seivind ((u_int32_t)np[0] << 8) | 127182455Sjkim (u_int32_t)np[1]); 1281541Srgrimes 1291541Srgrimes default: 130182455Sjkim return (((u_int32_t)cp[0] << 24) | 13141588Seivind ((u_int32_t)cp[1] << 16) | 13241588Seivind ((u_int32_t)cp[2] << 8) | 133182455Sjkim (u_int32_t)np[0]); 1341541Srgrimes } 1351541Srgrimes bad: 1361541Srgrimes *err = 1; 137177003Srwatson return (0); 1381541Srgrimes} 1391541Srgrimes 14041588Seivindstatic u_int16_t 141177003Srwatsonm_xhalf(struct mbuf *m, bpf_u_int32 k, int *err) 1421541Srgrimes{ 143177003Srwatson size_t len; 144177003Srwatson u_char *cp; 145177003Srwatson struct mbuf *m0; 1461541Srgrimes 1471541Srgrimes len = m->m_len; 1481541Srgrimes while (k >= len) { 1491541Srgrimes k -= len; 1501541Srgrimes m = m->m_next; 1511541Srgrimes if (m == 0) 1521541Srgrimes goto bad; 1531541Srgrimes len = m->m_len; 1541541Srgrimes } 1551541Srgrimes cp = mtod(m, u_char *) + k; 1561541Srgrimes if (len - k >= 2) { 1571541Srgrimes *err = 0; 158177003Srwatson return (EXTRACT_SHORT(cp)); 1591541Srgrimes } 1601541Srgrimes m0 = m->m_next; 1611541Srgrimes if (m0 == 0) 1621541Srgrimes goto bad; 1631541Srgrimes *err = 0; 164177003Srwatson return ((cp[0] << 8) | mtod(m0, u_char *)[0]); 1651541Srgrimes bad: 1661541Srgrimes *err = 1; 167177003Srwatson return (0); 1681541Srgrimes} 1691541Srgrimes#endif 1701541Srgrimes 1711541Srgrimes/* 1721541Srgrimes * Execute the filter program starting at pc on the packet p 1731541Srgrimes * wirelen is the length of the original packet 1741541Srgrimes * buflen is the amount of data present 1751541Srgrimes */ 1761541Srgrimesu_int 177177003Srwatsonbpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen) 1781541Srgrimes{ 179177003Srwatson u_int32_t A = 0, X = 0; 180177003Srwatson bpf_u_int32 k; 181172154Sdwmalone u_int32_t mem[BPF_MEMWORDS]; 1821541Srgrimes 183224044Smp bzero(mem, sizeof(mem)); 184224044Smp 185177003Srwatson if (pc == NULL) 1861541Srgrimes /* 1871541Srgrimes * No filter means accept all. 1881541Srgrimes */ 189177003Srwatson return ((u_int)-1); 1901549Srgrimes 1911541Srgrimes --pc; 1921541Srgrimes while (1) { 1931541Srgrimes ++pc; 1941541Srgrimes switch (pc->code) { 1951541Srgrimes default: 19655205Speter#ifdef _KERNEL 197182455Sjkim return (0); 1981541Srgrimes#else 1991541Srgrimes abort(); 2008876Srgrimes#endif 201177003Srwatson 2021541Srgrimes case BPF_RET|BPF_K: 203177003Srwatson return ((u_int)pc->k); 2041541Srgrimes 2051541Srgrimes case BPF_RET|BPF_A: 206177003Srwatson return ((u_int)A); 2071541Srgrimes 2081541Srgrimes case BPF_LD|BPF_W|BPF_ABS: 2091541Srgrimes k = pc->k; 21041588Seivind if (k > buflen || sizeof(int32_t) > buflen - k) { 21155205Speter#ifdef _KERNEL 2121541Srgrimes int merr; 2131541Srgrimes 2141541Srgrimes if (buflen != 0) 215182455Sjkim return (0); 2161541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2171541Srgrimes if (merr != 0) 218182455Sjkim return (0); 2191541Srgrimes continue; 2201541Srgrimes#else 221177003Srwatson return (0); 2221541Srgrimes#endif 2231541Srgrimes } 2241541Srgrimes#ifdef BPF_ALIGN 22540779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2261541Srgrimes A = EXTRACT_LONG(&p[k]); 2271541Srgrimes else 2281541Srgrimes#endif 22940779Sdfr A = ntohl(*(int32_t *)(p + k)); 2301541Srgrimes continue; 2311541Srgrimes 2321541Srgrimes case BPF_LD|BPF_H|BPF_ABS: 2331541Srgrimes k = pc->k; 23441588Seivind if (k > buflen || sizeof(int16_t) > buflen - k) { 23555205Speter#ifdef _KERNEL 2361541Srgrimes int merr; 2371541Srgrimes 2381541Srgrimes if (buflen != 0) 239182455Sjkim return (0); 2401541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 2411541Srgrimes continue; 2421541Srgrimes#else 243182455Sjkim return (0); 2441541Srgrimes#endif 2451541Srgrimes } 2461541Srgrimes A = EXTRACT_SHORT(&p[k]); 2471541Srgrimes continue; 2481541Srgrimes 2491541Srgrimes case BPF_LD|BPF_B|BPF_ABS: 2501541Srgrimes k = pc->k; 2511541Srgrimes if (k >= buflen) { 25255205Speter#ifdef _KERNEL 253177003Srwatson struct mbuf *m; 2541541Srgrimes 2551541Srgrimes if (buflen != 0) 256182455Sjkim return (0); 2571541Srgrimes m = (struct mbuf *)p; 2581541Srgrimes MINDEX(m, k); 2591541Srgrimes A = mtod(m, u_char *)[k]; 2601541Srgrimes continue; 2611541Srgrimes#else 262182455Sjkim return (0); 2631541Srgrimes#endif 2641541Srgrimes } 2651541Srgrimes A = p[k]; 2661541Srgrimes continue; 2671541Srgrimes 2681541Srgrimes case BPF_LD|BPF_W|BPF_LEN: 2691541Srgrimes A = wirelen; 2701541Srgrimes continue; 2711541Srgrimes 2721541Srgrimes case BPF_LDX|BPF_W|BPF_LEN: 2731541Srgrimes X = wirelen; 2741541Srgrimes continue; 2751541Srgrimes 2761541Srgrimes case BPF_LD|BPF_W|BPF_IND: 2771541Srgrimes k = X + pc->k; 27845574Seivind if (pc->k > buflen || X > buflen - pc->k || 27945574Seivind sizeof(int32_t) > buflen - k) { 28055205Speter#ifdef _KERNEL 2811541Srgrimes int merr; 2821541Srgrimes 2831541Srgrimes if (buflen != 0) 284177003Srwatson return (0); 2851541Srgrimes A = m_xword((struct mbuf *)p, k, &merr); 2861541Srgrimes if (merr != 0) 287177003Srwatson return (0); 2881541Srgrimes continue; 2891541Srgrimes#else 290177003Srwatson return (0); 2911541Srgrimes#endif 2921541Srgrimes } 2931541Srgrimes#ifdef BPF_ALIGN 29440779Sdfr if (((intptr_t)(p + k) & 3) != 0) 2951541Srgrimes A = EXTRACT_LONG(&p[k]); 2961541Srgrimes else 2971541Srgrimes#endif 29840779Sdfr A = ntohl(*(int32_t *)(p + k)); 2991541Srgrimes continue; 3001541Srgrimes 3011541Srgrimes case BPF_LD|BPF_H|BPF_IND: 3021541Srgrimes k = X + pc->k; 30345574Seivind if (X > buflen || pc->k > buflen - X || 30445574Seivind sizeof(int16_t) > buflen - k) { 30555205Speter#ifdef _KERNEL 3061541Srgrimes int merr; 3071541Srgrimes 3081541Srgrimes if (buflen != 0) 309182455Sjkim return (0); 3101541Srgrimes A = m_xhalf((struct mbuf *)p, k, &merr); 3111541Srgrimes if (merr != 0) 312177003Srwatson return (0); 3131541Srgrimes continue; 3141541Srgrimes#else 315177003Srwatson return (0); 3161541Srgrimes#endif 3171541Srgrimes } 3181541Srgrimes A = EXTRACT_SHORT(&p[k]); 3191541Srgrimes continue; 3201541Srgrimes 3211541Srgrimes case BPF_LD|BPF_B|BPF_IND: 3221541Srgrimes k = X + pc->k; 32348548Sbde if (pc->k >= buflen || X >= buflen - pc->k) { 32455205Speter#ifdef _KERNEL 325177003Srwatson struct mbuf *m; 3261541Srgrimes 3271541Srgrimes if (buflen != 0) 328182455Sjkim return (0); 3291541Srgrimes m = (struct mbuf *)p; 3301541Srgrimes MINDEX(m, k); 331159018Sdwmalone A = mtod(m, u_char *)[k]; 3321541Srgrimes continue; 3331541Srgrimes#else 334177003Srwatson return (0); 3351541Srgrimes#endif 3361541Srgrimes } 3371541Srgrimes A = p[k]; 3381541Srgrimes continue; 3391541Srgrimes 3401541Srgrimes case BPF_LDX|BPF_MSH|BPF_B: 3411541Srgrimes k = pc->k; 3421541Srgrimes if (k >= buflen) { 34355205Speter#ifdef _KERNEL 3441541Srgrimes register struct mbuf *m; 3451541Srgrimes 3461541Srgrimes if (buflen != 0) 347182455Sjkim return (0); 3481541Srgrimes m = (struct mbuf *)p; 3491541Srgrimes MINDEX(m, k); 350159018Sdwmalone X = (mtod(m, u_char *)[k] & 0xf) << 2; 3511541Srgrimes continue; 3521541Srgrimes#else 353182455Sjkim return (0); 3541541Srgrimes#endif 3551541Srgrimes } 3561541Srgrimes X = (p[pc->k] & 0xf) << 2; 3571541Srgrimes continue; 3581541Srgrimes 3591541Srgrimes case BPF_LD|BPF_IMM: 3601541Srgrimes A = pc->k; 3611541Srgrimes continue; 3621541Srgrimes 3631541Srgrimes case BPF_LDX|BPF_IMM: 3641541Srgrimes X = pc->k; 3651541Srgrimes continue; 3661541Srgrimes 3671541Srgrimes case BPF_LD|BPF_MEM: 3681541Srgrimes A = mem[pc->k]; 3691541Srgrimes continue; 3708876Srgrimes 3711541Srgrimes case BPF_LDX|BPF_MEM: 3721541Srgrimes X = mem[pc->k]; 3731541Srgrimes continue; 3741541Srgrimes 3751541Srgrimes case BPF_ST: 3761541Srgrimes mem[pc->k] = A; 3771541Srgrimes continue; 3781541Srgrimes 3791541Srgrimes case BPF_STX: 3801541Srgrimes mem[pc->k] = X; 3811541Srgrimes continue; 3821541Srgrimes 3831541Srgrimes case BPF_JMP|BPF_JA: 3841541Srgrimes pc += pc->k; 3851541Srgrimes continue; 3861541Srgrimes 3871541Srgrimes case BPF_JMP|BPF_JGT|BPF_K: 3881541Srgrimes pc += (A > pc->k) ? pc->jt : pc->jf; 3891541Srgrimes continue; 3901541Srgrimes 3911541Srgrimes case BPF_JMP|BPF_JGE|BPF_K: 3921541Srgrimes pc += (A >= pc->k) ? pc->jt : pc->jf; 3931541Srgrimes continue; 3941541Srgrimes 3951541Srgrimes case BPF_JMP|BPF_JEQ|BPF_K: 3961541Srgrimes pc += (A == pc->k) ? pc->jt : pc->jf; 3971541Srgrimes continue; 3981541Srgrimes 3991541Srgrimes case BPF_JMP|BPF_JSET|BPF_K: 4001541Srgrimes pc += (A & pc->k) ? pc->jt : pc->jf; 4011541Srgrimes continue; 4021541Srgrimes 4031541Srgrimes case BPF_JMP|BPF_JGT|BPF_X: 4041541Srgrimes pc += (A > X) ? pc->jt : pc->jf; 4051541Srgrimes continue; 4061541Srgrimes 4071541Srgrimes case BPF_JMP|BPF_JGE|BPF_X: 4081541Srgrimes pc += (A >= X) ? pc->jt : pc->jf; 4091541Srgrimes continue; 4101541Srgrimes 4111541Srgrimes case BPF_JMP|BPF_JEQ|BPF_X: 4121541Srgrimes pc += (A == X) ? pc->jt : pc->jf; 4131541Srgrimes continue; 4141541Srgrimes 4151541Srgrimes case BPF_JMP|BPF_JSET|BPF_X: 4161541Srgrimes pc += (A & X) ? pc->jt : pc->jf; 4171541Srgrimes continue; 4181541Srgrimes 4191541Srgrimes case BPF_ALU|BPF_ADD|BPF_X: 4201541Srgrimes A += X; 4211541Srgrimes continue; 4228876Srgrimes 4231541Srgrimes case BPF_ALU|BPF_SUB|BPF_X: 4241541Srgrimes A -= X; 4251541Srgrimes continue; 4268876Srgrimes 4271541Srgrimes case BPF_ALU|BPF_MUL|BPF_X: 4281541Srgrimes A *= X; 4291541Srgrimes continue; 4308876Srgrimes 4311541Srgrimes case BPF_ALU|BPF_DIV|BPF_X: 4321541Srgrimes if (X == 0) 433182455Sjkim return (0); 4341541Srgrimes A /= X; 4351541Srgrimes continue; 4368876Srgrimes 4371541Srgrimes case BPF_ALU|BPF_AND|BPF_X: 4381541Srgrimes A &= X; 4391541Srgrimes continue; 4408876Srgrimes 4411541Srgrimes case BPF_ALU|BPF_OR|BPF_X: 4421541Srgrimes A |= X; 4431541Srgrimes continue; 4441541Srgrimes 4451541Srgrimes case BPF_ALU|BPF_LSH|BPF_X: 4461541Srgrimes A <<= X; 4471541Srgrimes continue; 4481541Srgrimes 4491541Srgrimes case BPF_ALU|BPF_RSH|BPF_X: 4501541Srgrimes A >>= X; 4511541Srgrimes continue; 4521541Srgrimes 4531541Srgrimes case BPF_ALU|BPF_ADD|BPF_K: 4541541Srgrimes A += pc->k; 4551541Srgrimes continue; 4568876Srgrimes 4571541Srgrimes case BPF_ALU|BPF_SUB|BPF_K: 4581541Srgrimes A -= pc->k; 4591541Srgrimes continue; 4608876Srgrimes 4611541Srgrimes case BPF_ALU|BPF_MUL|BPF_K: 4621541Srgrimes A *= pc->k; 4631541Srgrimes continue; 4648876Srgrimes 4651541Srgrimes case BPF_ALU|BPF_DIV|BPF_K: 4661541Srgrimes A /= pc->k; 4671541Srgrimes continue; 4688876Srgrimes 4691541Srgrimes case BPF_ALU|BPF_AND|BPF_K: 4701541Srgrimes A &= pc->k; 4711541Srgrimes continue; 4728876Srgrimes 4731541Srgrimes case BPF_ALU|BPF_OR|BPF_K: 4741541Srgrimes A |= pc->k; 4751541Srgrimes continue; 4761541Srgrimes 4771541Srgrimes case BPF_ALU|BPF_LSH|BPF_K: 4781541Srgrimes A <<= pc->k; 4791541Srgrimes continue; 4801541Srgrimes 4811541Srgrimes case BPF_ALU|BPF_RSH|BPF_K: 4821541Srgrimes A >>= pc->k; 4831541Srgrimes continue; 4841541Srgrimes 4851541Srgrimes case BPF_ALU|BPF_NEG: 4861541Srgrimes A = -A; 4871541Srgrimes continue; 4881541Srgrimes 4891541Srgrimes case BPF_MISC|BPF_TAX: 4901541Srgrimes X = A; 4911541Srgrimes continue; 4921541Srgrimes 4931541Srgrimes case BPF_MISC|BPF_TXA: 4941541Srgrimes A = X; 4951541Srgrimes continue; 4961541Srgrimes } 4971541Srgrimes } 4981541Srgrimes} 4991541Srgrimes 50055205Speter#ifdef _KERNEL 501182454Sjkimstatic const u_short bpf_code_map[] = { 502182412Sjkim 0x10ff, /* 0x00-0x0f: 1111111100001000 */ 503182412Sjkim 0x3070, /* 0x10-0x1f: 0000111000001100 */ 504182412Sjkim 0x3131, /* 0x20-0x2f: 1000110010001100 */ 505182412Sjkim 0x3031, /* 0x30-0x3f: 1000110000001100 */ 506182412Sjkim 0x3131, /* 0x40-0x4f: 1000110010001100 */ 507182412Sjkim 0x1011, /* 0x50-0x5f: 1000100000001000 */ 508182412Sjkim 0x1013, /* 0x60-0x6f: 1100100000001000 */ 509182412Sjkim 0x1010, /* 0x70-0x7f: 0000100000001000 */ 510182412Sjkim 0x0093, /* 0x80-0x8f: 1100100100000000 */ 511182412Sjkim 0x0000, /* 0x90-0x9f: 0000000000000000 */ 512182412Sjkim 0x0000, /* 0xa0-0xaf: 0000000000000000 */ 513182412Sjkim 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 514182412Sjkim 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 515182412Sjkim 0x0000, /* 0xd0-0xdf: 0000000000000000 */ 516182412Sjkim 0x0000, /* 0xe0-0xef: 0000000000000000 */ 517182412Sjkim 0x0000 /* 0xf0-0xff: 0000000000000000 */ 518182412Sjkim}; 519182412Sjkim 520182454Sjkim#define BPF_VALIDATE_CODE(c) \ 521182454Sjkim ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) 522182454Sjkim 5231541Srgrimes/* 5241541Srgrimes * Return true if the 'fcode' is a valid filter program. 5251541Srgrimes * The constraints are that each jump be forward and to a valid 5268876Srgrimes * code. The code must terminate with either an accept or reject. 5271541Srgrimes * 5281541Srgrimes * The kernel needs to be able to verify an application's filter code. 5291541Srgrimes * Otherwise, a bogus program could easily crash the system. 5301541Srgrimes */ 5311541Srgrimesint 532182455Sjkimbpf_validate(const struct bpf_insn *f, int len) 5331541Srgrimes{ 5341541Srgrimes register int i; 53554038Sarchie register const struct bpf_insn *p; 5361541Srgrimes 537153996Sjkim /* Do not accept negative length filter. */ 538153996Sjkim if (len < 0) 539182455Sjkim return (0); 540153996Sjkim 541153996Sjkim /* An empty filter means accept all. */ 542153996Sjkim if (len == 0) 543182455Sjkim return (1); 544153221Sjkim 5451541Srgrimes for (i = 0; i < len; ++i) { 546182412Sjkim p = &f[i]; 5471541Srgrimes /* 548182412Sjkim * Check that the code is valid. 549182412Sjkim */ 550182454Sjkim if (!BPF_VALIDATE_CODE(p->code)) 551182455Sjkim return (0); 552182412Sjkim /* 5538876Srgrimes * Check that that jumps are forward, and within 5541541Srgrimes * the code block. 5551541Srgrimes */ 5561541Srgrimes if (BPF_CLASS(p->code) == BPF_JMP) { 557182425Sjkim register u_int offset; 5581541Srgrimes 559182454Sjkim if (p->code == (BPF_JMP|BPF_JA)) 560182425Sjkim offset = p->k; 561182425Sjkim else 562182425Sjkim offset = p->jt > p->jf ? p->jt : p->jf; 563182425Sjkim if (offset >= (u_int)(len - i) - 1) 564182455Sjkim return (0); 565182454Sjkim continue; 5661541Srgrimes } 5671541Srgrimes /* 5681541Srgrimes * Check that memory operations use valid addresses. 5691541Srgrimes */ 570182454Sjkim if (p->code == BPF_ST || p->code == BPF_STX || 571182454Sjkim p->code == (BPF_LD|BPF_MEM) || 572182454Sjkim p->code == (BPF_LDX|BPF_MEM)) { 573182454Sjkim if (p->k >= BPF_MEMWORDS) 574182455Sjkim return (0); 575182454Sjkim continue; 576182454Sjkim } 5771541Srgrimes /* 5781541Srgrimes * Check for constant division by 0. 5791541Srgrimes */ 5801541Srgrimes if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) 581182455Sjkim return (0); 5821541Srgrimes } 583182455Sjkim return (BPF_CLASS(f[len - 1].code) == BPF_RET); 5841541Srgrimes} 5851541Srgrimes#endif 586