Mitigator BPF API
Functions and types programs can use to filter packets.
mitigator_bpf.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2022 BIFIT Mitigator Team <info@mitigator.ru>
3  */
4 #pragma once
5 
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #define ENTRYPOINT_SECTION "filter_v2"
11 
12 #define SECTION(name) __attribute__((section(name), used))
13 
14 #ifdef __cplusplus
15 #define STATIC_ASSERT(x) static_assert(x, "")
16 #else
17 #define STATIC_ASSERT(x) _Static_assert(x, "")
18 #endif
19 
43 #define PROGRAM_DISPLAY_ID(id) \
44  SECTION("meta.display_id") \
45  static const char _mitigator_meta_program_id[] = id;
46 
64 #define ENTRYPOINT SECTION(ENTRYPOINT_SECTION)
65 
82 #define LOCAL static inline __attribute__((always_inline))
83 
98 #define PACKED __attribute__((packed))
99 
125 #if defined(__clang__)
126 #define UNROLL _Pragma("unroll")
127 #else
128 #define UNROLL
129 #endif
130 
141 #define MAX_PAYLOAD_LENGTH 1536
142 
152 #define MAX_PARAMETERS_LENGTH 1024
153 
154 #ifdef __cplusplus
155 namespace mitigator {
156 extern "C" {
157 #endif
158 
160 typedef void* Context;
161 
167 enum Result {
182 };
183 
189 typedef uint64_t Bool;
190 
196 typedef uint32_t Time;
197 
206 const void* parameters_get(Context ctx);
207 
209 struct EtherAddr {
210  uint8_t u8[6];
211 };
212 
218 struct EtherHeader {
219  struct EtherAddr ether_dhost; /* Destination host MAC address */
220  struct EtherAddr ether_shost; /* Source host MAC address */
221  uint16_t ether_type; /* Next protocol ID (big-endian) */
222 };
223 
232 struct VlanHeader {
233  uint16_t control; /* Tag Control Information (big-endian) */
234  uint16_t type; /* Next protocol ID (big-endian) */
235 };
236 
241 enum EtherType {
242  ETHER_TYPE_IP = 0x0800, /* Internet Protocol version 4 */
243  ETHER_TYPE_ARP = 0x0806, /* Address Resolution Protocol */
244  ETHER_TYPE_8021Q = 0x8100, /* IEEE 802.1q (VLAN) */
245  ETHER_TYPE_IP6 = 0x86DD /* Internet Protocol version 6 */
246 };
247 
249 typedef uint32_t IpAddr;
250 
269 struct IpHeader {
270  uint32_t ip_hl : 4; /* 0 header length */
271  uint32_t ip_v : 4; /* version == 4 */
272  uint8_t ip_tos; /* 1 type of service */
273  uint16_t ip_len; /* 2-3 total length */
274  uint16_t ip_id; /* 4-5 packet ID */
275  uint16_t ip_off; /* 6-7 fragmentation offset */
276  uint8_t ip_ttl; /* 8 time to live */
277  uint8_t ip_p; /* 9 protocol ID */
278  uint16_t ip_sum; /* 10-11 header checksum */
279  uint32_t ip_src; /* 12-15 source address */
280  uint32_t ip_dst; /* 16-19 destination address */
281 };
282 
289 struct Ip6Addr {
290  uint8_t u8[16];
291 };
292 
312 struct Ip6Header {
313  uint32_t ip6_vfc; /* Version, traffic class, flow label */
314  uint16_t ip6_plen; /* Payload length */
315  uint8_t ip6_next; /* Next header */
316  uint8_t ip6_hoplim; /* Hop limit */
317  struct Ip6Addr ip6_src; /* Source address */
318  struct Ip6Addr ip6_dst; /* Destination address */
319 };
320 
326 enum IpProto {
327  IP_PROTO_ICMP = 1,
328  IP_PROTO_TCP = 6,
329  IP_PROTO_UDP = 17,
330  IP_PROTO_IPV6 = 41,
331  IP_PROTO_ICMPV6 = 58,
332 };
333 
354 struct UdpHeader {
355  uint16_t uh_sport; /* 0-1 source port */
356  uint16_t uh_dport; /* 2-3 destination port */
357  uint16_t uh_ulen; /* 4-5 UDP length */
358  uint16_t uh_sum; /* 6-7 checksum */
359 };
360 
381 struct TcpHeader {
382  uint16_t th_sport; /* 0-1 source port */
383  uint16_t th_dport; /* 2-3 destination port */
384  uint32_t th_seq; /* 4-7 sequence number */
385  uint32_t th_ack; /* 8-11 acknowledgement number */
386  uint32_t th_flags2 : 4; /* 12 more flags */
387  uint32_t th_off : 4; /* data offset in words */
388  uint8_t th_flags; /* 13 flags */
389  uint16_t th_win; /* 14-15 window */
390  uint16_t th_sum; /* 16-17 checksum */
391  uint16_t th_urp; /* 18-19 urgent pointer */
392 };
393 
422 enum TcpFlags {
423  TCP_FLAG_FIN = 0x01,
424  TCP_FLAG_SYN = 0x02,
425  TCP_FLAG_RST = 0x04,
426  TCP_FLAG_PUSH = 0x08,
427  TCP_FLAG_ACK = 0x10,
428  TCP_FLAG_URG = 0x20,
429  TCP_FLAG_ECE = 0x40,
430  TCP_FLAG_CWR = 0x80
431 };
432 
441 enum TcpOption {
442  TCP_OPT_EOL = 0, /* End of Option List */
443  TCP_OPT_NOP = 1, /* No option (used for padding) */
444  TCP_OPT_MAXSEG = 2, /* Maximum segment size (MSS) */
445  TCP_OPT_WSCALE = 3, /* Window scaling factor */
446  TCP_OPT_SACK_PERM = 4, /* Selective acknowledgement permitted */
447  TCP_OPT_SACK = 5, /* Selective acknowledgement */
448  TCP_OPT_TIMESTAMPS = 8 /* Timestamps */
449 };
450 
462 struct IcmpHeader {
463  uint8_t icmp_type; /* 0 ICMP type */
464  uint8_t icmp_code; /* 1 ICMP code */
465  uint16_t icmp_cksum; /* 2-3 checksum */
466 };
467 
469 enum IcmpType {
470  ICMP_ECHO_REPLY = 0, /* Echo Reply Message */
471  ICMP_DEST_UNREACHABLE = 3, /* Destination Unreachable */
472  ICMP_SOURCE_QUENCH = 4, /* Source Quench */
473  ICMP_REDIRECT = 5, /* Redirect */
474  ICMP_ECHO = 8, /* Echo Message */
475  ICMP_TIME_EXCEEDED = 11, /* Time Exceeded */
476  ICMP_PARAM_PROBLEM = 12, /* Parameter Problem */
477  ICMP_TIMESTAMP_REQUEST = 13, /* Timestamp Request */
478  ICMP_TIMESTAMP_REPLY = 14, /* Timestamp Reply */
479  ICMP_INFO_REQUEST = 15, /* Information Request */
480  ICMP_INFO_REPLY = 16, /* Information Reply */
481 };
482 
484 enum Icmp6Type {
485  ICMP6_DEST_UNREACHABLE = 1, /* Destination Unreachable */
486  ICMP6_PKT_TOO_BIG = 2, /* Packet Too Big */
487  ICMP6_TIME_EXCEEDED = 3, /* Time Exceeded */
488  ICMP6_PARAM_PROBLEM = 4, /* Parameter Problem */
489  ICMP6_ECHO_REQUEST = 128, /* Echo Request */
490  ICMP6_ECHO_REPLY = 129, /* Echo Reply */
491  ICMP6_ROUTER_SOL = 133, /* Router Advertisement */
492  ICMP6_ROUTER_ADV = 134, /* Router Solicitation */
493  ICMP6_NEIGHBOR_SOL = 135, /* Neighbor Solicitation */
494  ICMP6_NEIGHBOR_ADV = 136, /* Neighbor Advertisement */
495 };
496 
498 union NetAddr {
499  struct {
500  uint8_t padding[12]; /* Reserved, zero-filled by API */
501  IpAddr v4; /* IPv4 address */
502  };
503  struct Ip6Addr v6; /* IPv6 address */
504 };
505 
517 struct Flow {
518  union NetAddr src_ip; /* Source address */
519  union NetAddr dst_ip; /* Destination address */
520  uint16_t src_port; /* Source port */
521  uint16_t dst_port; /* Destination port */
522  uint32_t padding; /* Not used and zero-filled by API */
523 };
524 
531 void packet_flow(Context ctx, struct Flow* info);
532 
546 
558 
576 
586 
604 
617 void* packet_transport_payload(Context ctx, uint16_t* length);
618 
625 void set_packet_length(Context ctx, uint16_t length);
626 
636 void set_packet_offset(Context ctx, uint16_t offset);
637 
649 
665 
672 void set_src_blacklisted(Context ctx, Time duration);
673 
680 void set_src_whitelisted(Context ctx, Time duration);
681 
690 typedef uint64_t TableKey;
691 
697 typedef uint64_t TableValue;
698 
711 struct TableRecord {
712  TableValue value; /* User data */
713  Time update_time; /* Update time maintained by the system */
714  uint32_t padding; /* Reserved, not used by API */
715 };
716 
722 Bool table_find(Context ctx, TableKey key, struct TableRecord* record);
723 
731 Bool table_get(Context ctx, TableKey key, struct TableRecord* record);
732 
742 
744 uint64_t table_size(Context ctx);
745 
764  bool found; /* Indicates if the record has been found */
765  uint8_t reserved[3]; /* Reserved, do not use */
766  Time update_time; /* Record update time maintained by the system */
767 };
768 
770 #define TABLE_EX_KEY_SIZE 16
771 
773 #define TABLE_EX_VALUE_SIZE 8
774 
783 struct TableExResult
784 table_ex_find(Context ctx, const void* key, const void* key_end,
785  void* value, void* value_end);
786 
795 struct TableExResult
796 table_ex_get(Context ctx, const void* key, const void* key_end,
797  void* value, void* value_end);
798 
809 Bool table_ex_put(Context ctx, const void* key, const void* key_end,
810  const void* value, const void* value_end);
811 
813 uint64_t table_ex_size(Context ctx);
814 
816 typedef uint32_t Cookie;
817 
842 Cookie cookie_make(Context ctx, const struct Flow* id);
843 
865 Bool cookie_check(Context ctx, const struct Flow* id, Cookie cookie);
866 
876 
891 Bool syncookie_check(Context ctx, uint32_t seqnum_offset, uint32_t acknum_offset);
892 
902 
908 Bool isn_syncookie_check(Context ctx, uint32_t seqnum_offset,
909  uint32_t acknum_offset);
910 
918 
924 Bool bloom_check(Context ctx, uint64_t hash);
925 
929 void bloom_add(Context ctx, uint64_t hash);
930 
935 
950 uint32_t hash_crc32_u32(uint32_t value, uint32_t init);
951 
957 uint32_t hash_crc32_u64(uint64_t value, uint32_t init);
958 
989 uint32_t hash_crc32_data(const void* data, const void* end, uint32_t init);
990 
992 uint64_t rand64(void);
993 
996 
998 LOCAL uint16_t
999 bswap16(uint16_t value) {
1000  return __builtin_bswap16(value);
1001 }
1002 
1004 LOCAL uint32_t
1005 bswap32(uint32_t value) {
1006  return __builtin_bswap32(value);
1007 }
1008 
1010 LOCAL uint64_t
1011 bswap64(uint64_t value) {
1012  return __builtin_bswap64(value);
1013 }
1014 
1015 #define VLAN_ID_MASK 0x0fff
1016 
1018 LOCAL uint16_t
1019 vlan_get_id(const struct VlanHeader* vlan) {
1020  return bswap16(vlan->control) & VLAN_ID_MASK;
1021 }
1022 
1031 LOCAL void
1032 vlan_set_id(struct VlanHeader* vlan, uint16_t id) {
1033  uint16_t bits = vlan->control & ~bswap16(VLAN_ID_MASK);
1034  vlan->control = bswap16(bswap16(bits) | id);
1035 }
1036 
1037 STATIC_ASSERT(sizeof(struct EtherHeader) == 14);
1038 STATIC_ASSERT(sizeof(struct VlanHeader) == 4);
1039 STATIC_ASSERT(sizeof(struct IpHeader) == 20);
1040 STATIC_ASSERT(sizeof(struct Ip6Addr) == 16);
1041 STATIC_ASSERT(sizeof(struct Ip6Header) == 40);
1042 STATIC_ASSERT(sizeof(struct TcpHeader) == 20);
1043 STATIC_ASSERT(sizeof(struct UdpHeader) == 8);
1044 STATIC_ASSERT(sizeof(struct IcmpHeader) == 4);
1045 STATIC_ASSERT(sizeof(struct TableExResult) == 8);
1046 STATIC_ASSERT(sizeof(union NetAddr) == sizeof(struct Ip6Addr));
1047 
1048 #ifdef __cplusplus
1049 } // extern "C"
1050 } // namespace mitigator
1051 #endif
LOCAL void vlan_set_id(struct VlanHeader *vlan, uint16_t id)
Set VLAN ID in 802.1q header.
Definition: mitigator_bpf.h:1032
EtherType
Ethernet frame type codes.
Definition: mitigator_bpf.h:241
uint8_t packet_transport_proto(Context ctx)
Get packet transport protocol code, e.g. TCP, UDP, or ICMP.
struct TableExResult table_ex_get(Context ctx, const void *key, const void *key_end, void *value, void *value_end)
Lookup value in the extended table by key and modify record update time.
uint64_t TableValue
Definition: mitigator_bpf.h:697
void * Context
Opaque filter context.
Definition: mitigator_bpf.h:160
LOCAL uint16_t bswap16(uint16_t value)
Change byte order of a 16-bit value.
Definition: mitigator_bpf.h:999
uint64_t table_ex_size(Context ctx)
Get number of records in the extended table.
IcmpType
ICMPv4 types.
Definition: mitigator_bpf.h:469
void bloom_reset(Context ctx)
Reset bloom filter to the initial state.
uint32_t hash_crc32_data(const void *data, const void *end, uint32_t init)
Compute CRC32 (Castagnoli) over [data; end).
uint32_t Time
Definition: mitigator_bpf.h:196
void set_packet_offset(Context ctx, uint16_t offset)
Set number of bytes to strip from the beginning of transport payload.
uint16_t packet_network_proto(Context ctx)
Get packet network protocol code, e.g. IPv4.
Result
Filter verdict.
Definition: mitigator_bpf.h:167
@ RESULT_LIMIT
Definition: mitigator_bpf.h:175
@ RESULT_DROP
Definition: mitigator_bpf.h:171
@ RESULT_SORB
Definition: mitigator_bpf.h:181
@ RESULT_PASS
Definition: mitigator_bpf.h:169
@ RESULT_BACK
Definition: mitigator_bpf.h:173
LOCAL uint16_t vlan_get_id(const struct VlanHeader *vlan)
Get VLAN ID from 802.1q header.
Definition: mitigator_bpf.h:1019
#define LOCAL
Force the compiler to inline a local function.
Definition: mitigator_bpf.h:82
Bool table_get(Context ctx, TableKey key, struct TableRecord *record)
Lookup value in the basic table by key and modify record update time.
uint32_t hash_crc32_u64(uint64_t value, uint32_t init)
Compute CRC32 (Castagnoli) of a 64-bit value.
TcpOption
TCP option codes.
Definition: mitigator_bpf.h:441
IpProto
IPv4 and IPv6 transport protocol codes.
Definition: mitigator_bpf.h:326
Cookie cookie_make(Context ctx, const struct Flow *id)
Make a generic cookie value based on random seed, current time, and flow fields that identify the cli...
TcpFlags
TCP flags.
Definition: mitigator_bpf.h:422
Cookie syncookie_make(Context ctx)
Make a cookie value for use as a sequence number in a SYN+ACK packet.
LOCAL uint64_t bswap64(uint64_t value)
Change byte order of a 64-bit value.
Definition: mitigator_bpf.h:1011
void set_packet_length(Context ctx, uint16_t length)
Set new packet transport payload length (max 1400).
uint64_t table_size(Context ctx)
Get number of records in the table.
uint32_t IpAddr
IPv4 address.
Definition: mitigator_bpf.h:249
Bool table_ex_put(Context ctx, const void *key, const void *key_end, const void *value, const void *value_end)
Update value in the extended table, creating a new record if needed.
void * packet_transport_payload(Context ctx, uint16_t *length)
Get packet transport payload for TCP or UDP.
Bool isn_syncookie_check(Context ctx, uint32_t seqnum_offset, uint32_t acknum_offset)
Check if packet is a TCP ACK carrying an ISN SYN cookie.
struct TableExResult table_ex_find(Context ctx, const void *key, const void *key_end, void *value, void *value_end)
Lookup value in the extended table by key.
LOCAL uint32_t bswap32(uint32_t value)
Change byte order of a 32-bit value.
Definition: mitigator_bpf.h:1005
uint64_t rand64(void)
Generate a pseudo-random, non cryptographically-secure value.
void * packet_ether_header(Context ctx)
Get packet Ethernet header.
uint32_t hash_crc32_u32(uint32_t value, uint32_t init)
Compute CRC32 (Castagnoli) of a 32-bit value.
Icmp6Type
ICMPv6 types.
Definition: mitigator_bpf.h:484
Bool syncookie_check(Context ctx, uint32_t seqnum_offset, uint32_t acknum_offset)
Check if packet is a TCP ACK carrying a SYN cookie.
void * packet_transport_header(Context ctx)
Get packet transport header, e.g. TCP header.
Bool cookie_check(Context ctx, const struct Flow *id, Cookie cookie)
Check if a generic cookie matches the flow and has not expired.
void set_packet_isn_syncookie(Context ctx)
Convert response packet to an empty TCP SYN+ACK with ISN syncookie.
void set_src_blacklisted(Context ctx, Time duration)
Add packet source address to temporary blacklist.
Bool table_put(Context ctx, TableKey key, TableValue value)
Update value in the basic table, creating a new record if needed.
const void * parameters_get(Context ctx)
Get a pointer to read-only program parameters.
Bool bloom_check(Context ctx, uint64_t hash)
Check if hash value is stored in the bloom filter.
void * packet_network_header(Context ctx)
Get packet network header, e.g. IPv4 header.
void bloom_add(Context ctx, uint64_t hash)
Add hash value to the bloom filter.
Time time_sec(Context ctx)
Get system time in seconds.
uint64_t Bool
ABI-safe, EBPF-friendly boolean type.
Definition: mitigator_bpf.h:189
void isn_send_ack_packet(Context ctx)
Send ACK packet with ISN syncookie.
Bool table_find(Context ctx, TableKey key, struct TableRecord *record)
Lookup value in the basic table by key.
void set_src_whitelisted(Context ctx, Time duration)
Add packet source address to temporary whitelist.
uint64_t TableKey
Definition: mitigator_bpf.h:690
void set_packet_mangled(Context ctx)
Mark the packet as mangled by the program.
void set_packet_syncookie(Context ctx)
Convert response packet to an empty TCP SYN+ACK with syncookie.
void packet_flow(Context ctx, struct Flow *info)
Get packet flow information, including source and destination.
uint32_t Cookie
Definition: mitigator_bpf.h:816
Ethernet address (MAC address).
Definition: mitigator_bpf.h:209
Ethernet header (802.1).
Definition: mitigator_bpf.h:218
Packet flow information.
Definition: mitigator_bpf.h:517
ICMP and ICMPv6 header.
Definition: mitigator_bpf.h:462
IPv6 address representation.
Definition: mitigator_bpf.h:289
IPv6 header.
Definition: mitigator_bpf.h:312
IPv4 header.
Definition: mitigator_bpf.h:269
Result of a lookup in the extended table.
Definition: mitigator_bpf.h:763
Record in the program-wide table.
Definition: mitigator_bpf.h:711
TCP header.
Definition: mitigator_bpf.h:381
UDP header.
Definition: mitigator_bpf.h:354
VLAN header (802.1q).
Definition: mitigator_bpf.h:232
Network address, either IPv4 or IPv6.
Definition: mitigator_bpf.h:498