|
56 | 56 | #include "sunatmpos.h"
|
57 | 57 | #include "pflog.h"
|
58 | 58 | #include "ppp.h"
|
| 59 | +#include "batadv_packet.h" |
| 60 | +#include "batadv_legacy_packet.h" |
59 | 61 | #include "pcap/sll.h"
|
60 | 62 | #include "pcap/ipnet.h"
|
61 | 63 | #include "arcnet.h"
|
@@ -9731,6 +9733,168 @@ gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
|
9731 | 9733 | return b1;
|
9732 | 9734 | }
|
9733 | 9735 |
|
| 9736 | +static struct block * |
| 9737 | +gen_batadv_check_version(compiler_state_t *cstate, struct block *b0, bpf_u_int32 version) |
| 9738 | +{ |
| 9739 | + struct block *b1; |
| 9740 | + |
| 9741 | + if (version > UINT8_MAX) |
| 9742 | + bpf_error(cstate, |
| 9743 | + "batman-adv compatibility version number %u unsupported", |
| 9744 | + version); |
| 9745 | + |
| 9746 | + b1 = gen_cmp(cstate, OR_LINKPL, 1, BPF_B, version); |
| 9747 | + gen_and(b0, b1); |
| 9748 | + |
| 9749 | + return b1; |
| 9750 | +} |
| 9751 | + |
| 9752 | +static struct block * |
| 9753 | +gen_batadv_check_type(compiler_state_t *cstate, struct block *b0, |
| 9754 | + bpf_u_int32 version, bpf_u_int32 type) |
| 9755 | +{ |
| 9756 | + struct block *b1; |
| 9757 | + |
| 9758 | + switch (version) { |
| 9759 | + case 14: |
| 9760 | + case 15: |
| 9761 | + if (type > UINT8_MAX) |
| 9762 | + bpf_error(cstate, |
| 9763 | + "batman-adv packet type %u unsupported for compatibility version %u", |
| 9764 | + type, version); |
| 9765 | + |
| 9766 | + b1 = gen_cmp(cstate, OR_LINKPL, 0, BPF_B, type); |
| 9767 | + gen_and(b0, b1); |
| 9768 | + b0 = b1; |
| 9769 | + |
| 9770 | + break; |
| 9771 | + default: |
| 9772 | + bpf_error(cstate, |
| 9773 | + "batman-adv compatibility version number %u unsupported", |
| 9774 | + version); |
| 9775 | + } |
| 9776 | + |
| 9777 | + return b0; |
| 9778 | +} |
| 9779 | + |
| 9780 | + |
| 9781 | +static void gen_batadv_push_offset(compiler_state_t *cstate, u_int offset) |
| 9782 | +{ |
| 9783 | + PUSH_LINKHDR(cstate, DLT_EN10MB, cstate->off_linkpl.is_variable, |
| 9784 | + cstate->off_linkpl.constant_part + cstate->off_nl + offset, |
| 9785 | + cstate->off_linkpl.reg); |
| 9786 | + |
| 9787 | + cstate->off_linktype.constant_part += cstate->off_linkhdr.constant_part; |
| 9788 | + cstate->off_linkpl.constant_part += cstate->off_linkhdr.constant_part; |
| 9789 | + |
| 9790 | + cstate->off_nl = 0; |
| 9791 | + cstate->off_nl_nosnap = 0; /* no 802.2 LLC */ |
| 9792 | +} |
| 9793 | + |
| 9794 | +static void |
| 9795 | +gen_batadv_offsets_v14(compiler_state_t *cstate, bpf_u_int32 type) |
| 9796 | +{ |
| 9797 | + size_t offset; |
| 9798 | + |
| 9799 | + switch (type) { |
| 9800 | + case BATADV_LEGACY_UNICAST: /* 0x03 */ |
| 9801 | + offset = sizeof(struct batadv_legacy_unicast_packet); |
| 9802 | + break; |
| 9803 | + case BATADV_LEGACY_BCAST: /* 0x04 */ |
| 9804 | + offset = sizeof(struct batadv_legacy_bcast_packet); |
| 9805 | + break; |
| 9806 | + case BATADV_LEGACY_UNICAST_FRAG: /* 0x06 */ |
| 9807 | + offset = sizeof(struct batadv_legacy_unicast_frag_packet); |
| 9808 | + break; |
| 9809 | + case BATADV_LEGACY_UNICAST_4ADDR: /* 0x09 */ |
| 9810 | + offset = sizeof(struct batadv_legacy_unicast_4addr_packet); |
| 9811 | + break; |
| 9812 | + case BATADV_LEGACY_CODED: /* 0x0a */ |
| 9813 | + offset = sizeof(struct batadv_legacy_coded_packet); |
| 9814 | + break; |
| 9815 | + default: |
| 9816 | + offset = 0; |
| 9817 | + } |
| 9818 | + |
| 9819 | + if (offset) |
| 9820 | + gen_batadv_push_offset(cstate, (u_int)offset); |
| 9821 | +} |
| 9822 | + |
| 9823 | +static void |
| 9824 | +gen_batadv_offsets_v15(compiler_state_t *cstate, bpf_u_int32 type) |
| 9825 | +{ |
| 9826 | + size_t offset; |
| 9827 | + |
| 9828 | + switch (type) { |
| 9829 | + case BATADV_BCAST: /* 0x01 */ |
| 9830 | + offset = sizeof(struct batadv_bcast_packet); |
| 9831 | + break; |
| 9832 | + case BATADV_CODED: /* 0x02 */ |
| 9833 | + offset = sizeof(struct batadv_coded_packet); |
| 9834 | + break; |
| 9835 | + case BATADV_UNICAST: /* 0x40 */ |
| 9836 | + offset = sizeof(struct batadv_unicast_packet); |
| 9837 | + break; |
| 9838 | + case BATADV_UNICAST_FRAG: /* 0x41 */ |
| 9839 | + offset = sizeof(struct batadv_frag_packet); |
| 9840 | + break; |
| 9841 | + case BATADV_UNICAST_4ADDR: /* 0x42 */ |
| 9842 | + offset = sizeof(struct batadv_unicast_4addr_packet); |
| 9843 | + break; |
| 9844 | + case BATADV_UNICAST_TVLV: |
| 9845 | + /* unsupported for now, needs variable offset to |
| 9846 | + * take tvlv_len into account |
| 9847 | + */ |
| 9848 | + /* fall through */ |
| 9849 | + default: |
| 9850 | + offset = 0; |
| 9851 | + } |
| 9852 | + |
| 9853 | + if (offset) |
| 9854 | + gen_batadv_push_offset(cstate, (u_int)offset); |
| 9855 | +} |
| 9856 | + |
| 9857 | +static void |
| 9858 | +gen_batadv_offsets(compiler_state_t *cstate, bpf_u_int32 version, bpf_u_int32 type) |
| 9859 | +{ |
| 9860 | + switch (version) { |
| 9861 | + case 14: |
| 9862 | + gen_batadv_offsets_v14(cstate, type); |
| 9863 | + break; |
| 9864 | + case 15: |
| 9865 | + gen_batadv_offsets_v15(cstate, type); |
| 9866 | + break; |
| 9867 | + default: |
| 9868 | + break; |
| 9869 | + } |
| 9870 | +} |
| 9871 | + |
| 9872 | +struct block * |
| 9873 | +gen_batadv(compiler_state_t *cstate, bpf_u_int32 version, int has_version, |
| 9874 | + bpf_u_int32 type, int has_type) |
| 9875 | +{ |
| 9876 | + struct block *b0; |
| 9877 | + |
| 9878 | + /* |
| 9879 | + * Catch errors reported by us and routines below us, and return NULL |
| 9880 | + * on an error. |
| 9881 | + */ |
| 9882 | + if (setjmp(cstate->top_ctx)) |
| 9883 | + return (NULL); |
| 9884 | + |
| 9885 | + b0 = gen_linktype(cstate, ETHERTYPE_BATMAN); |
| 9886 | + |
| 9887 | + if (has_version) |
| 9888 | + b0 = gen_batadv_check_version(cstate, b0, version); |
| 9889 | + |
| 9890 | + if (has_type) { |
| 9891 | + b0 = gen_batadv_check_type(cstate, b0, version, type); |
| 9892 | + gen_batadv_offsets(cstate, version, type); |
| 9893 | + } |
| 9894 | + |
| 9895 | + return b0; |
| 9896 | +} |
| 9897 | + |
9734 | 9898 | /* Check that the encapsulated frame has a link layer header
|
9735 | 9899 | * for Ethernet filters. */
|
9736 | 9900 | static struct block *
|
|
0 commit comments