1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 // Accept the full packet 20 #define BPF_ACCEPT BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFFF) 21 22 // Reject the packet 23 #define BPF_REJECT BPF_STMT(BPF_RET | BPF_K, 0) 24 25 // Note arguments to BPF_JUMP(opcode, operand, true_offset, false_offset) 26 27 // If not equal, jump over count instructions 28 #define BPF_JUMP_IF_NOT_EQUAL(v, count) \ 29 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 0, (count)) 30 31 // *TWO* instructions: compare and if not equal jump over the accept statement 32 #define BPF2_ACCEPT_IF_EQUAL(v) \ 33 BPF_JUMP_IF_NOT_EQUAL((v), 1), \ 34 BPF_ACCEPT 35 36 // *TWO* instructions: compare and if equal jump over the reject statement 37 #define BPF2_REJECT_IF_NOT_EQUAL(v) \ 38 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, (v), 1, 0), \ 39 BPF_REJECT 40 41 // *TWO* instructions: compare and if greater or equal jump over the reject statement 42 #define BPF2_REJECT_IF_LESS_THAN(v) \ 43 BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, (v), 1, 0), \ 44 BPF_REJECT 45 46 // *TWO* instructions: compare and if *NOT* greater jump over the reject statement 47 #define BPF2_REJECT_IF_GREATER_THAN(v) \ 48 BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, (v), 0, 1), \ 49 BPF_REJECT 50 51 // *THREE* instructions: compare and if *NOT* in range [lo, hi], jump over the reject statement 52 #define BPF3_REJECT_IF_NOT_IN_RANGE(lo, hi) \ 53 BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, (lo), 0, 1), \ 54 BPF_JUMP(BPF_JMP | BPF_JGT | BPF_K, (hi), 0, 1), \ 55 BPF_REJECT 56 57 // *TWO* instructions: compare and if none of the bits are set jump over the reject statement 58 #define BPF2_REJECT_IF_ANY_MASKED_BITS_SET(v) \ 59 BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, (v), 0, 1), \ 60 BPF_REJECT 61 62 // loads skb->protocol 63 #define BPF_LOAD_SKB_PROTOCOL \ 64 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, (__u32)SKF_AD_OFF + SKF_AD_PROTOCOL) 65 66 // 8-bit load relative to start of link layer (mac/ethernet) header. 67 #define BPF_LOAD_MAC_RELATIVE_U8(ofs) \ 68 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, (__u32)SKF_LL_OFF + (ofs)) 69 70 // Big/Network Endian 16-bit load relative to start of link layer (mac/ethernet) header. 71 #define BPF_LOAD_MAC_RELATIVE_BE16(ofs) \ 72 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, (__u32)SKF_LL_OFF + (ofs)) 73 74 // Big/Network Endian 32-bit load relative to start of link layer (mac/ethernet) header. 75 #define BPF_LOAD_MAC_RELATIVE_BE32(ofs) \ 76 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (__u32)SKF_LL_OFF + (ofs)) 77 78 // 8-bit load relative to start of network (IPv4/IPv6) header. 79 #define BPF_LOAD_NET_RELATIVE_U8(ofs) \ 80 BPF_STMT(BPF_LD | BPF_B | BPF_ABS, (__u32)SKF_NET_OFF + (ofs)) 81 82 // Big/Network Endian 16-bit load relative to start of network (IPv4/IPv6) header. 83 #define BPF_LOAD_NET_RELATIVE_BE16(ofs) \ 84 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, (__u32)SKF_NET_OFF + (ofs)) 85 86 // Big/Network Endian 32-bit load relative to start of network (IPv4/IPv6) header. 87 #define BPF_LOAD_NET_RELATIVE_BE32(ofs) \ 88 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (__u32)SKF_NET_OFF + (ofs)) 89 90 #define field_sizeof(struct_type,field) sizeof(((struct_type *)0)->field) 91 92 // 8-bit load from IPv4 header field. 93 #define BPF_LOAD_IPV4_U8(field) \ 94 BPF_LOAD_NET_RELATIVE_U8(({ \ 95 _Static_assert(field_sizeof(struct iphdr, field) == 1, "field of wrong size"); \ 96 offsetof(iphdr, field); \ 97 })) 98 99 // Big/Network Endian 16-bit load from IPv4 header field. 100 #define BPF_LOAD_IPV4_BE16(field) \ 101 BPF_LOAD_NET_RELATIVE_BE16(({ \ 102 _Static_assert(field_sizeof(struct iphdr, field) == 2, "field of wrong size"); \ 103 offsetof(iphdr, field); \ 104 })) 105 106 // Big/Network Endian 32-bit load from IPv4 header field. 107 #define BPF_LOAD_IPV4_BE32(field) \ 108 BPF_LOAD_NET_RELATIVE_BE32(({ \ 109 _Static_assert(field_sizeof(struct iphdr, field) == 4, "field of wrong size"); \ 110 offsetof(iphdr, field); \ 111 })) 112 113 // 8-bit load from IPv6 header field. 114 #define BPF_LOAD_IPV6_U8(field) \ 115 BPF_LOAD_NET_RELATIVE_U8(({ \ 116 _Static_assert(field_sizeof(struct ipv6hdr, field) == 1, "field of wrong size"); \ 117 offsetof(ipv6hdr, field); \ 118 })) 119 120 // Big/Network Endian 16-bit load from IPv6 header field. 121 #define BPF_LOAD_IPV6_BE16(field) \ 122 BPF_LOAD_NET_RELATIVE_BE16(({ \ 123 _Static_assert(field_sizeof(struct ipv6hdr, field) == 2, "field of wrong size"); \ 124 offsetof(ipv6hdr, field); \ 125 })) 126 127 // Big/Network Endian 32-bit load from IPv6 header field. 128 #define BPF_LOAD_IPV6_BE32(field) \ 129 BPF_LOAD_NET_RELATIVE_BE32(({ \ 130 _Static_assert(field_sizeof(struct ipv6hdr, field) == 4, "field of wrong size"); \ 131 offsetof(ipv6hdr, field); \ 132 })) 133 134 // Load the length of the IPv4 header into X index register. 135 // ie. X := 4 * IPv4.IHL, where IPv4.IHL is the bottom nibble 136 // of the first byte of the IPv4 (aka network layer) header. 137 #define BPF_LOADX_NET_RELATIVE_IPV4_HLEN \ 138 BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, (__u32)SKF_NET_OFF) 139 140 // Blindly assumes no IPv6 extension headers, just does X := 40 141 // You may later adjust this as you parse through IPv6 ext hdrs. 142 #define BPF_LOADX_CONSTANT_IPV6_HLEN \ 143 BPF_STMT(BPF_LDX | BPF_W | BPF_IMM, sizeof(struct ipv6hdr)) 144 145 // NOTE: all the following require X to be setup correctly (v4: 20+, v6: 40+) 146 147 // 8-bit load from L4 (TCP/UDP/...) header 148 #define BPF_LOAD_NETX_RELATIVE_L4_U8(ofs) \ 149 BPF_STMT(BPF_LD | BPF_B | BPF_IND, (__u32)SKF_NET_OFF + (ofs)) 150 151 // Big/Network Endian 16-bit load from L4 (TCP/UDP/...) header 152 #define BPF_LOAD_NETX_RELATIVE_L4_BE16(ofs) \ 153 BPF_STMT(BPF_LD | BPF_H | BPF_IND, (__u32)SKF_NET_OFF + (ofs)) 154 155 // Big/Network Endian 32-bit load from L4 (TCP/UDP/...) header 156 #define BPF_LOAD_NETX_RELATIVE_L4_BE32(ofs) \ 157 BPF_STMT(BPF_LD | BPF_W | BPF_IND, (__u32)SKF_NET_OFF + (ofs)) 158 159 // Both ICMPv4 and ICMPv6 start with u8 type, u8 code 160 #define BPF_LOAD_NETX_RELATIVE_ICMP_TYPE BPF_LOAD_NETX_RELATIVE_L4_U8(0) 161 #define BPF_LOAD_NETX_RELATIVE_ICMP_CODE BPF_LOAD_NETX_RELATIVE_L4_U8(1) 162 163 // IPv6 extension headers (HOPOPTS, DSTOPS, FRAG) begin with a u8 nexthdr 164 #define BPF_LOAD_NETX_RELATIVE_V6EXTHDR_NEXTHDR BPF_LOAD_NETX_RELATIVE_L4_U8(0) 165 166 // IPv6 fragment header is always exactly 8 bytes long 167 #define BPF_LOAD_CONSTANT_V6FRAGHDR_LEN \ 168 BPF_STMT(BPF_LD | BPF_IMM, 8) 169 170 // HOPOPTS/DSTOPS follow up with 'u8 len', counting 8 byte units, (0->8, 1->16) 171 // *THREE* instructions 172 #define BPF3_LOAD_NETX_RELATIVE_V6EXTHDR_LEN \ 173 BPF_LOAD_NETX_RELATIVE_L4_U8(1), \ 174 BPF_STMT(BPF_ALU | BPF_ADD | BPF_K, 1), \ 175 BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 3) 176 177 // *TWO* instructions: A += X; X := A 178 #define BPF2_ADD_A_TO_X \ 179 BPF_STMT(BPF_ALU | BPF_ADD | BPF_X, 0), \ 180 BPF_STMT(BPF_MISC | BPF_TAX, 0) 181 182 // UDP/UDPLITE/TCP/SCTP/DCCP all start with be16 srcport, dstport 183 #define BPF_LOAD_NETX_RELATIVE_SRC_PORT BPF_LOAD_NETX_RELATIVE_L4_BE16(0) 184 #define BPF_LOAD_NETX_RELATIVE_DST_PORT BPF_LOAD_NETX_RELATIVE_L4_BE16(2) 185