bpf.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // bpf.c: bpf packet filter for linux/freebsd
  2. #include "config.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include "dat.h"
  8. #include "fns.h"
  9. struct bpf_insn {
  10. ushort code;
  11. uchar jt;
  12. uchar jf;
  13. u_int32_t k;
  14. };
  15. struct bpf_program {
  16. uint bf_len;
  17. struct bpf_insn *bf_insns;
  18. };
  19. /* instruction classes */
  20. #define BPF_CLASS(code) ((code) & 0x07)
  21. #define BPF_LD 0x00
  22. #define BPF_LDX 0x01
  23. #define BPF_ST 0x02
  24. #define BPF_STX 0x03
  25. #define BPF_ALU 0x04
  26. #define BPF_JMP 0x05
  27. #define BPF_RET 0x06
  28. #define BPF_MISC 0x07
  29. /* ld/ldx fields */
  30. #define BPF_SIZE(code) ((code) & 0x18)
  31. #define BPF_W 0x00
  32. #define BPF_H 0x08
  33. #define BPF_B 0x10
  34. #define BPF_MODE(code) ((code) & 0xe0)
  35. #define BPF_IMM 0x00
  36. #define BPF_ABS 0x20
  37. #define BPF_IND 0x40
  38. #define BPF_MEM 0x60
  39. #define BPF_LEN 0x80
  40. #define BPF_MSH 0xa0
  41. /* alu/jmp fields */
  42. #define BPF_OP(code) ((code) & 0xf0)
  43. #define BPF_ADD 0x00
  44. #define BPF_SUB 0x10
  45. #define BPF_MUL 0x20
  46. #define BPF_DIV 0x30
  47. #define BPF_OR 0x40
  48. #define BPF_AND 0x50
  49. #define BPF_LSH 0x60
  50. #define BPF_RSH 0x70
  51. #define BPF_NEG 0x80
  52. #define BPF_JA 0x00
  53. #define BPF_JEQ 0x10
  54. #define BPF_JGT 0x20
  55. #define BPF_JGE 0x30
  56. #define BPF_JSET 0x40
  57. #define BPF_SRC(code) ((code) & 0x08)
  58. #define BPF_K 0x00
  59. #define BPF_X 0x08
  60. /* ret - BPF_K and BPF_X also apply */
  61. #define BPF_RVAL(code) ((code) & 0x18)
  62. #define BPF_A 0x10
  63. /* misc */
  64. #define BPF_MISCOP(code) ((code) & 0xf8)
  65. #define BPF_TAX 0x00
  66. #define BPF_TXA 0x80
  67. /* macros for insn array initializers */
  68. #define BPF_STMT(code, k) { (ushort)(code), 0, 0, k }
  69. #define BPF_JUMP(code, k, jt, jf) { (ushort)(code), jt, jf, k }
  70. void *
  71. create_bpf_program(int shelf, int slot)
  72. {
  73. struct bpf_program *bpf_program;
  74. struct bpf_insn insns[] = {
  75. /* Load the type into register */
  76. BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
  77. /* Does it match AoE Type (0x88a2)? No, goto INVALID */
  78. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0x88a2, 0, 12),
  79. /* Load the flags into register */
  80. BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 14),
  81. /* Check to see if the Resp flag is set */
  82. BPF_STMT(BPF_ALU+BPF_AND+BPF_K, Resp),
  83. /* Yes, goto INVALID */
  84. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 9),
  85. /* Load the shelf number into register */
  86. BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
  87. /* Does it match shelf number? No, goto CHECKBROADCAST */
  88. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, shelf, 0, 2),
  89. /* Load the slot number into register */
  90. BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
  91. /* Does it match shelf number? Yes, goto VALID */
  92. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, slot, 4, 0),
  93. /* CHECKBROADCAST: is (shelf, slot) == (0xffff, 0xff)? */
  94. /* Load the shelf number into register */
  95. BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 16),
  96. /* Is it 0xffff? No, goto INVALID */
  97. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xffff, 0, 3),
  98. /* Load the slot number into register */
  99. BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 18),
  100. /* Is it 0xff? No, goto INVALID */
  101. BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xff, 0, 1),
  102. /* VALID: return -1 (allow the packet to be read) */
  103. BPF_STMT(BPF_RET+BPF_K, -1),
  104. /* INVALID: return 0 (ignore the packet) */
  105. BPF_STMT(BPF_RET+BPF_K, 0),
  106. };
  107. if ((bpf_program = malloc(sizeof(struct bpf_program))) == NULL
  108. || (bpf_program->bf_insns = malloc(sizeof(insns))) == NULL) {
  109. perror("malloc");
  110. exit(1);
  111. }
  112. bpf_program->bf_len = sizeof(insns)/sizeof(struct bpf_insn);
  113. memcpy(bpf_program->bf_insns, insns, sizeof(insns));
  114. return (void *)bpf_program;
  115. }
  116. void
  117. free_bpf_program(void *bpf_program)
  118. {
  119. free(((struct bpf_program *) bpf_program)->bf_insns);
  120. free(bpf_program);
  121. }