1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 #if !(defined(lint) || defined(KERNEL)) 22 static char rcsid[] = 23 "@(#) $Header: bpf_filter.c,v 1.10 91/04/24 22:07:07 mccanne Locked $ (LBL)"; 24 #endif 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <net/bpf.h> 30 31 #if defined(sparc) || defined(mips) 32 #define ALIGN 33 #endif 34 35 #ifndef ALIGN 36 #define EXTRACT_SHORT(p) (ntohs(*(u_short *)p)) 37 #define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) 38 #else 39 #define EXTRACT_SHORT(p)\ 40 ((u_short)\ 41 (*((u_char *)p+0)<<8|\ 42 *((u_char *)p+1)<<0)) 43 #define EXTRACT_LONG(p)\ 44 (*((u_char *)p+0)<<24|\ 45 *((u_char *)p+1)<<16|\ 46 *((u_char *)p+2)<<8|\ 47 *((u_char *)p+3)<<0) 48 #endif 49 50 /* 51 * Execute the filter program starting at pc on the packet p 52 * wirelen is the length of the original packet 53 * buflen is the amount of data present 54 */ 55 u_int 56 bpf_filter(pc, p, wirelen, buflen) 57 register struct bpf_insn *pc; 58 register u_char *p; 59 u_int wirelen; 60 register u_int buflen; 61 { 62 register long A, X; 63 register int k; 64 long mem[BPF_MEMWORDS]; 65 66 if (pc == 0) 67 /* 68 * No filter means accept all. 69 */ 70 return (u_int)-1; 71 #ifdef lint 72 A = 0; 73 X = 0; 74 #endif 75 --pc; 76 while (1) { 77 ++pc; 78 switch (pc->code) { 79 80 default: 81 #ifdef KERNEL 82 return 0; 83 #else 84 abort(); 85 #endif 86 case BPF_RET|BPF_K: 87 return (u_int)pc->k; 88 89 case BPF_RET|BPF_A: 90 return (u_int)A; 91 92 case BPF_LD|BPF_W|BPF_ABS: 93 k = pc->k; 94 if (k + sizeof(long) > buflen) 95 return 0; 96 #ifdef ALIGN 97 if (((int)(p + k) & 3) != 0) 98 A = EXTRACT_LONG(&p[k]); 99 else 100 #endif 101 A = *(long *)(p + k); 102 break; 103 104 case BPF_LD|BPF_H|BPF_ABS: 105 k = pc->k; 106 if (k + sizeof(short) > buflen) 107 return 0; 108 A = EXTRACT_SHORT(&p[k]); 109 break; 110 111 case BPF_LD|BPF_B|BPF_ABS: 112 k = pc->k; 113 if (k >= buflen) 114 return 0; 115 A = p[k]; 116 break; 117 118 case BPF_LD|BPF_W|BPF_LEN: 119 A = wirelen; 120 break; 121 122 case BPF_LDX|BPF_W|BPF_LEN: 123 X = wirelen; 124 break; 125 126 case BPF_LD|BPF_W|BPF_IND: 127 k = X + pc->k; 128 if (k + sizeof(long) > buflen) 129 return 0; 130 #ifdef ALIGN 131 if (((int)(p + k) & 3) != 0) 132 A = EXTRACT_LONG(&p[k]); 133 else 134 #endif 135 A = *(long *)(p + k); 136 break; 137 138 case BPF_LD|BPF_H|BPF_IND: 139 k = X + pc->k; 140 if (k + sizeof(short) > buflen) 141 return 0; 142 A = EXTRACT_SHORT(&p[k]); 143 break; 144 145 case BPF_LD|BPF_B|BPF_IND: 146 k = X + pc->k; 147 if (k >= buflen) 148 return 0; 149 A = p[k]; 150 break; 151 152 case BPF_LD|BPF_IMM: 153 A = pc->k; 154 break; 155 156 case BPF_LDX|BPF_IMM: 157 X = pc->k; 158 break; 159 160 case BPF_LDX|BPF_MSH|BPF_B: 161 if (pc->k >= buflen) 162 return 0; 163 X = (p[pc->k] & 0xf) << 2; 164 break; 165 166 case BPF_LD|BPF_MEM: 167 A = mem[pc->k]; 168 break; 169 170 case BPF_LDX|BPF_MEM: 171 X = mem[pc->k]; 172 break; 173 174 case BPF_ST: 175 mem[pc->k] = A; 176 break; 177 178 case BPF_STX: 179 mem[pc->k] = X; 180 break; 181 182 case BPF_JMP|BPF_JA: 183 pc += pc->k; 184 break; 185 186 case BPF_JMP|BPF_JGT|BPF_K: 187 pc += (A > pc->k) ? pc->jt : pc->jf; 188 break; 189 190 case BPF_JMP|BPF_JGE|BPF_K: 191 pc += (A >= pc->k) ? pc->jt : pc->jf; 192 break; 193 194 case BPF_JMP|BPF_JEQ|BPF_K: 195 pc += (A == pc->k) ? pc->jt : pc->jf; 196 break; 197 198 case BPF_JMP|BPF_JSET|BPF_K: 199 pc += (A & pc->k) ? pc->jt : pc->jf; 200 break; 201 202 case BPF_JMP|BPF_JGT|BPF_X: 203 pc += (A > X) ? pc->jt : pc->jf; 204 break; 205 206 case BPF_JMP|BPF_JGE|BPF_X: 207 pc += (A >= X) ? pc->jt : pc->jf; 208 break; 209 210 case BPF_JMP|BPF_JEQ|BPF_X: 211 pc += (A == X) ? pc->jt : pc->jf; 212 break; 213 214 case BPF_JMP|BPF_JSET|BPF_X: 215 pc += (A & X) ? pc->jt : pc->jf; 216 break; 217 218 case BPF_ALU|BPF_ADD|BPF_X: 219 A += X; 220 break; 221 222 case BPF_ALU|BPF_SUB|BPF_X: 223 A -= X; 224 break; 225 226 case BPF_ALU|BPF_MUL|BPF_X: 227 A *= X; 228 break; 229 230 case BPF_ALU|BPF_DIV|BPF_X: 231 if (X == 0) 232 return 0; 233 A /= X; 234 break; 235 236 case BPF_ALU|BPF_AND|BPF_X: 237 A &= X; 238 break; 239 240 case BPF_ALU|BPF_OR|BPF_X: 241 A |= X; 242 break; 243 244 case BPF_ALU|BPF_LSH|BPF_X: 245 A <<= X; 246 break; 247 248 case BPF_ALU|BPF_RSH|BPF_X: 249 A >>= X; 250 break; 251 252 case BPF_ALU|BPF_ADD|BPF_K: 253 A += pc->k; 254 break; 255 256 case BPF_ALU|BPF_SUB|BPF_K: 257 A -= pc->k; 258 break; 259 260 case BPF_ALU|BPF_MUL|BPF_K: 261 A *= pc->k; 262 break; 263 264 case BPF_ALU|BPF_DIV|BPF_K: 265 A /= pc->k; 266 break; 267 268 case BPF_ALU|BPF_AND|BPF_K: 269 A &= pc->k; 270 break; 271 272 case BPF_ALU|BPF_OR|BPF_K: 273 A |= pc->k; 274 break; 275 276 case BPF_ALU|BPF_LSH|BPF_K: 277 A <<= pc->k; 278 break; 279 280 case BPF_ALU|BPF_RSH|BPF_K: 281 A >>= pc->k; 282 break; 283 284 case BPF_ALU|BPF_NEG: 285 A = -A; 286 break; 287 288 case BPF_MISC|BPF_TAX: 289 X = A; 290 break; 291 292 case BPF_MISC|BPF_TXA: 293 A = X; 294 break; 295 } 296 } 297 } 298 299 #ifdef KERNEL 300 /* 301 * Return true if the 'fcode' is a valid filter program. 302 * The constraints are that each jump be forward and to a valid 303 * code. The code must terminate with either an accept or reject. 304 * 'valid' is an array for use by the routine (it must be at least 305 * 'len' bytes long). 306 * 307 * The kernel needs to be able to verify an application's filter code. 308 * Otherwise, a bogus program could easily crash the system. 309 */ 310 int 311 bpf_validate(f, len) 312 struct bpf_insn *f; 313 int len; 314 { 315 register int i; 316 register struct bpf_insn *p; 317 318 for (i = 0; i < len; ++i) { 319 /* 320 * Check that that jumps are forward, and within 321 * the code block. 322 */ 323 p = &f[i]; 324 if (BPF_CLASS(p->code) == BPF_JMP) { 325 register int from = i + 1; 326 327 if (BPF_OP(p->code) == BPF_JA) { 328 if (from + p->k >= len) 329 return 0; 330 } 331 else if (from + p->jt >= len || from + p->jf >= len) 332 return 0; 333 } 334 /* 335 * Check that memory operations use valid addresses. 336 */ 337 if ((BPF_CLASS(p->code) == BPF_ST || 338 (BPF_CLASS(p->code) == BPF_LD && 339 (p->code & 0xe0) == BPF_MEM)) && 340 (p->k >= BPF_MEMWORDS || p->k < 0)) 341 return 0; 342 /* 343 * Check for constant division by 0. 344 */ 345 if (p->code == BPF_ALU|BPF_DIV|BPF_K && p->k == 0) 346 return; 347 } 348 return BPF_CLASS(f[len - 1].code) == BPF_RET; 349 } 350 #endif 351