96e7e4cb44abd782c070aabd2f79aadae36a45a5
[reactos.git] / reactos / drivers / net / packet / win_bpf_filter_init.c
1 /*
2 * Copyright (c) 2001
3 * Politecnico di Torino. 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 Politecnico
13 * di Torino, 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 *
22 *
23 * Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
24 * The Regents of the University of California. All rights reserved.
25 *
26 * This code is derived from the Stanford/CMU enet packet filter,
27 * (net/enet.c) distributed as part of 4.3BSD, and code contributed
28 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
29 * Berkeley Laboratory.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59
60 #include "tme.h"
61 #include "win_bpf.h"
62
63 /*
64 * Initialize the filter machine
65 */
66 uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
67 {
68 register uint32 A, X;
69 int32 mem[BPF_MEMWORDS];
70 register int32 k;
71 uint32 *tmp;
72 uint16 *tmp2;
73 uint32 j;
74 if (pc == 0)
75 /*
76 * No filter means accept all.
77 */
78 return (uint32)-1;
79 A = 0;
80 X = 0;
81 --pc;
82 while (1) {
83 ++pc;
84 switch (pc->code) {
85
86 default:
87 return 0;
88
89 /* RET INSTRUCTIONS */
90 case BPF_RET|BPF_K:
91 return (uint32)pc->k;
92
93 case BPF_RET|BPF_A:
94 return (uint32)A;
95 /* END RET INSTRUCTIONS */
96
97 /* LD NO PACKET INSTRUCTIONS */
98 case BPF_LD|BPF_IMM:
99 A = pc->k;
100 continue;
101
102 case BPF_LDX|BPF_IMM:
103 X = pc->k;
104 continue;
105
106 case BPF_LD|BPF_MEM:
107 A = mem[pc->k];
108 continue;
109
110 case BPF_LDX|BPF_MEM:
111 X = mem[pc->k];
112 continue;
113
114 case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
115 A= mem_ex->buffer[pc->k];
116 continue;
117
118 case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
119 X= mem_ex->buffer[pc->k];
120 continue;
121
122 case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
123 tmp2=(uint16*)&mem_ex->buffer[pc->k];
124 #ifndef __GNUC__
125 __asm
126 {
127 push eax
128 push ebx
129 mov ebx,tmp2
130 xor eax, eax
131 mov ax, [ebx]
132 bswap eax
133 mov A, eax
134 pop ebx
135 pop eax
136 }
137 #else
138 #endif
139 continue;
140
141 case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
142 tmp2=(uint16*)&mem_ex->buffer[pc->k];
143 #ifndef __GNUC__
144 __asm
145 {
146 push eax
147 push ebx
148 mov ebx,tmp2
149 xor eax, eax
150 mov ax, [ebx]
151 bswap eax
152 mov X, eax
153 pop ebx
154 pop eax
155 }
156 #else
157 #endif
158 continue;
159
160 case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
161 tmp=(uint32*)&mem_ex->buffer[pc->k];
162 #ifndef __GNUC__
163 __asm
164 {
165 push eax
166 push ebx
167 mov ebx,tmp
168 mov eax, [ebx]
169 bswap eax
170 mov A, eax
171 pop ebx
172 pop eax
173 }
174 #else
175 #endif
176 continue;
177
178 case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
179 tmp=(uint32*)&mem_ex->buffer[pc->k];
180 #ifndef __GNUC__
181 __asm
182 {
183 push eax
184 push ebx
185 mov ebx,tmp
186 mov eax, [ebx]
187 bswap eax
188 mov X, eax
189 pop ebx
190 pop eax
191 }
192 #else
193 #endif
194 continue;
195
196 case BPF_LD|BPF_MEM_EX_IND|BPF_B:
197 k = X + pc->k;
198 if ((int32)k>= (int32)mem_ex->size) {
199 return 0;
200 }
201 A= mem_ex->buffer[k];
202 continue;
203
204 case BPF_LD|BPF_MEM_EX_IND|BPF_H:
205 k = X + pc->k;
206 if ((int32)(k+1)>= (int32)mem_ex->size) {
207 return 0;
208 }
209 tmp2=(uint16*)&mem_ex->buffer[k];
210 #ifndef __GNUC__
211 __asm
212 {
213 push eax
214 push ebx
215 mov ebx,tmp2
216 xor eax, eax
217 mov ax, [ebx]
218 bswap eax
219 mov A, eax
220 pop ebx
221 pop eax
222 }
223 #else
224 #endif
225 continue;
226
227 case BPF_LD|BPF_MEM_EX_IND|BPF_W:
228 k = X + pc->k;
229 if ((int32)(k+3)>= (int32)mem_ex->size) {
230 return 0;
231 }
232 tmp=(uint32*)&mem_ex->buffer[k];
233 #ifndef __GNUC__
234 __asm
235 {
236 push eax
237 push ebx
238 mov ebx,tmp
239 mov eax, [ebx]
240 bswap eax
241 mov A, eax
242 pop ebx
243 pop eax
244 }
245 #else
246 #endif
247 continue;
248 /* END LD NO PACKET INSTRUCTIONS */
249
250 /* STORE INSTRUCTIONS */
251 case BPF_ST:
252 mem[pc->k] = A;
253 continue;
254
255 case BPF_STX:
256 mem[pc->k] = X;
257 continue;
258
259 case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
260 mem_ex->buffer[pc->k]=(uint8)A;
261 continue;
262
263 case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
264 mem_ex->buffer[pc->k]=(uint8)X;
265 continue;
266
267 case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
268 tmp=(uint32*)&mem_ex->buffer[pc->k];
269 #ifndef __GNUC__
270 __asm
271 {
272 push eax
273 push ebx
274 mov ebx, tmp
275 mov eax, A
276 bswap eax
277 mov [ebx], eax
278 pop ebx
279 pop eax
280 }
281 #else
282 #endif
283 continue;
284
285 case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
286 tmp=(uint32*)&mem_ex->buffer[pc->k];
287 #ifndef __GNUC__
288 __asm
289 {
290 push eax
291 push ebx
292 mov ebx, tmp
293 mov eax, X
294 bswap eax
295 mov [ebx], eax
296 pop ebx
297 pop eax
298 }
299 #else
300 #endif
301 continue;
302
303 case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
304 tmp2=(uint16*)&mem_ex->buffer[pc->k];
305 #ifndef __GNUC__
306 __asm
307 {
308 push eax
309 push ebx
310 mov ebx, tmp2
311 mov eax, A
312 xchg ah, al
313 mov [ebx], ax
314 pop ebx
315 pop eax
316 }
317 #else
318 #endif
319 continue;
320
321 case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
322 tmp2=(uint16*)&mem_ex->buffer[pc->k];
323 #ifndef __GNUC__
324 __asm
325 {
326 push eax
327 push ebx
328 mov ebx, tmp2
329 mov eax, X
330 xchg ah, al
331 mov [ebx], ax
332 pop ebx
333 pop eax
334 }
335 #else
336 #endif
337 continue;
338
339 case BPF_ST|BPF_MEM_EX_IND|BPF_B:
340 mem_ex->buffer[pc->k+X]=(uint8)A;
341
342 case BPF_ST|BPF_MEM_EX_IND|BPF_W:
343 tmp=(uint32*)&mem_ex->buffer[pc->k+X];
344 #ifndef __GNUC__
345 __asm
346 {
347 push eax
348 push ebx
349 mov ebx, tmp
350 mov eax, A
351 bswap eax
352 mov [ebx], eax
353 pop ebx
354 pop eax
355 }
356 #else
357 #endif
358 continue;
359
360 case BPF_ST|BPF_MEM_EX_IND|BPF_H:
361 tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
362 #ifndef __GNUC__
363 __asm
364 {
365 push eax
366 push ebx
367 mov ebx, tmp2
368 mov eax, A
369 xchg ah, al
370 mov [ebx], ax
371 pop ebx
372 pop eax
373 }
374 #else
375 #endif
376 continue;
377 /* END STORE INSTRUCTIONS */
378
379 /* JUMP INSTRUCTIONS */
380 case BPF_JMP|BPF_JA:
381 pc += pc->k;
382 continue;
383
384 case BPF_JMP|BPF_JGT|BPF_K:
385 pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
386 continue;
387
388 case BPF_JMP|BPF_JGE|BPF_K:
389 pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
390 continue;
391
392 case BPF_JMP|BPF_JEQ|BPF_K:
393 pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
394 continue;
395
396 case BPF_JMP|BPF_JSET|BPF_K:
397 pc += (A & pc->k) ? pc->jt : pc->jf;
398 continue;
399
400 case BPF_JMP|BPF_JGT|BPF_X:
401 pc += (A > X) ? pc->jt : pc->jf;
402 continue;
403
404 case BPF_JMP|BPF_JGE|BPF_X:
405 pc += (A >= X) ? pc->jt : pc->jf;
406 continue;
407
408 case BPF_JMP|BPF_JEQ|BPF_X:
409 pc += (A == X) ? pc->jt : pc->jf;
410 continue;
411
412 case BPF_JMP|BPF_JSET|BPF_X:
413 pc += (A & X) ? pc->jt : pc->jf;
414 continue;
415 /* END JUMP INSTRUCTIONS */
416
417 /* ARITHMETIC INSTRUCTIONS */
418 case BPF_ALU|BPF_ADD|BPF_X:
419 A += X;
420 continue;
421
422 case BPF_ALU|BPF_SUB|BPF_X:
423 A -= X;
424 continue;
425
426 case BPF_ALU|BPF_MUL|BPF_X:
427 A *= X;
428 continue;
429
430 case BPF_ALU|BPF_DIV|BPF_X:
431 if (X == 0)
432 return 0;
433 A /= X;
434 continue;
435
436 case BPF_ALU|BPF_AND|BPF_X:
437 A &= X;
438 continue;
439
440 case BPF_ALU|BPF_OR|BPF_X:
441 A |= X;
442 continue;
443
444 case BPF_ALU|BPF_LSH|BPF_X:
445 A <<= X;
446 continue;
447
448 case BPF_ALU|BPF_RSH|BPF_X:
449 A >>= X;
450 continue;
451
452 case BPF_ALU|BPF_ADD|BPF_K:
453 A += pc->k;
454 continue;
455
456 case BPF_ALU|BPF_SUB|BPF_K:
457 A -= pc->k;
458 continue;
459
460 case BPF_ALU|BPF_MUL|BPF_K:
461 A *= pc->k;
462 continue;
463
464 case BPF_ALU|BPF_DIV|BPF_K:
465 A /= pc->k;
466 continue;
467
468 case BPF_ALU|BPF_AND|BPF_K:
469 A &= pc->k;
470 continue;
471
472 case BPF_ALU|BPF_OR|BPF_K:
473 A |= pc->k;
474 continue;
475
476 case BPF_ALU|BPF_LSH|BPF_K:
477 A <<= pc->k;
478 continue;
479
480 case BPF_ALU|BPF_RSH|BPF_K:
481 A >>= pc->k;
482 continue;
483
484 case BPF_ALU|BPF_NEG:
485 (int32)A = -((int32)A);
486 continue;
487 /* ARITHMETIC INSTRUCTIONS */
488
489 /* MISC INSTRUCTIONS */
490 case BPF_MISC|BPF_TAX:
491 X = A;
492 continue;
493
494 case BPF_MISC|BPF_TXA:
495 A = X;
496 continue;
497 /* END MISC INSTRUCTIONS */
498
499 /* TME INSTRUCTIONS */
500 case BPF_MISC|BPF_TME|BPF_LOOKUP:
501 j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
502 if (j==TME_ERROR)
503 return 0;
504 pc += (j == TME_TRUE) ? pc->jt : pc->jf;
505 continue;
506
507 case BPF_MISC|BPF_TME|BPF_EXECUTE:
508 if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
509 return 0;
510 continue;
511
512 case BPF_MISC|BPF_TME|BPF_INIT:
513 if (init_tme_block(tme,pc->k)==TME_ERROR)
514 return 0;
515 continue;
516
517 case BPF_MISC|BPF_TME|BPF_VALIDATE:
518 if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
519 return 0;
520 continue;
521
522 case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
523 if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
524 return 0;
525 continue;
526
527 case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
528 if (set_active_tme_block(tme,pc->k)==TME_ERROR)
529 return 0;
530 continue;
531
532 case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
533 if (set_active_tme_block(tme,pc->k)==TME_ERROR)
534 return 0;
535 continue;
536 case BPF_MISC|BPF_TME|BPF_SET_WORKING:
537 if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
538 return 0;
539 tme->working=pc->k;
540 continue;
541
542
543
544 case BPF_MISC|BPF_TME|BPF_RESET:
545 if (reset_tme(tme)==TME_ERROR)
546 return 0;
547 continue;
548
549 case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
550 if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
551 return 0;
552 A=j;
553 continue;
554
555 case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
556 if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
557 return 0;
558 continue;
559
560 case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
561 set_autodeletion(&tme->block_data[tme->working],pc->k);
562 continue;
563
564 /* END TME INSTRUCTIONS */
565
566 }
567 }
568 }
569