minor corrections by M.Taguchi
[reactos.git] / reactos / drivers / net / npf / 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 asm("push %%eax;"
139 "push %%ebx;"
140 "mov %1,%%ebx;"
141 "xor %%eax, %%eax;"
142 "mov (%%ebx), %%ax;"
143 "bswap %%eax;"
144 "mov %%eax, %0;"
145 "pop %%ebx;"
146 "pop %%eax;"
147 :"=a"(A),"=c"(tmp2): );
148 #endif
149 continue;
150
151 case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
152 tmp2=(uint16*)&mem_ex->buffer[pc->k];
153 #ifndef __GNUC__
154 __asm
155 {
156 push eax
157 push ebx
158 mov ebx,tmp2
159 xor eax, eax
160 mov ax, [ebx]
161 bswap eax
162 mov X, eax
163 pop ebx
164 pop eax
165 }
166 #else
167 asm("push %%eax;"
168 "push %%ebx;"
169 "mov %1,%%ebx;"
170 "xor %%eax, %%eax;"
171 "mov (%%ebx), %%ax;"
172 "bswap %%eax;"
173 "mov %%eax, %0;"
174 "pop %%ebx;"
175 "pop %%eax;"
176 :"=a"(X),"=c"(tmp2): );
177 #endif
178 continue;
179
180 case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
181 tmp=(uint32*)&mem_ex->buffer[pc->k];
182 #ifndef __GNUC__
183 __asm
184 {
185 push eax
186 push ebx
187 mov ebx,tmp
188 mov eax, [ebx]
189 bswap eax
190 mov A, eax
191 pop ebx
192 pop eax
193 }
194 #else
195 asm("push %%eax;"
196 "push %%ebx;"
197 "mov %1,%%ebx;"
198 "xor %%eax, %%eax;"
199 "mov (%%ebx), %%ax;"
200 "bswap %%eax;"
201 "mov %%eax, %0;"
202 "pop %%ebx;"
203 "pop %%eax;"
204 :"=a"(A),"=c"(tmp): );
205 #endif
206 continue;
207
208 case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
209 tmp=(uint32*)&mem_ex->buffer[pc->k];
210 #ifndef __GNUC__
211 __asm
212 {
213 push eax
214 push ebx
215 mov ebx,tmp
216 mov eax, [ebx]
217 bswap eax
218 mov X, eax
219 pop ebx
220 pop eax
221 }
222 #else
223 asm("push %%eax;"
224 "push %%ebx;"
225 "mov %1,%%ebx;"
226 "xor %%eax, %%eax;"
227 "mov (%%ebx), %%ax;"
228 "bswap %%eax;"
229 "mov %%eax, %0;"
230 "pop %%ebx;"
231 "pop %%eax;"
232 :"=a"(X),"=c"(tmp): );
233 #endif
234 continue;
235
236 case BPF_LD|BPF_MEM_EX_IND|BPF_B:
237 k = X + pc->k;
238 if ((int32)k>= (int32)mem_ex->size) {
239 return 0;
240 }
241 A= mem_ex->buffer[k];
242 continue;
243
244 case BPF_LD|BPF_MEM_EX_IND|BPF_H:
245 k = X + pc->k;
246 if ((int32)(k+1)>= (int32)mem_ex->size) {
247 return 0;
248 }
249 tmp2=(uint16*)&mem_ex->buffer[k];
250 #ifndef __GNUC__
251 __asm
252 {
253 push eax
254 push ebx
255 mov ebx,tmp2
256 xor eax, eax
257 mov ax, [ebx]
258 bswap eax
259 mov A, eax
260 pop ebx
261 pop eax
262 }
263 #else
264 asm("push %%eax;"
265 "push %%ebx;"
266 "mov %1,%%ebx;"
267 "xor %%eax, %%eax;"
268 "mov (%%ebx), %%ax;"
269 "bswap %%eax;"
270 "mov %%eax, %0;"
271 "pop %%ebx;"
272 "pop %%eax;"
273 :"=a"(A),"=c"(tmp2): );
274 #endif
275 continue;
276
277 case BPF_LD|BPF_MEM_EX_IND|BPF_W:
278 k = X + pc->k;
279 if ((int32)(k+3)>= (int32)mem_ex->size) {
280 return 0;
281 }
282 tmp=(uint32*)&mem_ex->buffer[k];
283 #ifndef __GNUC__
284 __asm
285 {
286 push eax
287 push ebx
288 mov ebx,tmp
289 mov eax, [ebx]
290 bswap eax
291 mov A, eax
292 pop ebx
293 pop eax
294 }
295 #else
296 asm("push %%eax;"
297 "push %%ebx;"
298 "mov %1,%%ebx;"
299 "xor %%eax, %%eax;"
300 "mov (%%ebx), %%ax;"
301 "bswap %%eax;"
302 "mov %%eax, %0;"
303 "pop %%ebx;"
304 "pop %%eax;"
305 :"=a"(A),"=c"(tmp): );
306 #endif
307 continue;
308 /* END LD NO PACKET INSTRUCTIONS */
309
310 /* STORE INSTRUCTIONS */
311 case BPF_ST:
312 mem[pc->k] = A;
313 continue;
314
315 case BPF_STX:
316 mem[pc->k] = X;
317 continue;
318
319 case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
320 mem_ex->buffer[pc->k]=(uint8)A;
321 continue;
322
323 case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
324 mem_ex->buffer[pc->k]=(uint8)X;
325 continue;
326
327 case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
328 tmp=(uint32*)&mem_ex->buffer[pc->k];
329 #ifndef __GNUC__
330 __asm
331 {
332 push eax
333 push ebx
334 mov ebx, tmp
335 mov eax, A
336 bswap eax
337 mov [ebx], eax
338 pop ebx
339 pop eax
340 }
341 #else
342 asm("push %%eax;"
343 "push %%ebx;"
344 "mov %1,%%ebx;"
345 "xor %%eax, %%eax;"
346 "mov (%%ebx), %%ax;"
347 "bswap %%eax;"
348 "mov %%eax, %0;"
349 "pop %%ebx;"
350 "pop %%eax;"
351 :"=a"(A),"=c"(tmp): );
352 #endif
353 continue;
354
355 case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
356 tmp=(uint32*)&mem_ex->buffer[pc->k];
357 #ifndef __GNUC__
358 __asm
359 {
360 push eax
361 push ebx
362 mov ebx, tmp
363 mov eax, X
364 bswap eax
365 mov [ebx], eax
366 pop ebx
367 pop eax
368 }
369 #else
370 asm("push %%eax;"
371 "push %%ebx;"
372 "mov %1,%%ebx;"
373 "xor %%eax, %%eax;"
374 "mov (%%ebx), %%ax;"
375 "bswap %%eax;"
376 "mov %%eax, %0;"
377 "pop %%ebx;"
378 "pop %%eax;"
379 :"=a"(X),"=c"(tmp): );
380 #endif
381 continue;
382
383 case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
384 tmp2=(uint16*)&mem_ex->buffer[pc->k];
385 #ifndef __GNUC__
386 __asm
387 {
388 push eax
389 push ebx
390 mov ebx, tmp2
391 mov eax, A
392 xchg ah, al
393 mov [ebx], ax
394 pop ebx
395 pop eax
396 }
397 #else
398 asm("push %%eax;"
399 "push %%ebx;"
400 "mov %1,%%ebx;"
401 "xor %%eax, %%eax;"
402 "mov (%%ebx), %%ax;"
403 "bswap %%eax;"
404 "mov %%eax, %0;"
405 "pop %%ebx;"
406 "pop %%eax;"
407 :"=a"(A),"=c"(tmp2): );
408 #endif
409 continue;
410
411 case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
412 tmp2=(uint16*)&mem_ex->buffer[pc->k];
413 #ifndef __GNUC__
414 __asm
415 {
416 push eax
417 push ebx
418 mov ebx, tmp2
419 mov eax, X
420 xchg ah, al
421 mov [ebx], ax
422 pop ebx
423 pop eax
424 }
425 #else
426 asm("push %%eax;"
427 "push %%ebx;"
428 "mov %1,%%ebx;"
429 "xor %%eax, %%eax;"
430 "mov (%%ebx), %%ax;"
431 "bswap %%eax;"
432 "mov %%eax, %0;"
433 "pop %%ebx;"
434 "pop %%eax;"
435 :"=a"(X),"=c"(tmp2): );
436 #endif
437 continue;
438
439 case BPF_ST|BPF_MEM_EX_IND|BPF_B:
440 mem_ex->buffer[pc->k+X]=(uint8)A;
441
442 case BPF_ST|BPF_MEM_EX_IND|BPF_W:
443 tmp=(uint32*)&mem_ex->buffer[pc->k+X];
444 #ifndef __GNUC__
445 __asm
446 {
447 push eax
448 push ebx
449 mov ebx, tmp
450 mov eax, A
451 bswap eax
452 mov [ebx], eax
453 pop ebx
454 pop eax
455 }
456 #else
457 asm("push %%eax;"
458 "push %%ebx;"
459 "mov %1,%%ebx;"
460 "xor %%eax, %%eax;"
461 "mov (%%ebx), %%ax;"
462 "bswap %%eax;"
463 "mov %%eax, %0;"
464 "pop %%ebx;"
465 "pop %%eax;"
466 :"=a"(A),"=c"(tmp): );
467 #endif
468 continue;
469
470 case BPF_ST|BPF_MEM_EX_IND|BPF_H:
471 tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
472 #ifndef __GNUC__
473 __asm
474 {
475 push eax
476 push ebx
477 mov ebx, tmp2
478 mov eax, A
479 xchg ah, al
480 mov [ebx], ax
481 pop ebx
482 pop eax
483 }
484 #else
485 asm("push %%eax;"
486 "push %%ebx;"
487 "mov %1,%%ebx;"
488 "xor %%eax, %%eax;"
489 "mov (%%ebx), %%ax;"
490 "bswap %%eax;"
491 "mov %%eax, %0;"
492 "pop %%ebx;"
493 "pop %%eax;"
494 :"=a"(A),"=c"(tmp2): );
495 #endif
496 continue;
497 /* END STORE INSTRUCTIONS */
498
499 /* JUMP INSTRUCTIONS */
500 case BPF_JMP|BPF_JA:
501 pc += pc->k;
502 continue;
503
504 case BPF_JMP|BPF_JGT|BPF_K:
505 pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
506 continue;
507
508 case BPF_JMP|BPF_JGE|BPF_K:
509 pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
510 continue;
511
512 case BPF_JMP|BPF_JEQ|BPF_K:
513 pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
514 continue;
515
516 case BPF_JMP|BPF_JSET|BPF_K:
517 pc += (A & pc->k) ? pc->jt : pc->jf;
518 continue;
519
520 case BPF_JMP|BPF_JGT|BPF_X:
521 pc += (A > X) ? pc->jt : pc->jf;
522 continue;
523
524 case BPF_JMP|BPF_JGE|BPF_X:
525 pc += (A >= X) ? pc->jt : pc->jf;
526 continue;
527
528 case BPF_JMP|BPF_JEQ|BPF_X:
529 pc += (A == X) ? pc->jt : pc->jf;
530 continue;
531
532 case BPF_JMP|BPF_JSET|BPF_X:
533 pc += (A & X) ? pc->jt : pc->jf;
534 continue;
535 /* END JUMP INSTRUCTIONS */
536
537 /* ARITHMETIC INSTRUCTIONS */
538 case BPF_ALU|BPF_ADD|BPF_X:
539 A += X;
540 continue;
541
542 case BPF_ALU|BPF_SUB|BPF_X:
543 A -= X;
544 continue;
545
546 case BPF_ALU|BPF_MUL|BPF_X:
547 A *= X;
548 continue;
549
550 case BPF_ALU|BPF_DIV|BPF_X:
551 if (X == 0)
552 return 0;
553 A /= X;
554 continue;
555
556 case BPF_ALU|BPF_AND|BPF_X:
557 A &= X;
558 continue;
559
560 case BPF_ALU|BPF_OR|BPF_X:
561 A |= X;
562 continue;
563
564 case BPF_ALU|BPF_LSH|BPF_X:
565 A <<= X;
566 continue;
567
568 case BPF_ALU|BPF_RSH|BPF_X:
569 A >>= X;
570 continue;
571
572 case BPF_ALU|BPF_ADD|BPF_K:
573 A += pc->k;
574 continue;
575
576 case BPF_ALU|BPF_SUB|BPF_K:
577 A -= pc->k;
578 continue;
579
580 case BPF_ALU|BPF_MUL|BPF_K:
581 A *= pc->k;
582 continue;
583
584 case BPF_ALU|BPF_DIV|BPF_K:
585 A /= pc->k;
586 continue;
587
588 case BPF_ALU|BPF_AND|BPF_K:
589 A &= pc->k;
590 continue;
591
592 case BPF_ALU|BPF_OR|BPF_K:
593 A |= pc->k;
594 continue;
595
596 case BPF_ALU|BPF_LSH|BPF_K:
597 A <<= pc->k;
598 continue;
599
600 case BPF_ALU|BPF_RSH|BPF_K:
601 A >>= pc->k;
602 continue;
603
604 case BPF_ALU|BPF_NEG:
605 (int32)A = -((int32)A);
606 continue;
607 /* ARITHMETIC INSTRUCTIONS */
608
609 /* MISC INSTRUCTIONS */
610 case BPF_MISC|BPF_TAX:
611 X = A;
612 continue;
613
614 case BPF_MISC|BPF_TXA:
615 A = X;
616 continue;
617 /* END MISC INSTRUCTIONS */
618
619 /* TME INSTRUCTIONS */
620 case BPF_MISC|BPF_TME|BPF_LOOKUP:
621 j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
622 if (j==TME_ERROR)
623 return 0;
624 pc += (j == TME_TRUE) ? pc->jt : pc->jf;
625 continue;
626
627 case BPF_MISC|BPF_TME|BPF_EXECUTE:
628 if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
629 return 0;
630 continue;
631
632 case BPF_MISC|BPF_TME|BPF_INIT:
633 if (init_tme_block(tme,pc->k)==TME_ERROR)
634 return 0;
635 continue;
636
637 case BPF_MISC|BPF_TME|BPF_VALIDATE:
638 if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
639 return 0;
640 continue;
641
642 case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
643 if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
644 return 0;
645 continue;
646
647 case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
648 if (set_active_tme_block(tme,pc->k)==TME_ERROR)
649 return 0;
650 continue;
651
652 case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
653 if (set_active_tme_block(tme,pc->k)==TME_ERROR)
654 return 0;
655 continue;
656 case BPF_MISC|BPF_TME|BPF_SET_WORKING:
657 if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
658 return 0;
659 tme->working=pc->k;
660 continue;
661
662
663
664 case BPF_MISC|BPF_TME|BPF_RESET:
665 if (reset_tme(tme)==TME_ERROR)
666 return 0;
667 continue;
668
669 case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
670 if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
671 return 0;
672 A=j;
673 continue;
674
675 case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
676 if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
677 return 0;
678 continue;
679
680 case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
681 set_autodeletion(&tme->block_data[tme->working],pc->k);
682 continue;
683
684 /* END TME INSTRUCTIONS */
685
686 }
687 }
688 }
689