10#include <bpf/libbpf.h>
29 if (lvl == LIBBPF_WARN)
30 std::cerr <<
"libbpf: " << msg;
39 : obj_(nullptr), whitelist_map_(nullptr), blacklist_map_(nullptr),
40 drop_counter_map_(nullptr) {
61 bpf_object__close(
obj_);
77 throw std::runtime_error(
"BPF object is empty");
79 struct bpf_object_open_opts opts = {};
80 opts.sz =
sizeof(opts);
83 throw std::runtime_error(
"failed to open BPF object from memory");
85 if (bpf_object__load(
obj_))
86 throw std::runtime_error(
"failed to load BPF object into kernel");
90 throw std::runtime_error(
"whitelist_map not found in BPF object");
94 throw std::runtime_error(
"blacklist_map not found in BPF object");
98 throw std::runtime_error(
"drop_counter not found in BPF object");
107 bpf_program *prog = bpf_object__next_program(
obj_,
nullptr);
109 throw std::runtime_error(
"no BPF program found in object");
111 bpf_program__set_type(prog, BPF_PROG_TYPE_XDP);
113 int ifindex = if_nametoindex(
iface_.c_str());
115 throw std::runtime_error(
"interface not found: " +
iface_);
117 int fd = bpf_program__fd(prog);
119 throw std::runtime_error(
"invalid program fd");
121 struct bpf_xdp_attach_opts attach_opts = {};
122 attach_opts.sz =
sizeof(attach_opts);
124 if (bpf_xdp_attach(ifindex, fd, 0, &attach_opts))
125 throw std::runtime_error(
"failed to attach XDP program to " +
iface_);
130 int ifindex = if_nametoindex(
iface_.c_str());
134 struct bpf_xdp_attach_opts detach_opts = {};
135 detach_opts.sz =
sizeof(detach_opts);
137 bpf_xdp_detach(ifindex, 0, &detach_opts);
146 int fd = bpf_map__fd(map);
154 struct lpm_key *cur_key =
nullptr;
156 while (bpf_map_get_next_key(fd, cur_key, &next_key) == 0) {
157 bpf_map_delete_elem(fd, &next_key);
166 const std::vector<BlockEntry> &entries) {
167 bpf_map *map =
nullptr;
168 if (map_name ==
"whitelist_map")
170 else if (map_name ==
"blacklist_map")
173 throw std::invalid_argument(
"unknown map: " + map_name);
177 int fd = bpf_map__fd(map);
179 throw std::runtime_error(
"invalid fd for " + map_name);
181 __u32 value = (map_name ==
"whitelist_map") ? 0 : 1;
183 for (
const auto &entry : entries) {
191 if (bpf_map_update_elem(fd, &key, &value, BPF_ANY))
192 std::cerr <<
"warning: failed to add " << entry.ip <<
" to " << map_name
194 }
catch (
const std::exception &e) {
195 std::cerr <<
"warning: skipping invalid entry '" << entry.ip
196 <<
"': " << e.what() << std::endl;
214std::vector<std::pair<uint32_t, uint64_t>>
216 std::vector<std::pair<uint32_t, uint64_t>> result;
222 __u32 *cur_key =
nullptr;
226 while (bpf_map_get_next_key(fd, cur_key, &next_key) == 0) {
227 if (bpf_map_lookup_elem(fd, &next_key, &value) == 0 && value > 0)
228 result.emplace_back(next_key, value);
229 bpf_map_delete_elem(fd, &next_key);
void DetachFromInterface()
Открепляет XDP-программу от iface_.
void AttachToInterface()
Прикрепляет загруженную XDP-программу к iface_.
std::vector< std::pair< uint32_t, uint64_t > > ReadAndClearDropCounters()
Читает все записи из карты drop_counter и атомарно очищает их.
void Unload()
Открепляет XDP и закрывает BPF-объект. Безопасен для многократного вызова.
void LoadBPFProgram()
Открывает и загружает BPF-объект из встроенного массива байткода.
bpf_object * obj_
Дескриптор BPF-объекта libbpf.
std::string iface_
Имя текущего прикреплённого интерфейса.
bpf_map * whitelist_map_
LPM trie для записей белого списка.
void UpdateWhitelist(const std::vector< BlockEntry > &entries)
void UpdateBlacklist(const std::vector< BlockEntry > &entries)
void ClearMap(bpf_map *map)
Перебирает и удаляет все ключи из BPF-карты (итерация LPM trie).
bpf_map * drop_counter_map_
Хэш-карта для счётчиков дропов по IP.
bpf_map * blacklist_map_
LPM trie для записей чёрного списка.
void UpdateMap(const std::string &map_name, const std::vector< BlockEntry > &entries)
Заменяет все записи в указанной BPF-карте.
void Load(const std::string &iface)
CIDR ParseCIDR(const std::string &str)
Распарсенное представление CIDR-подсети.
uint32_t prefixlen
Длина префикса (0-32). 32 означает одиночный хост.
uint32_t ip
IP-адрес в network byte order с применённой маской.
Ключ для LPM trie-карт: длина префикса + IP в network byte order.
static int PrintLibbpfLog(enum libbpf_print_level lvl, const char *msg, va_list)
unsigned int blocker_bpf_len
unsigned char blocker_bpf[]
Встроенный BPF-байткод, сгенерированный xxd во время сборки.
Загрузчик BPF-объекта и менеджер XDP-программы.