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.9 91/01/30 18:21:54 mccanne Exp $ (LBL)"; 24 #endif 25 26 #include <sys/types.h> 27 #include <netinet/in.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 pointed to by 'pc' on the 52 * packet pointed to by 'p'. 'wirelen' is the length of actual 53 * packet received by the interface. 'buflen' is the amount of 54 * contiguous data. The return value is the return value of the 55 * filter program, or 0 on an error. 56 */ 57 u_int 58 bpf_filter(pc, p, wirelen, buflen) 59 register struct bpf_insn *pc; 60 register u_char *p; 61 u_int wirelen; 62 u_int buflen; 63 { 64 #define JUMP(delta) pc += (delta) 65 #define BR(cond) JUMP((cond) ? pc->jt : pc->jf) 66 67 register long A, X; 68 long mem[BPF_MEMWORDS]; 69 70 if (pc == 0) 71 /* 72 * No filter means accept all. 73 */ 74 return 1; 75 76 #ifdef lint 77 A = 0; 78 X = 0; 79 #endif 80 81 while (1) { 82 83 switch (pc->code) { 84 85 default: 86 #ifdef KERNEL 87 return 0; 88 #else 89 abort(); 90 #endif 91 case RetOp: 92 return (u_int)pc->k; 93 94 case RetAOp: 95 return (u_int)A; 96 97 case LdOp: 98 if (pc->k + sizeof(long) > buflen) 99 return 0; 100 A = EXTRACT_LONG(&p[pc->k]); 101 break; 102 103 case LdHOp: 104 if (pc->k + sizeof(short) > buflen) 105 return 0; 106 A = EXTRACT_SHORT(&p[pc->k]); 107 break; 108 109 case LdBOp: 110 if (pc->k >= buflen) 111 return 0; 112 A = p[pc->k]; 113 break; 114 115 case LdLenOp: 116 A = wirelen; 117 break; 118 119 case ILdOp: 120 if (X + pc->k + sizeof(long) > buflen) 121 return 0; 122 A = EXTRACT_LONG(&p[X + pc->k]); 123 break; 124 125 case ILdHOp: 126 if (X + pc->k + sizeof(short) > buflen) 127 return 0; 128 A = EXTRACT_SHORT(&p[X + pc->k]); 129 break; 130 131 case ILdBOp: 132 if (X + pc->k >= buflen) 133 return 0; 134 A = p[X + pc->k]; 135 break; 136 137 case LdIOp: 138 A = pc->k; 139 break; 140 141 case LdXIOp: 142 X = pc->k; 143 break; 144 145 case LdxmsOp: 146 if (pc->k >= buflen) 147 return 0; 148 X = (p[pc->k] & 0xf) << 2; 149 break; 150 151 case TaxOp: 152 X = A; 153 break; 154 155 case TxaOp: 156 A = X; 157 break; 158 159 case StmOp: 160 mem[pc->k] = A; 161 break; 162 163 case LdmOp: 164 A = mem[pc->k]; 165 break; 166 167 case StmXOp: 168 mem[pc->k] = X; 169 break; 170 171 case LdmXOp: 172 X = mem[pc->k]; 173 break; 174 175 case NopOp: 176 break; 177 178 case GTOp: 179 BR(A > pc->k); 180 continue; 181 182 case GEOp: 183 BR(A >= pc->k); 184 continue; 185 186 case EQOp: 187 BR(A == pc->k); 188 continue; 189 190 case AddXOp: 191 A += X; 192 break; 193 194 case SubXOp: 195 A -= X; 196 break; 197 198 case MulXOp: 199 A *= X; 200 break; 201 202 case DivXOp: 203 if (X == 0) 204 return 0; 205 A /= X; 206 break; 207 208 case AndXOp: 209 A &= X; 210 break; 211 212 case OrXOp: 213 A |= X; 214 break; 215 216 case LshXOp: 217 A <<= X; 218 break; 219 220 case RshXOp: 221 A >>= X; 222 break; 223 224 case AddIOp: 225 A += pc->k; 226 break; 227 228 case SubIOp: 229 A -= pc->k; 230 break; 231 232 case MulIOp: 233 A *= pc->k; 234 break; 235 236 case DivIOp: 237 if (pc->k == 0) 238 return 0; 239 A /= pc->k; 240 break; 241 242 case AndIOp: 243 A &= pc->k; 244 break; 245 246 case OrIOp: 247 A |= pc->k; 248 break; 249 250 case LshIOp: 251 A <<= pc->k; 252 break; 253 254 case RshIOp: 255 A >>= pc->k; 256 break; 257 258 case NegOp: 259 A = -A; 260 break; 261 } 262 ++pc; 263 } 264 } 265 266 #ifdef KERNEL 267 /* 268 * Return true if the 'fcode' is a valid filter program. 269 * The constraints are that each jump be forward and to a valid 270 * code. The code must terminate with either an accept or reject. 271 * 'valid' is an array for use by the routine (it must be at least 272 * 'len' bytes long). 273 * 274 * The kernel needs to be able to verify an application's filter code. 275 * Otherwise, a bogus program could easily crash the system. 276 */ 277 int 278 bpf_validate(fcode, len) 279 struct bpf_insn *fcode; 280 int len; 281 { 282 struct bpf_insn *p; 283 int i; 284 285 p = fcode; 286 for (i = 0; i < len; ++p, ++i) 287 if (!BPF_VALIDCODE(p->code)) 288 return 0; 289 p = fcode; 290 for (i = 0; i < len; ++p, ++i) { 291 /* 292 * Check that that jumps are forward, and within 293 * the code block. 294 */ 295 if (BPF_ISJUMP(p->code) && 296 (p->jt <= 0 || i + p->jt >= len || 297 p->jf <= 0 || i + p->jf >= len)) 298 return 0; 299 /* 300 * Check that memory operations use valid addresses. 301 */ 302 switch (p->code) { 303 case StmOp: 304 case StmXOp: 305 case LdmOp: 306 case LdmXOp: 307 if (p->k >= BPF_MEMWORDS || p->k < 0) 308 return 0; 309 } 310 } 311 return BPF_ISLEAF(fcode[len - 1].code); 312 } 313 #endif 314