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
155namespace mitigator {
156extern "C" {
157#endif
158
160typedef void* Context;
161
167enum Result {
183
189typedef uint64_t Bool;
190
196typedef uint32_t Time;
197
206const void* parameters_get(Context ctx);
207
209struct EtherAddr {
210 uint8_t u8[6];
211};
212
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
233 uint16_t control; /* Tag Control Information (big-endian) */
234 uint16_t type; /* Next protocol ID (big-endian) */
235};
236
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
249typedef uint32_t IpAddr;
250
269struct 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
289struct Ip6Addr {
290 uint8_t u8[16];
291};
292
312struct 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
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
354struct 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
381struct 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
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
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
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
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
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
498union NetAddr {
499 struct {
500 uint8_t padding[12]; /* Reserved, zero-filled by API */
501 IpAddr addr; /* IPv4 address */
502 } v4;
503 struct Ip6Addr v6; /* IPv6 address */
504};
505
517struct 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
531void packet_flow(Context ctx, struct Flow* info);
532
546
558
576
586
604
617void* packet_transport_payload(Context ctx, uint16_t* length);
618
625void set_packet_length(Context ctx, uint16_t length);
626
636void set_packet_offset(Context ctx, uint16_t offset);
637
649
665
672void set_src_blacklisted(Context ctx, Time duration);
673
680void set_src_whitelisted(Context ctx, Time duration);
681
690typedef uint64_t TableKey;
691
697typedef uint64_t TableValue;
698
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
722Bool table_find(Context ctx, TableKey key, struct TableRecord* record);
723
731Bool table_get(Context ctx, TableKey key, struct TableRecord* record);
732
742
744uint64_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
783struct TableExResult
784table_ex_find(Context ctx, const void* key, const void* key_end,
785 void* value, void* value_end);
786
795struct TableExResult
796table_ex_get(Context ctx, const void* key, const void* key_end,
797 void* value, void* value_end);
798
809Bool table_ex_put(Context ctx, const void* key, const void* key_end,
810 const void* value, const void* value_end);
811
813uint64_t table_ex_size(Context ctx);
814
816typedef uint32_t Cookie;
817
842Cookie cookie_make(Context ctx, const struct Flow* id);
843
865Bool cookie_check(Context ctx, const struct Flow* id, Cookie cookie);
866
876
891Bool syncookie_check(Context ctx, uint32_t seqnum_offset, uint32_t acknum_offset);
892
902
908Bool isn_syncookie_check(Context ctx, uint32_t seqnum_offset,
909 uint32_t acknum_offset);
910
918
924Bool bloom_check(Context ctx, uint64_t hash);
925
929void bloom_add(Context ctx, uint64_t hash);
930
935
950uint32_t hash_crc32_u32(uint32_t value, uint32_t init);
951
957uint32_t hash_crc32_u64(uint64_t value, uint32_t init);
958
989uint32_t hash_crc32_data(const void* data, const void* end, uint32_t init);
990
992uint64_t rand64(void);
993
996
998LOCAL uint16_t
999bswap16(uint16_t value) {
1000 return __builtin_bswap16(value);
1001}
1002
1004LOCAL uint32_t
1005bswap32(uint32_t value) {
1006 return __builtin_bswap32(value);
1007}
1008
1010LOCAL uint64_t
1011bswap64(uint64_t value) {
1012 return __builtin_bswap64(value);
1013}
1014
1015#define VLAN_ID_MASK 0x0fff
1016
1018LOCAL uint16_t
1019vlan_get_id(const struct VlanHeader* vlan) {
1020 return bswap16(vlan->control) & VLAN_ID_MASK;
1021}
1022
1031LOCAL void
1032vlan_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
1037STATIC_ASSERT(sizeof(struct EtherHeader) == 14);
1038STATIC_ASSERT(sizeof(struct VlanHeader) == 4);
1039STATIC_ASSERT(sizeof(struct IpHeader) == 20);
1040STATIC_ASSERT(sizeof(struct Ip6Addr) == 16);
1041STATIC_ASSERT(sizeof(struct Ip6Header) == 40);
1042STATIC_ASSERT(sizeof(struct TcpHeader) == 20);
1043STATIC_ASSERT(sizeof(struct UdpHeader) == 8);
1044STATIC_ASSERT(sizeof(struct IcmpHeader) == 4);
1045STATIC_ASSERT(sizeof(struct TableExResult) == 8);
1046STATIC_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.
void * packet_ether_header(Context ctx)
Get packet Ethernet header.
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
void * packet_transport_payload(Context ctx, uint16_t *length)
Get packet transport payload for TCP, UDP, or ICMP.
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
void * packet_network_header(Context ctx)
Get packet network header, e.g. IPv4 header.
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_header(Context ctx)
Get packet transport header, e.g. TCP header.
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.
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.
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 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