Cover empty NODEINFO outputs and malformed BGP preservation

This commit is contained in:
evgeny committed 2026-10-24 13:03:42 +02:00
1 parent 790978458c
commit acd9dcd1a8
3 files changed
+40

No files matched your search

+8
View File
@@ -6,6 +6,14 @@
заменяются вместе. Timestamp входит в подпись. Групповые пути и подсети
остаются в `TOPO_GROUP_NODE` и не являются частью общей записи узла.
В NODEINFO секции подсетей присутствуют только при `TOPO_FLAG_SEND_SUBNETS`.
Без флага оба счётчика подсетей равны нулю; противоречащий этому заголовок отклоняется.
Parser проверяет точную длину пакета и проходит все присутствующие секции независимо
от запрошенных `out_*`: например, `out_subnets=NULL` отключает создание объектов подсетей,
но сохраняет проверку префиксов и правильное положение следующего hop-list.
Выходы выдаются только после полного успеха; при ошибке они обнулены, частичные объекты
освобождены. Подпись и допустимость пути проверяются после структурного разбора.
Получатель проверяет подпись до изменения реестра или маршрутов. Более свежая
запись заменяет старую целиком, включая пустые списки адресов. Старые записи
игнорируются; разные подписанные записи с одинаковым timestamp — конфликт.
+5
View File
@@ -159,6 +159,11 @@ static void test_bgp(struct UTUN_INSTANCE* signer) {
assert(topo_group_process_nodeinfo(&group, &from, packet, (size_t)len + sizeof(struct TOPOMSG_HEADER)) == 0);
assert(queue_entry_count(peer->paths) == 1);
struct TOPOMSG_NODEINFO_PKT* wire = (struct TOPOMSG_NODEINFO_PKT*)packet;
wire->node.local_v4_subnets = 1; /* malformed CHAT не меняет уже принятую запись и маршрут */
assert(topo_group_process_nodeinfo(&group, &from, packet, (size_t)len + sizeof(struct TOPOMSG_HEADER)) < 0);
assert(topo_node_find_by_id(&group, ni->node_id) == peer && queue_entry_count(peer->paths) == 1);
assert(peer->last_timestamp == ni->timestamp && topo_node_registry_find(signer->topo_groups, ni->node_id)->timestamp == ni->timestamp);
wire->node.local_v4_subnets = 0;
wire->node.timestamp++; /* подделка не удаляет узел и ранее принятый маршрут */
assert(topo_group_process_nodeinfo(&group, &from, packet, (size_t)len + sizeof(struct TOPOMSG_HEADER)) < 0);
assert(topo_node_find_by_id(&group, ni->node_id) == peer && queue_entry_count(peer->paths) == 1);
+27
View File
@@ -216,6 +216,32 @@ static void test_encoder(struct wire_fixture *f) {
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] NODEINFO encoder emits only selected sections and checks exact buffer capacity");
}
static void test_empty_and_arguments(struct wire_fixture *f) {
memset(f->wire, 0, sizeof(f->wire));
struct TOPOMSG_NODE *h = (struct TOPOMSG_NODE *)f->wire;
for (unsigned with_flag = 0; with_flag < 2; with_flag++) {
h->flags = with_flag ? TOPO_FLAG_SEND_SUBNETS : 0;
struct TOPO_NODE *node = NULL; struct TOPO_NODESUBNETS *subnets = (void *)(uintptr_t)1;
uint64_t *hops = (void *)(uintptr_t)1; uint8_t count = 99; uint16_t rtt = 99;
assert(!topo_node_deserialize(&f->group, f->wire, TOPOMSG_NODE_HDR_SIZE, &node, &subnets, &hops, &count, &rtt));
assert(node && !node->node_name && !node->v4_addrs && !node->v6_addrs && !subnets && !hops && !count && !rtt);
result_free(f, node, subnets, hops);
}
struct TOPO_NODE *node = (void *)(uintptr_t)1;
assert(topo_node_deserialize(NULL, f->wire, TOPOMSG_NODE_HDR_SIZE, &node, NULL, NULL, NULL, NULL) < 0 && !node);
assert(topo_node_deserialize(&f->group, NULL, TOPOMSG_NODE_HDR_SIZE, &node, NULL, NULL, NULL, NULL) < 0 && !node);
assert(topo_node_deserialize(&f->group, f->wire, TOPOMSG_NODE_HDR_SIZE, NULL, NULL, NULL, NULL, NULL) < 0);
assert(topo_node_dyn_size(NULL) < 0);
fixture_packet(f, TOPO_FLAG_SEND_SUBNETS, 0);
struct TOPOMSG_SUBNET4 *v4 = (struct TOPOMSG_SUBNET4 *)(f->wire + f->subnet4_offset);
struct TOPOMSG_SUBNET6 *v6 = (struct TOPOMSG_SUBNET6 *)(f->wire + f->subnet6_offset);
v4[0].prefix_length = 0; v4[1].prefix_length = 32;
v6[0].prefix_length = 0; v6[1].prefix_length = 128;
assert(!topo_node_deserialize(&f->group, f->wire, f->length, &node, NULL, NULL, NULL, NULL));
topo_node_destroy(&f->groups, node);
DEBUG_INFO(DEBUG_CATEGORY_BGP, "[PASS] NODEINFO empty sections, missing arguments and prefix boundaries");
}
#ifdef __linux__
static void test_allocation_failures(struct wire_fixture *f) {
fixture_packet(f, TOPO_FLAG_SEND_SUBNETS, 2);
@@ -246,6 +272,7 @@ int main(void) {
test_invalid_packets(&fixture);
test_optional_outputs(&fixture);
test_encoder(&fixture);
test_empty_and_arguments(&fixture);
#ifdef __linux__
test_allocation_failures(&fixture);
#endif