diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 00000000..ab5d02d1 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,2436 @@ +[ + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-ll_queue.o", + "ll_queue.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/ll_queue.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-ll_queue.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-debug_config.o", + "debug_config.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/debug_config.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-debug_config.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-u_async.o", + "u_async.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/u_async.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-u_async.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-timeout_heap.o", + "timeout_heap.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/timeout_heap.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-timeout_heap.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-memory_pool.o", + "memory_pool.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/memory_pool.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-memory_pool.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-sha256.o", + "sha256.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/sha256.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-sha256.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-socket_compat.o", + "socket_compat.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/socket_compat.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-socket_compat.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-platform_compat.o", + "platform_compat.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/platform_compat.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-platform_compat.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-getmyip.o", + "getmyip.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/getmyip.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-getmyip.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-swm_min.o", + "swm_min.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/swm_min.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-swm_min.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-mem.o", + "mem.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/mem.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-mem.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-radix.o", + "radix.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/radix.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-radix.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-serialize.o", + "serialize.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/serialize.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-serialize.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "libuasync_a-tcp_io.o", + "tcp_io.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/tcp_io.c", + "output": "/home/vnc1/proj/utun3/lib/libuasync_a-tcp_io.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "liblmdb/libuasync_a-mdb.o", + "liblmdb/mdb.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/liblmdb/mdb.c", + "output": "/home/vnc1/proj/utun3/lib/liblmdb/libuasync_a-mdb.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-D_ISOC99_SOURCE", + "-DDEBUG_OUTPUT_STDERR", + "-g", + "-I../src", + "-I../lib", + "-I./liblmdb", + "-g", + "-O2", + "-c", + "-o", + "liblmdb/libuasync_a-midl.o", + "liblmdb/midl.c" + ], + "directory": "/home/vnc1/proj/utun3/lib", + "file": "/home/vnc1/proj/utun3/lib/liblmdb/midl.c", + "output": "/home/vnc1/proj/utun3/lib/liblmdb/libuasync_a-midl.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-config_parser.o", + "config_parser.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/config_parser.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-config_parser.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "utun-utun.o", + "utun.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/utun.c", + "output": "/home/vnc1/proj/utun3/src/utun-utun.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-utun_instance.o", + "utun_instance.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/utun_instance.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-utun_instance.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-config_updater.o", + "config_updater.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/config_updater.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-config_updater.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_lib.o", + "route_lib.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_lib.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_lib.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route6_lib.o", + "route6_lib.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route6_lib.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route6_lib.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_bgp.o", + "route_bgp.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_bgp.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_bgp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_ping.o", + "route_ping.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_ping.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_ping.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_node.o", + "route_node.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_node.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_node.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_node_lmdb.o", + "route_node_lmdb.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_node_lmdb.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_node_lmdb.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-route_connectivity.o", + "route_connectivity.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/route_connectivity.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-route_connectivity.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-conn_mgr.o", + "conn_mgr.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/conn_mgr.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-conn_mgr.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-db_sync.o", + "db_sync.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/db_sync.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-db_sync.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-routing.o", + "routing.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/routing.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-routing.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-tun_if.o", + "tun_if.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/tun_if.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-tun_if.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-tun_route.o", + "tun_route.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/tun_route.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-tun_route.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-tun_linux.o", + "tun_linux.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/tun_linux.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-tun_linux.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-tun_freebsd.o", + "tun_freebsd.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/tun_freebsd.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-tun_freebsd.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-tun_windows.o", + "tun_windows.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/tun_windows.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-tun_windows.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp.o", + "etcp.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_connections.o", + "etcp_connections.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_connections.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_connections.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_bbr.o", + "etcp_bbr.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_bbr.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_bbr.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_loadbalancer.o", + "etcp_loadbalancer.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_loadbalancer.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_loadbalancer.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_debug.o", + "etcp_debug.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_debug.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_debug.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_dump.o", + "etcp_dump.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_dump.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_dump.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-secure_channel.o", + "secure_channel.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/secure_channel.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-secure_channel.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-crc32.o", + "crc32.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/crc32.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-crc32.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-stcp_link.o", + "stcp_link.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/stcp_link.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-stcp_link.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-stcp.o", + "stcp.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/stcp.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-stcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-stcp_server.o", + "stcp_server.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/stcp_server.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-stcp_server.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-stcp_client.o", + "stcp_client.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/stcp_client.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-stcp_client.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-pkt_normalizer.o", + "pkt_normalizer.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/pkt_normalizer.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-pkt_normalizer.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-packet_dump.o", + "packet_dump.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/packet_dump.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-packet_dump.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_api.o", + "etcp_api.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_api.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_api.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_connect.o", + "etcp_connect.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_connect.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_connect.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-control_server.o", + "control_server.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/control_server.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-control_server.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-msg_transport.o", + "msg_transport.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/msg_transport.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-msg_transport.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-firewall.o", + "firewall.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/firewall.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-firewall.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-eim_nat.o", + "eim_nat.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/eim_nat.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-eim_nat.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-dummynet.o", + "dummynet.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/dummynet.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-dummynet.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-nat_transport.o", + "nat_transport.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/nat_transport.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-nat_transport.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "proxy/libutun_a-tcp_proxy_client.o", + "proxy/tcp_proxy_client.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/proxy/tcp_proxy_client.c", + "output": "/home/vnc1/proj/utun3/src/proxy/libutun_a-tcp_proxy_client.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "libutun_a-etcp_router.o", + "etcp_router.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/etcp_router.c", + "output": "/home/vnc1/proj/utun3/src/libutun_a-etcp_router.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "proxy/libutun_a-tcp_proxy_server.o", + "proxy/tcp_proxy_server.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/proxy/tcp_proxy_server.c", + "output": "/home/vnc1/proj/utun3/src/proxy/libutun_a-tcp_proxy_server.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "proxy/libutun_a-udp_proxy.o", + "proxy/udp_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/proxy/udp_proxy.c", + "output": "/home/vnc1/proj/utun3/src/proxy/libutun_a-udp_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "proxy/libutun_a-socks_proxy.o", + "proxy/socks_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/proxy/socks_proxy.c", + "output": "/home/vnc1/proj/utun3/src/proxy/libutun_a-socks_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "proxy/libutun_a-icmp_proxy.o", + "proxy/icmp_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/proxy/icmp_proxy.c", + "output": "/home/vnc1/proj/utun3/src/proxy/libutun_a-icmp_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "lwip_tcp/libutun_a-lwip_pbuf.o", + "lwip_tcp/lwip_pbuf.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/lwip_tcp/lwip_pbuf.c", + "output": "/home/vnc1/proj/utun3/src/lwip_tcp/libutun_a-lwip_pbuf.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "lwip_tcp/libutun_a-lwip_tcp.o", + "lwip_tcp/lwip_tcp.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/lwip_tcp/lwip_tcp.c", + "output": "/home/vnc1/proj/utun3/src/lwip_tcp/libutun_a-lwip_tcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "lwip_tcp/libutun_a-lwip_tcp_in.o", + "lwip_tcp/lwip_tcp_in.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/lwip_tcp/lwip_tcp_in.c", + "output": "/home/vnc1/proj/utun3/src/lwip_tcp/libutun_a-lwip_tcp_in.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-I../src/uip", + "-g", + "-g", + "-O2", + "-c", + "-o", + "lwip_tcp/libutun_a-lwip_tcp_out.o", + "lwip_tcp/lwip_tcp_out.c" + ], + "directory": "/home/vnc1/proj/utun3/src", + "file": "/home/vnc1/proj/utun3/src/lwip_tcp/lwip_tcp_out.c", + "output": "/home/vnc1/proj/utun3/src/lwip_tcp/libutun_a-lwip_tcp_out.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_ll_queue-test_ll_queue.o", + "test_ll_queue.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_ll_queue.c", + "output": "/home/vnc1/proj/utun3/tests/test_ll_queue-test_ll_queue.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_serialize-test_serialize.o", + "test_serialize.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_serialize.c", + "output": "/home/vnc1/proj/utun3/tests/test_serialize-test_serialize.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_stream_sign-test_stream_sign.o", + "test_stream_sign.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_stream_sign.c", + "output": "/home/vnc1/proj/utun3/tests/test_stream_sign-test_stream_sign.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_stream_cipher-test_stream_cipher.o", + "test_stream_cipher.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_stream_cipher.c", + "output": "/home/vnc1/proj/utun3/tests/test_stream_cipher-test_stream_cipher.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_transport-test_etcp_stcp.o", + "test_etcp_stcp.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_stcp.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_transport-test_etcp_stcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_transport-test_stcp_link.o", + "test_stcp_link.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_stcp_link.c", + "output": "/home/vnc1/proj/utun3/tests/test_transport-test_stcp_link.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_stcp-test_stcp.o", + "test_stcp.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_stcp.c", + "output": "/home/vnc1/proj/utun3/tests/test_stcp-test_stcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_packet_dump-test_packet_dump.o", + "test_packet_dump.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_packet_dump.c", + "output": "/home/vnc1/proj/utun3/tests/test_packet_dump-test_packet_dump.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_debug_categories-test_debug_categories.o", + "test_debug_categories.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_debug_categories.c", + "output": "/home/vnc1/proj/utun3/tests/test_debug_categories-test_debug_categories.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_config_debug-test_config_debug.o", + "test_config_debug.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_config_debug.c", + "output": "/home/vnc1/proj/utun3/tests/test_config_debug-test_config_debug.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_memory_pool_and_config-test_memory_pool_and_config.o", + "test_memory_pool_and_config.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_memory_pool_and_config.c", + "output": "/home/vnc1/proj/utun3/tests/test_memory_pool_and_config-test_memory_pool_and_config.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_api-test_etcp_api.o", + "test_etcp_api.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_api.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_api-test_etcp_api.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_crypto-test_etcp_crypto.o", + "test_etcp_crypto.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_crypto.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_crypto-test_etcp_crypto.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_pkt_normalizer_standalone-test_pkt_normalizer_standalone.o", + "test_pkt_normalizer_standalone.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_pkt_normalizer_standalone.c", + "output": "/home/vnc1/proj/utun3/tests/test_pkt_normalizer_standalone-test_pkt_normalizer_standalone.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_route_lib-test_route_lib.o", + "test_route_lib.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_route_lib.c", + "output": "/home/vnc1/proj/utun3/tests/test_route_lib-test_route_lib.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_radix-test_radix.o", + "test_radix.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_radix.c", + "output": "/home/vnc1/proj/utun3/tests/test_radix-test_radix.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_route6_lib-test_route6_lib.o", + "test_route6_lib.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_route6_lib.c", + "output": "/home/vnc1/proj/utun3/tests/test_route6_lib-test_route6_lib.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_router_unit.o", + "test_etcp_router_unit.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_router_unit.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_router_unit.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_minimal.o", + "test_etcp_minimal.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_minimal.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_minimal.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_ipv6_sockets-test_ipv6_sockets.o", + "test_ipv6_sockets.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_ipv6_sockets.c", + "output": "/home/vnc1/proj/utun3/tests/test_ipv6_sockets-test_ipv6_sockets.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_u_async_timeouts-test_u_async_timeouts.o", + "test_u_async_timeouts.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_u_async_timeouts.c", + "output": "/home/vnc1/proj/utun3/tests/test_u_async_timeouts-test_u_async_timeouts.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_u_async_comprehensive-test_u_async_comprehensive.o", + "test_u_async_comprehensive.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_u_async_comprehensive.c", + "output": "/home/vnc1/proj/utun3/tests/test_u_async_comprehensive-test_u_async_comprehensive.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_two_instances-test_etcp_two_instances.o", + "test_etcp_two_instances.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_two_instances.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_two_instances-test_etcp_two_instances.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_simple_traffic-test_etcp_simple_traffic.o", + "test_etcp_simple_traffic.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_simple_traffic.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_simple_traffic-test_etcp_simple_traffic.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_100_packets-test_etcp_100_packets.o", + "test_etcp_100_packets.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_100_packets.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_100_packets-test_etcp_100_packets.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_reconnect-test_etcp_reconnect.o", + "test_etcp_reconnect.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_reconnect.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_reconnect-test_etcp_reconnect.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_pkt_normalizer_etcp-test_pkt_normalizer_etcp.o", + "test_pkt_normalizer_etcp.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_pkt_normalizer_etcp.c", + "output": "/home/vnc1/proj/utun3/tests/test_pkt_normalizer_etcp-test_pkt_normalizer_etcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_lwip_tcp-test_lwip_tcp.o", + "test_lwip_tcp.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_lwip_tcp.c", + "output": "/home/vnc1/proj/utun3/tests/test_lwip_tcp-test_lwip_tcp.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_u_async_performance-test_u_async_performance.o", + "test_u_async_performance.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_u_async_performance.c", + "output": "/home/vnc1/proj/utun3/tests/test_u_async_performance-test_u_async_performance.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_router.o", + "test_etcp_router.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_router.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_router.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_router_reconnect.o", + "test_etcp_router_reconnect.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_router_reconnect.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_router_reconnect.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_bbr-test_etcp_bbr.o", + "test_etcp_bbr.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_bbr.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_bbr-test_etcp_bbr.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_ping-test_etcp_ping.o", + "test_etcp_ping.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_ping.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_ping-test_etcp_ping.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_route_ping-test_route_ping.o", + "test_route_ping.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_route_ping.c", + "output": "/home/vnc1/proj/utun3/tests/test_route_ping-test_route_ping.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_nat_detection-test_nat_detection.o", + "test_nat_detection.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_nat_detection.c", + "output": "/home/vnc1/proj/utun3/tests/test_nat_detection-test_nat_detection.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_nat_engine-test_nat_engine.o", + "test_nat_engine.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_nat_engine.c", + "output": "/home/vnc1/proj/utun3/tests/test_nat_engine-test_nat_engine.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_nat_transport-test_nat_transport.o", + "test_nat_transport.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_nat_transport.c", + "output": "/home/vnc1/proj/utun3/tests/test_nat_transport-test_nat_transport.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_nat_stress-test_nat_stress.o", + "test_nat_stress.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_nat_stress.c", + "output": "/home/vnc1/proj/utun3/tests/test_nat_stress-test_nat_stress.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_tcp_proxy_server-test_tcp_proxy_server.o", + "test_tcp_proxy_server.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_tcp_proxy_server.c", + "output": "/home/vnc1/proj/utun3/tests/test_tcp_proxy_server-test_tcp_proxy_server.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_udp_proxy.o", + "test_udp_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_udp_proxy.c", + "output": "/home/vnc1/proj/utun3/tests/test_udp_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_icmp_proxy.o", + "test_icmp_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_icmp_proxy.c", + "output": "/home/vnc1/proj/utun3/tests/test_icmp_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_tcp_proxy_client.o", + "test_tcp_proxy_client.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_tcp_proxy_client.c", + "output": "/home/vnc1/proj/utun3/tests/test_tcp_proxy_client.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-g", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_socks_http_proxy.o", + "test_socks_http_proxy.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_socks_http_proxy.c", + "output": "/home/vnc1/proj/utun3/tests/test_socks_http_proxy.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_bgp_route_exchange-test_bgp_route_exchange.o", + "test_bgp_route_exchange.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_bgp_route_exchange.c", + "output": "/home/vnc1/proj/utun3/tests/test_bgp_route_exchange-test_bgp_route_exchange.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_bgp_triangle-test_bgp_triangle.o", + "test_bgp_triangle.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_bgp_triangle.c", + "output": "/home/vnc1/proj/utun3/tests/test_bgp_triangle-test_bgp_triangle.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_conn_mgr-test_conn_mgr.o", + "test_conn_mgr.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_conn_mgr.c", + "output": "/home/vnc1/proj/utun3/tests/test_conn_mgr-test_conn_mgr.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_etcp_connect-test_etcp_connect.o", + "test_etcp_connect.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_etcp_connect.c", + "output": "/home/vnc1/proj/utun3/tests/test_etcp_connect-test_etcp_connect.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_db_sync-test_db_sync.o", + "test_db_sync.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_db_sync.c", + "output": "/home/vnc1/proj/utun3/tests/test_db_sync-test_db_sync.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_stcp_traffic-test_stcp_traffic.o", + "test_stcp_traffic.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_stcp_traffic.c", + "output": "/home/vnc1/proj/utun3/tests/test_stcp_traffic-test_stcp_traffic.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "bbr_integration/test_bbr_integration-test_bbr_integration.o", + "bbr_integration/test_bbr_integration.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/bbr_integration/test_bbr_integration.c", + "output": "/home/vnc1/proj/utun3/tests/bbr_integration/test_bbr_integration-test_bbr_integration.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../src", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_intensive_memory_pool-test_intensive_memory_pool.o", + "test_intensive_memory_pool.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_intensive_memory_pool.c", + "output": "/home/vnc1/proj/utun3/tests/test_intensive_memory_pool-test_intensive_memory_pool.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_tcp_io-test_tcp_io.o", + "test_tcp_io.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_tcp_io.c", + "output": "/home/vnc1/proj/utun3/tests/test_tcp_io-test_tcp_io.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "test_uasync_socket_race-test_uasync_socket_race.o", + "test_uasync_socket_race.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/test_uasync_socket_race.c", + "output": "/home/vnc1/proj/utun3/tests/test_uasync_socket_race-test_uasync_socket_race.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "bench_timeout_heap-bench_timeout_heap.o", + "bench_timeout_heap.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/bench_timeout_heap.c", + "output": "/home/vnc1/proj/utun3/tests/bench_timeout_heap-bench_timeout_heap.o" + }, + { + "arguments": [ + "/usr/bin/gcc", + "-DHAVE_CONFIG_H", + "-I.", + "-I..", + "-I../lib", + "-g", + "-O2", + "-c", + "-o", + "bench_uasync_timeouts-bench_uasync_timeouts.o", + "bench_uasync_timeouts.c" + ], + "directory": "/home/vnc1/proj/utun3/tests", + "file": "/home/vnc1/proj/utun3/tests/bench_uasync_timeouts.c", + "output": "/home/vnc1/proj/utun3/tests/bench_uasync_timeouts-bench_uasync_timeouts.o" + } +] diff --git a/src/_route_tz.txt b/src/_route_tz.txt new file mode 100644 index 00000000..33a1b530 --- /dev/null +++ b/src/_route_tz.txt @@ -0,0 +1,9 @@ +Задача сделать механизм маршрутизации между узлами для групповых чатов. + +Узлы для всех чатов находятся в одной таблице - это nodeinfo (информация о подключении) +В другой таблице есть список узлов конкретного чата. + +надо сделать возможность хранить одновременно несколько групп узлов. в группу узлов добавить тип - utun или чатовая. +если utun - в группе используется роутинг (ipv4/ipv6). +если чатовая - то только связность между узлами. + diff --git a/src/conn_mgr.c b/src/conn_mgr.c index eec8d4a8..dd7e919a 100644 --- a/src/conn_mgr.c +++ b/src/conn_mgr.c @@ -273,18 +273,19 @@ int conn_mgr_add_alien_node(struct CONN_MGR* mgr, const uint8_t* nodeinfo_data, if (!mgr || !nodeinfo_data || len < sizeof(struct NODEINFO)) return CONN_MGR_ERR_INTERNAL; struct ROUTE_BGP* bgp = mgr->instance->bgp; if (!bgp) return CONN_MGR_ERR_INTERNAL; - const struct NODEINFO* ni = (const struct NODEINFO*)nodeinfo_data; - uint64_t node_id = ni->node_id; + const struct NODEINFO* src = (const struct NODEINFO*)nodeinfo_data; + uint64_t node_id = src->node_id; struct NODEINFO_Q* existing = nodeinfo_find_by_id(bgp, node_id); if (existing) { DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: alien node 0x%016llx already exists, ignoring", (unsigned long long)node_id); return CONN_MGR_OK; } - size_t dyn_sz = len - sizeof(struct NODEINFO); - size_t data_sz = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + dyn_sz + 8; - struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(data_sz); - if (!nq) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "conn_mgr: alien node alloc failed"); return CONN_MGR_ERR_INTERNAL; } - memcpy(&nq->node, nodeinfo_data, len); - nq->alien = 1; - nq->dirty = 0; - nq->last_ver = ni->ver; + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!ni) return CONN_MGR_ERR_INTERNAL; + memcpy(ni, nodeinfo_data, len < sizeof(*ni) ? len : sizeof(*ni)); + ni->ref_count = 1; + struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(sizeof(struct NODEINFO_Q)); + if (!nq) { u_free(ni); return CONN_MGR_ERR_INTERNAL; } + nq->node = ni; nodeinfo_ref(ni); + nq->hash_node_id = ni->node_id; + nq->alien = 1; nq->dirty = 0; nq->last_ver = ni->ver; nq->connectivity.ping_req_time = 0; if (bgp->nodes) queue_data_put_with_index(bgp->nodes, &nq->ll); DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: added alien node 0x%016llx", (unsigned long long)node_id); @@ -386,17 +387,12 @@ static int cm_is_rtt_fresh(struct NODEINFO_Q* nq, uint64_t now_tb) { } static int cm_has_direct_ip(struct NODEINFO_Q* nq) { - if (!nq) return 0; - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - const struct NODEINFO_IPV4_SOCKET_META* metas = NULL; - int addr_count = get_node_v4_addrs(nq, &addrs); - int meta_count = get_node_v4_sockets_meta(nq, &metas); - for (int i = 0; i < addr_count; i++) { - if (addrs[i].type == ADDR_TYPE_REAL || addrs[i].type == ADDR_TYPE_NAT) { - for (int j = 0; j < meta_count; j++) { - if (metas[j].id == addrs[i].socket_id && - (metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].config_type == CFG_SERVER_TYPE_UNKNOWN - || metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT)) + if (!nq || !nq->node) return 0; + for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) { + if (a->type == ADDR_TYPE_REAL || a->type == ADDR_TYPE_NAT) { + for (const struct NI_IPV4_SOCKET_META* m = nq->node->v4_sock_meta; m; m = m->next) { + if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN + || m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT)) return 1; } } @@ -405,16 +401,11 @@ static int cm_has_direct_ip(struct NODEINFO_Q* nq) { } static int cm_has_local_addr(struct NODEINFO_Q* nq) { - if (!nq) return 0; - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - const struct NODEINFO_IPV4_SOCKET_META* metas = NULL; - int addr_count = get_node_v4_addrs(nq, &addrs); - int meta_count = get_node_v4_sockets_meta(nq, &metas); - for (int i = 0; i < addr_count; i++) { - if (addrs[i].type == ADDR_TYPE_INTERFACE) { - for (int j = 0; j < meta_count; j++) { - if (metas[j].id == addrs[i].socket_id && - (metas[j].config_type == CFG_SERVER_TYPE_PRIVATE || metas[j].config_type == CFG_SERVER_TYPE_LOCAL)) + if (!nq || !nq->node) return 0; + for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) { + if (a->type == ADDR_TYPE_INTERFACE) { + for (const struct NI_IPV4_SOCKET_META* m = nq->node->v4_sock_meta; m; m = m->next) { + if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PRIVATE || m->config_type == CFG_SERVER_TYPE_LOCAL)) return 1; } } @@ -437,36 +428,20 @@ struct cm_ping_ctx { static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) { struct ROUTE_BGP* bgp = entry->mgr->instance->bgp; struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, entry->node_id); - if (!target) { entry->local_scan_state = CM_TRY_FAILED; return; } - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - const struct NODEINFO_IPV4_SOCKET_META* metas = NULL; - int addr_count = get_node_v4_addrs(target, &addrs); - int meta_count = get_node_v4_sockets_meta(target, &metas); - for (int i = 0; i < addr_count; i++) { - if (addrs[i].type != ADDR_TYPE_INTERFACE) continue; - for (int j = 0; j < meta_count; j++) { - if (metas[j].id != addrs[i].socket_id || - (metas[j].config_type != CFG_SERVER_TYPE_PRIVATE && metas[j].config_type != CFG_SERVER_TYPE_LOCAL)) continue; + if (!target || !target->node) { entry->local_scan_state = CM_TRY_FAILED; return; } + for (const struct NI_IPV4_ADDR* a = target->node->v4_addrs; a; a = a->next) { + if (a->type != ADDR_TYPE_INTERFACE) continue; + for (const struct NI_IPV4_SOCKET_META* m = target->node->v4_sock_meta; m; m = m->next) { + if (m->id != a->socket_id || (m->config_type != CFG_SERVER_TYPE_PRIVATE && m->config_type != CFG_SERVER_TYPE_LOCAL)) continue; struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets; while (s) { if ((s->type == CFG_SERVER_TYPE_PRIVATE || s->type == CFG_SERVER_TYPE_LOCAL) && s->local_addr.ss_family == AF_INET) { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - memcpy(&sin.sin_addr.s_addr, addrs[i].addr, 4); - sin.sin_port = htons(addrs[i].port); - struct sockaddr_storage sa; - memset(&sa, 0, sizeof(sa)); - memcpy(&sa, &sin, sizeof(sin)); - struct cm_ping_ctx* ctx = u_calloc(1, sizeof(struct cm_ping_ctx)); - if (!ctx) continue; - ctx->entry = entry; - ctx->addr = sa; - ctx->sock = s; - ctx->phase = 0; - ctx->attempt = 0; - etcp_send_ping_to_socket(entry->mgr->instance, s, target->node.public_key, &sa, - CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0); + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; + memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port); + struct sockaddr_storage sa; memset(&sa, 0, sizeof(sa)); memcpy(&sa, &sin, sizeof(sin)); + struct cm_ping_ctx* ctx = u_calloc(1, sizeof(struct cm_ping_ctx)); if (!ctx) continue; + ctx->entry = entry; ctx->addr = sa; ctx->sock = s; ctx->phase = 0; ctx->attempt = 0; + etcp_send_ping_to_socket(entry->mgr->instance, s, target->node->public_key, &sa, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0); return; } s = s->next; @@ -474,7 +449,6 @@ static void cm_start_local_scan(struct CONN_MGR_ENTRY* entry) { } } entry->local_scan_state = CM_TRY_FAILED; - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: local scan no candidates for 0x%016llx", (unsigned long long)entry->node_id); } static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) { @@ -482,39 +456,25 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) { if (entry->local_scan_state == CM_TRY_OK) return; struct ROUTE_BGP* bgp = entry->mgr->instance->bgp; struct NODEINFO_Q* target = nodeinfo_find_by_id(bgp, entry->node_id); - if (!target) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; } - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - const struct NODEINFO_IPV4_SOCKET_META* metas = NULL; - int addr_count = get_node_v4_addrs(target, &addrs); - int meta_count = get_node_v4_sockets_meta(target, &metas); + if (!target || !target->node) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; } uint8_t priority_order[] = { ADDR_TYPE_REAL, ADDR_TYPE_NAT, ADDR_TYPE_INTERFACE }; for (int pri = 0; pri < 3; pri++) { - for (int i = 0; i < addr_count; i++) { - if (addrs[i].type != priority_order[pri]) continue; - for (int j = 0; j < meta_count; j++) { - if (metas[j].id != addrs[i].socket_id) continue; + for (const struct NI_IPV4_ADDR* a = target->node->v4_addrs; a; a = a->next) { + if (a->type != priority_order[pri]) continue; + for (const struct NI_IPV4_SOCKET_META* m = target->node->v4_sock_meta; m; m = m->next) { + if (m->id != a->socket_id) continue; struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets; while (s) { - int compat = cm_nat_compatible(s, metas[j].config_type, metas[j].nat_type); - if (compat && s->local_addr.ss_family == AF_INET) { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - memcpy(&sin.sin_addr.s_addr, addrs[i].addr, 4); - sin.sin_port = htons(addrs[i].port); - struct sockaddr_storage sa; - memset(&sa, 0, sizeof(sa)); - memcpy(&sa, &sin, sizeof(sin)); + if (cm_nat_compatible(s, m->config_type, m->nat_type) && s->local_addr.ss_family == AF_INET) { + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; + memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port); + struct sockaddr_storage sa; memset(&sa, 0, sizeof(sa)); memcpy(&sa, &sin, sizeof(sin)); struct ETCP_CONN* conn = etcp_connection_create(entry->mgr->instance, NULL); if (conn) { etcp_conn_set_ready_cbk(conn, cm_direct_ready_cb, entry); - sc_set_peer_public_key(&conn->crypto_ctx, target->node.public_key, 0); - struct ETCP_LINK* link = etcp_link_new(conn, s, &sa, 0); - if (link) { - entry->main.timer = uasync_set_timeout(entry->mgr->instance->ua, - CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS * 10, entry, cm_direct_timeout_cb, "conn_mgr_direct"); - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: phase 1 (direct) started INIT to 0x%016llx", - (unsigned long long)entry->node_id); + sc_set_peer_public_key(&conn->crypto_ctx, target->node->public_key, 0); + if (etcp_link_new(conn, s, &sa, 0)) { + entry->main.timer = uasync_set_timeout(entry->mgr->instance->ua, CONN_MGR_CONNECT_DIRECT_TIMEOUT_MS * 10, entry, cm_direct_timeout_cb, "conn_mgr_direct"); return; } } @@ -524,8 +484,6 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) { } } } - DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "conn_mgr: phase 1 (direct) no compatible pairs for 0x%016llx", - (unsigned long long)entry->node_id); int has_our = cm_has_direct_ip(bgp->local_node); int has_target = cm_has_direct_ip(target); if (has_our && !has_target) { cm_start_phase_reverse(entry); return; } @@ -584,7 +542,7 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce, ctx->attempt++; if (ctx->attempt < CONN_MGR_LOCAL_SCAN_ATTEMPTS && ctx->phase == 0) { etcp_send_ping_to_socket(entry->mgr->instance, ctx->sock, - nodeinfo_find_by_id(entry->mgr->instance->bgp, entry->node_id)->node.public_key, + nodeinfo_find_by_id(entry->mgr->instance->bgp, entry->node_id)->node->public_key, &ctx->addr, CONN_MGR_LOCAL_SCAN_TIMEOUT_MS, cm_ping_cb, ctx, NULL, 0); return; } @@ -597,28 +555,19 @@ static void cm_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce, static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) { struct ROUTE_BGP* bgp = entry->mgr->instance->bgp; struct NODEINFO_Q* local = bgp->local_node; - if (!local) { cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; } + if (!local || !local->node) { cm_deliver_result(entry, CONN_MGR_ERR_INTERNAL); return; } uint32_t req_id = ++entry->mgr->next_request_id; - entry->main.request_id = req_id; - entry->main.phase = 2; - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - const struct NODEINFO_IPV4_SOCKET_META* metas = NULL; - int addr_count = get_node_v4_addrs(local, &addrs); - int meta_count = get_node_v4_sockets_meta(local, &metas); + entry->main.request_id = req_id; entry->main.phase = 2; uint8_t direct_count = 0; struct { uint8_t type; uint8_t ip[4]; uint16_t port; uint8_t socket_id; } out_addrs[8]; - for (int i = 0; i < addr_count && direct_count < 8; i++) { - if (addrs[i].type != ADDR_TYPE_REAL && addrs[i].type != ADDR_TYPE_NAT) continue; - for (int j = 0; j < meta_count; j++) { - if (metas[j].id == addrs[i].socket_id && - (metas[j].config_type == CFG_SERVER_TYPE_PUBLIC || metas[j].config_type == CFG_SERVER_TYPE_UNKNOWN - || metas[j].nat_type == NAT_VERIFIED_EIM || metas[j].nat_type == NAT_VERIFIED_DIRECT)) { - out_addrs[direct_count].type = addrs[i].type; - memcpy(out_addrs[direct_count].ip, addrs[i].addr, 4); - out_addrs[direct_count].port = htons(addrs[i].port); - out_addrs[direct_count].socket_id = addrs[i].socket_id; - direct_count++; - break; + for (const struct NI_IPV4_ADDR* a = local->node->v4_addrs; a && direct_count < 8; a = a->next) { + if (a->type != ADDR_TYPE_REAL && a->type != ADDR_TYPE_NAT) continue; + for (const struct NI_IPV4_SOCKET_META* m = local->node->v4_sock_meta; m; m = m->next) { + if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN + || m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT)) { + out_addrs[direct_count].type = a->type; memcpy(out_addrs[direct_count].ip, a->addr, 4); + out_addrs[direct_count].port = htons(a->port); out_addrs[direct_count].socket_id = a->socket_id; + direct_count++; break; } } } @@ -904,7 +853,7 @@ static void cm_handle_direct_req(struct ETCP_CONN* conn, const uint8_t* data, si struct ETCP_CONN* new_conn = etcp_connection_create(conn->instance, NULL); if (new_conn) { struct NODEINFO_Q* nq = nodeinfo_find_by_id(conn->instance->bgp, src_node_id); - if (nq) sc_set_peer_public_key(&new_conn->crypto_ctx, nq->node.public_key, 0); + if (nq) sc_set_peer_public_key(&new_conn->crypto_ctx, nq->node->public_key, 0); struct cm_reverse_pending* rp = u_calloc(1, sizeof(struct cm_reverse_pending)); if (rp) { rp->request_id = req->request_id; rp->entry = NULL; rp->next = mgr->reverse_pending; etcp_conn_set_ready_cbk(new_conn, cm_reverse_ready_cb, rp); mgr->reverse_pending = rp; } @@ -991,7 +940,7 @@ static void cm_bg_ping_timer_cb(void* arg) { while (e && cursor < mgr->bg_ping_cursor) { cursor++; e = e->next; } if (e) { struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e; - uint64_t node_id = nq->node.node_id; + uint64_t node_id = nq->node->node_id; if (node_id != mgr->instance->node_id) { struct ETCP_CONN* dconn = route_bgp_find_conn_for_node(bgp, node_id); int has_active = 0; @@ -1000,7 +949,7 @@ static void cm_bg_ping_timer_cb(void* arg) { while (l) { if (l->initialized && l->link_status) { has_active = 1; break; } l = l->next; } } if (!has_active) { - etcp_send_ping(mgr->instance, nq->node.public_key, NULL, CONN_PROBE_TIMEOUT_MS, + etcp_send_ping(mgr->instance, nq->node->public_key, NULL, CONN_PROBE_TIMEOUT_MS, NULL, NULL, NULL, 0); } } @@ -1032,7 +981,7 @@ static void cm_candidate_ping_timer_cb(void* arg) { while (l) { if (l->initialized && l->link_status) { has_active = 1; break; } l = l->next; } } if (has_active) - etcp_send_ping(mgr->instance, nq->node.public_key, &dconn->links->remote_addr, CONN_PROBE_TIMEOUT_MS, NULL, NULL, NULL, 0); + etcp_send_ping(mgr->instance, nq->node->public_key, &dconn->links->remote_addr, CONN_PROBE_TIMEOUT_MS, NULL, NULL, NULL, 0); else route_connectivity_probe_node(mgr->instance, nq); } diff --git a/src/control_server.c b/src/control_server.c index fb394fa4..9b58e5a7 100644 --- a/src/control_server.c +++ b/src/control_server.c @@ -1386,19 +1386,20 @@ static struct ETCP_CONN* find_connection_by_peer_id(struct UTUN_INSTANCE* instan * ============================================================================ */ static void send_single_node_info(struct control_server* server, struct control_client* client, struct NODEINFO_Q* nq) { - int dyn = nodeinfo_dyn_size(&nq->node); - size_t np_size = sizeof(struct etcpmon_msg_header) + 2 + sizeof(struct NODEINFO) + dyn; - + if (!server || !nq || !nq->node) return; + uint8_t buf[8192]; + int ser_len = nodeinfo_serialize(server->instance->bgp, nq, buf + 2, sizeof(buf) - 2); + if (ser_len < 0) { DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Failed to serialize node info"); return; } + buf[0] = CTRL_BGP_CMD; buf[1] = CTRL_BGP_SUBCMD; + size_t data_size = 2 + (size_t)ser_len; + + size_t np_size = sizeof(struct etcpmon_msg_header) + data_size; uint8_t* buffer = (uint8_t*)u_malloc(np_size); if (!buffer) { DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Failed to allocate node info buffer"); return; } struct etcpmon_msg_header* hdr = (struct etcpmon_msg_header*)buffer; - etcpmon_build_header(hdr, 2 + sizeof(struct NODEINFO) + dyn, ETCPMON_RSP_NODE_INFO, 0); - - uint8_t* pay = buffer + sizeof(*hdr); - pay[0] = CTRL_BGP_CMD; pay[1] = CTRL_BGP_SUBCMD; - memcpy(pay + 2, &nq->node, sizeof(struct NODEINFO)); - memcpy(pay + 2 + sizeof(struct NODEINFO), (uint8_t*)&nq->node + sizeof(struct NODEINFO), dyn); + etcpmon_build_header(hdr, (uint16_t)data_size, ETCPMON_RSP_NODE_INFO, 0); + memcpy(buffer + sizeof(*hdr), buf, data_size); control_client_send(server, client, buffer, (uint16_t)np_size); } diff --git a/src/etcp_connect.c b/src/etcp_connect.c index 548db3dd..09ae9c4b 100644 --- a/src/etcp_connect.c +++ b/src/etcp_connect.c @@ -70,61 +70,43 @@ static void connect_cancel(struct ETCP_CONNECT* ctx) { } static void connect_create_links_v4(struct ETCP_CONNECT* ctx, struct NODEINFO_Q* node) { - const struct NODEINFO_IPV4_ADDR* addrs; int ac = get_node_v4_addrs(node, &addrs); - for (int i = 0; i < ac; i++) { - if (addrs[i].port == 0) continue; - { int zero = 1; for (int j = 0; j < 4; j++) if (addrs[i].addr[j] != 0) { zero = 0; break; } if (zero) continue; } - struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - memcpy(&sin.sin_addr.s_addr, addrs[i].addr, 4); - sin.sin_port = htons(addrs[i].port); + if (!node || !node->node) return; + for (const struct NI_IPV4_ADDR* a = node->node->v4_addrs; a; a = a->next) { + if (a->port == 0) continue; + { int zero = 1; for (int j = 0; j < 4; j++) if (a->addr[j] != 0) { zero = 0; break; } if (zero) continue; } + struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; + memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port); struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin)); - if (!(addrs[i].protocol & NODE_PROTO_TCP)) { + if (!(a->protocol & NODE_PROTO_TCP)) { struct ETCP_SOCKET* s = ctx->instance->etcp_sockets; - while (s) { - if (s->local_addr.ss_family == AF_INET) - etcp_link_new(ctx->conn, s, &sa, 0); - s = s->next; - } + while (s) { if (s->local_addr.ss_family == AF_INET) etcp_link_new(ctx->conn, s, &sa, 0); s = s->next; } } - if ((addrs[i].protocol & NODE_PROTO_TCP) && !ctx->tcp_link) { + if ((a->protocol & NODE_PROTO_TCP) && !ctx->tcp_link) { struct stcp_link_config tcp_cfg = {.ua = ctx->instance->ua, .my_keys = &ctx->instance->my_keys, .inst = ctx->instance, .peer_pubkey = ctx->conn->crypto_ctx.peer_public_key, .peer_pubkey_mode = 0, - .remote_addr = &sa, .remote_port = addrs[i].port}; + .remote_addr = &sa, .remote_port = a->port}; ctx->tcp_link = stcp_link_connect(&tcp_cfg); - if (ctx->tcp_link) { - ctx->conn->transport_link = (void*)ctx->tcp_link; - stcp_link_set_on_ready(ctx->tcp_link, tcp_link_ready_cb, ctx); - stcp_link_set_on_close(ctx->tcp_link, tcp_link_close_cb, ctx); - } + if (ctx->tcp_link) { ctx->conn->transport_link = (void*)ctx->tcp_link; stcp_link_set_on_ready(ctx->tcp_link, tcp_link_ready_cb, ctx); stcp_link_set_on_close(ctx->tcp_link, tcp_link_close_cb, ctx); } } } } static void connect_create_links_v6(struct ETCP_CONNECT* ctx, struct NODEINFO_Q* node) { - const struct NODEINFO_IPV6_ADDR* addrs; int ac = get_node_v6_addrs(node, &addrs); - for (int i = 0; i < ac; i++) { - if (addrs[i].port == 0) continue; - int zero = 1; - for (int j = 0; j < 16; j++) if (addrs[i].addr[j] != 0) { zero = 0; break; } - if (zero) continue; - struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - memcpy(&sin6.sin6_addr, addrs[i].addr, 16); - sin6.sin6_port = htons(addrs[i].port); + if (!node || !node->node) return; + for (const struct NI_IPV6_ADDR* a = node->node->v6_addrs; a; a = a->next) { + if (a->port == 0) continue; + int zero = 1; for (int j = 0; j < 16; j++) if (a->addr[j] != 0) { zero = 0; break; } if (zero) continue; + struct sockaddr_in6 sin6; memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; + memcpy(&sin6.sin6_addr, a->addr, 16); sin6.sin6_port = htons(a->port); struct sockaddr_storage sa; memcpy(&sa, &sin6, sizeof(sin6)); - if (!(addrs[i].protocol & NODE_PROTO_TCP)) { + if (!(a->protocol & NODE_PROTO_TCP)) { struct ETCP_SOCKET* s = ctx->instance->etcp_sockets; - while (s) { - if (s->local_addr.ss_family == AF_INET6) - etcp_link_new(ctx->conn, s, &sa, 0); - s = s->next; - } + while (s) { if (s->local_addr.ss_family == AF_INET6) etcp_link_new(ctx->conn, s, &sa, 0); s = s->next; } } - if ((addrs[i].protocol & NODE_PROTO_TCP) && !ctx->tcp_link) { + if ((a->protocol & NODE_PROTO_TCP) && !ctx->tcp_link) { struct stcp_link_config tcp_cfg = {.ua = ctx->instance->ua, .my_keys = &ctx->instance->my_keys, .inst = ctx->instance, .peer_pubkey = ctx->conn->crypto_ctx.peer_public_key, .peer_pubkey_mode = 0, - .remote_addr = &sa, .remote_port = addrs[i].port}; + .remote_addr = &sa, .remote_port = a->port}; ctx->tcp_link = stcp_link_connect(&tcp_cfg); if (ctx->tcp_link) { ctx->conn->transport_link = (void*)ctx->tcp_link; @@ -226,7 +208,7 @@ static void connect_ready_cb(struct ETCP_CONN* conn, void* arg) { int etcp_connect(struct UTUN_INSTANCE* inst, struct NODEINFO_Q* node, etcp_connect_callback_t cb, void* arg, uint8_t flags) { if (!inst || !node || !cb) return -1; - uint64_t node_id = node->node.node_id; + uint64_t node_id = node->node->node_id; struct ETCP_CONN* existing = inst->connections; while (existing) { @@ -264,7 +246,7 @@ int etcp_connect(struct UTUN_INSTANCE* inst, struct NODEINFO_Q* node, DEBUG_ERROR(DEBUG_CATEGORY_ETCP_CONNECT, "[etcp_connect] sc_init_ctx failed for node 0x%016llx", (unsigned long long)node_id); etcp_connection_close(conn); cb(arg, NULL, 0); return -1; } - if (sc_set_peer_public_key(&conn->crypto_ctx, node->node.public_key, 0) != SC_OK) { + if (sc_set_peer_public_key(&conn->crypto_ctx, node->node->public_key, 0) != SC_OK) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP_CONNECT, "[etcp_connect] sc_set_peer_public_key failed for node 0x%016llx", (unsigned long long)node_id); etcp_connection_close(conn); cb(arg, NULL, 0); return -1; } diff --git a/src/etcp_connections.c b/src/etcp_connections.c index d419df48..935481a6 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -1314,7 +1314,7 @@ static void send_init_response(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pk route_bgp_update_my_nodeinfo(link->etcp->instance->bgp->instance, link->etcp->instance->bgp); struct ROUTE_BGP* bgp = link->etcp->instance->bgp; if (bgp->local_node && bgp->senders_list) { - bgp->local_node->node.ver = (bgp->local_node->node.ver % 255) + 1; + bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1; bgp->local_node->dirty = 1; struct ll_entry* se = bgp->senders_list->head; while (se) { diff --git a/src/etcp_router.c b/src/etcp_router.c index 9fb34a0d..27f3a76b 100644 --- a/src/etcp_router.c +++ b/src/etcp_router.c @@ -797,14 +797,14 @@ static int router_verify_signature(struct UTUN_INSTANCE* inst, struct ll_entry* } { uint8_t zero[SC_PUBKEY_SIZE] = {0}; - if (memcmp(nq->node.ed25519_public_key, zero, SC_PUBKEY_SIZE) == 0) { + if (memcmp(nq->node->ed25519_public_key, zero, SC_PUBKEY_SIZE) == 0) { DEBUG_WARN(DEBUG_CATEGORY_ETCPROUTE, "router: no Ed25519 pubkey for node %016llx — dropping", (unsigned long long)hdr->src_node_id); free_entry(entry); return -1; } } struct sc_stream_sign_state vfy_state; - if (sc_stream_sign_verify_init(&vfy_state, nq->node.ed25519_public_key) != SC_OK) { + if (sc_stream_sign_verify_init(&vfy_state, nq->node->ed25519_public_key) != SC_OK) { DEBUG_ERROR(DEBUG_CATEGORY_ETCPROUTE, "router: sign_verify_init failed for node %016llx", (unsigned long long)hdr->src_node_id); free_entry(entry); return -1; diff --git a/src/msg_transport.c b/src/msg_transport.c index dcd009b3..fc2ab406 100644 --- a/src/msg_transport.c +++ b/src/msg_transport.c @@ -470,8 +470,8 @@ static void handle_client_data(struct msg_transport* t, struct msg_client* clien break; } uint8_t buf[SC_PUBKEY_SIZE * 2]; - memcpy(buf, nq->node.public_key, SC_PUBKEY_SIZE); - memcpy(buf + SC_PUBKEY_SIZE, nq->node.ed25519_public_key, SC_PUBKEY_SIZE); + memcpy(buf, nq->node->public_key, SC_PUBKEY_SIZE); + memcpy(buf + SC_PUBKEY_SIZE, nq->node->ed25519_public_key, SC_PUBKEY_SIZE); send_response(client, MSG_RSP_PEER_INFO, peer_id, buf, SC_PUBKEY_SIZE * 2); DEBUG_INFO(DEBUG_CATEGORY_MSGTRANSPORT, "GET_PEER_INFO: peer=%016llx sent pubkey+edpub", (unsigned long long)peer_id); diff --git a/src/route6_lib.c b/src/route6_lib.c index 454ddb94..4ef58eb2 100644 --- a/src/route6_lib.c +++ b/src/route6_lib.c @@ -64,22 +64,16 @@ void route6_table_destroy(struct ROUTE6_TABLE *table) { } bool route6_insert(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) { - if (!table || !node) return false; - const struct NODEINFO_IPV6_SUBNET *subnets = NULL; - int cnt = get_node_v6_routes(node, &subnets); - if (cnt <= 0) { - DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route6_insert: node has no v6 subnets"); - return false; - } - for (int i = 0; i < cnt; i++) { + if (!table || !node || !node->routes || !node->routes->v6_subnets) return false; + for (const struct NI_IPV6_SUBNET* s = node->routes->v6_subnets; s; s = s->next) { struct ll_entry *entry = queue_entry_new(ROUTE6_DATA_SIZE); if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route6_insert: queue_entry_new failed"); return false; } struct ROUTE6_DATA *rd = (struct ROUTE6_DATA *)entry->data; - make_key6(rd->key, subnets[i].addr); - make_mask6(rd->mask, subnets[i].prefix_length); + make_key6(rd->key, s->addr); + make_mask6(rd->mask, s->prefix_length); rd->v_node_info = node; - rd->node_id = node->node.node_id; - rd->prefix_length = subnets[i].prefix_length; + rd->node_id = node->node->node_id; + rd->prefix_length = s->prefix_length; struct radix_node *rn = rn_addroute(rd->key, rd->mask, &table->rnh->rh, rd->rn_nodes); if (!rn) { queue_entry_free(entry); continue; } queue_data_put_with_index(table->queue, entry); @@ -89,7 +83,7 @@ bool route6_insert(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) { void route6_delete(struct ROUTE6_TABLE *table, struct NODEINFO_Q *node) { if (!table || !node) return; - uint64_t node_id = node->node.node_id; + uint64_t node_id = node->node->node_id; struct ll_entry *entry = queue_find_data_by_index(table->queue, &node_id); while (entry) { struct ROUTE6_DATA *rd = (struct ROUTE6_DATA *)entry->data; diff --git a/src/route_bgp.c b/src/route_bgp.c index 5c699db9..f4e65537 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -1,6 +1,6 @@ /** * @file route_bgp.c - * @brief BGP-like обмен маршрутами — исправленная версия под новую route_lib + * @brief BGP-like обмен маршрутами */ #include #include @@ -8,6 +8,7 @@ #include "../lib/platform_compat.h" #include "../lib/debug_config.h" #include "../lib/mem.h" +#include "../lib/memory_pool.h" #include "utun_instance.h" #include "etcp_api.h" #include "etcp.h" @@ -35,16 +36,9 @@ static void route_bgp_send_table_request(struct ROUTE_BGP* bgp, struct ETCP_CONN req->cmd = ETCP_ID_ROUTE_ENTRY; req->subcmd = ROUTE_SUBCMD_REQUEST_TABLE; struct ll_entry* e = queue_entry_new(0); - if (!e) { - u_free(req); - return; - } - e->dgram = (uint8_t*)req; - e->len = sizeof(struct BGP_ROUTE_REQUEST); - if (etcp_send(conn, e) != 0) { - u_free(req); - queue_entry_free(e); - } + if (!e) { u_free(req); return; } + e->dgram = (uint8_t*)req; e->len = sizeof(struct BGP_ROUTE_REQUEST); + if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); } } static void route_bgp_send_table_complete(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) { @@ -55,8 +49,7 @@ static void route_bgp_send_table_complete(struct ROUTE_BGP* bgp, struct ETCP_CON req->subcmd = ROUTE_SUBCMD_TABLE_COMPLETE; struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(req); return; } - e->dgram = (uint8_t*)req; - e->len = sizeof(struct BGP_ROUTE_REQUEST); + e->dgram = (uint8_t*)req; e->len = sizeof(struct BGP_ROUTE_REQUEST); if (etcp_send(conn, e) != 0) { u_free(req); queue_entry_free(e); } } @@ -64,12 +57,11 @@ static void route_bgp_add_to_senders(struct ROUTE_BGP* bgp, struct ETCP_CONN* co static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t target_id); static void route_bgp_send_full_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn); static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn); -static void route_bgp_send_table_complete(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn); static void nodeinfo_dump_log(const uint8_t* data, size_t len) { if (!data || len < sizeof(struct BGP_NODEINFO_PACKET)) return; struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data; - struct NODEINFO* ni = &pkt->node; + struct NODEINFO_MSG* ni = &pkt->node; DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NODEINFO nid=%016llx ver=%u v4s=%u v4a=%u hops=%u", (unsigned long long)ni->node_id, ni->ver, ni->local_v4_sockets, ni->local_v4_addrs, ni->hop_count); @@ -78,7 +70,7 @@ static void nodeinfo_dump_log(const uint8_t* data, size_t len) { static char* nodeinfo_format(const uint8_t* data, size_t len) { if (!data || len < sizeof(struct BGP_NODEINFO_PACKET)) return NULL; struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data; - struct NODEINFO* ni = &pkt->node; + struct NODEINFO_MSG* ni = &pkt->node; uint64_t node_id = ni->node_id; const uint8_t* dyn = data + sizeof(struct BGP_NODEINFO_PACKET); size_t off = 0; @@ -102,8 +94,7 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) { } } int need = snprintf(NULL,0,"NODEINFO nid=%016llx ver=%u name=\"%s\" v4subs=\"%s\" v4s=%u v4a=%u hop=%u", (unsigned long long)node_id,(unsigned)ni->ver,name_buf,subs_buf,(unsigned)ni->local_v4_sockets,(unsigned)ni->local_v4_addrs,(unsigned)ni->hop_count); - char* buf = u_malloc(need+1); - if (!buf) return NULL; + char* buf = u_malloc(need+1); if (!buf) return NULL; snprintf(buf,need+1,"NODEINFO nid=%016llx ver=%u name=\"%s\" v4subs=\"%s\" v4s=%u v4a=%u hop=%u", (unsigned long long)node_id,(unsigned)ni->ver,name_buf,subs_buf,(unsigned)ni->local_v4_sockets,(unsigned)ni->local_v4_addrs,(unsigned)ni->hop_count); return buf; } @@ -122,29 +113,23 @@ static const char* bgp_subcmd_name(uint8_t subcmd) { } } + // ============================================================================ -// Broadcast / Withdraw: node_id - удаляемый узел, wd_source - от кого получена команда удалить +// Broadcast / Withdraw // ============================================================================ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id, uint64_t wd_source, struct ETCP_CONN* exclude) { if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "bgp is NULL"); return; } struct BGP_WITHDRAW_PACKET* pkt = u_calloc(1, sizeof(struct BGP_WITHDRAW_PACKET)); if (!pkt) return; - pkt->cmd = ETCP_ID_ROUTE_ENTRY; - pkt->subcmd = ROUTE_SUBCMD_WITHDRAW; - pkt->node_id = node_id; - pkt->wd_source = wd_source; + pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_WITHDRAW; + pkt->node_id = node_id; pkt->wd_source = wd_source; struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL; while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; if (item && item->conn && item->conn != exclude) { struct ll_entry* copy = queue_entry_new(0); - if (copy) { - copy->dgram = u_malloc(sizeof(*pkt)); - if (copy->dgram) memcpy(copy->dgram, pkt, sizeof(*pkt)); - copy->len = sizeof(*pkt); - etcp_send(item->conn, copy); - } + if (copy) { copy->dgram = u_malloc(sizeof(*pkt)); if (copy->dgram) memcpy(copy->dgram, pkt, sizeof(*pkt)); copy->len = sizeof(*pkt); etcp_send(item->conn, copy); } } e = e->next; } @@ -160,58 +145,25 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len); static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) { - if (!from_conn || !entry || entry->len < 2) { - if (entry) { - queue_dgram_free(entry); - queue_entry_free(entry); - } - return; - } - + if (!from_conn || !entry || entry->len < 2) { if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; } struct UTUN_INSTANCE* instance = from_conn->instance; - if (!instance || !instance->bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_receive_cbk: invalid instance/bgp"); - queue_dgram_free(entry); - queue_entry_free(entry); - return; - } - + if (!instance || !instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_receive_cbk: invalid instance/bgp"); queue_dgram_free(entry); queue_entry_free(entry); return; } struct ROUTE_BGP* bgp = instance->bgp; - uint8_t* data = entry->dgram; - uint8_t cmd = data[0]; - uint8_t subcmd = data[1]; - - if (cmd != ETCP_ID_ROUTE_ENTRY) { - queue_dgram_free(entry); - queue_entry_free(entry); - return; - } + uint8_t* data = entry->dgram; uint8_t cmd = data[0]; uint8_t subcmd = data[1]; + if (cmd != ETCP_ID_ROUTE_ENTRY) { queue_dgram_free(entry); queue_entry_free(entry); return; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu", - bgp_subcmd_name(subcmd), from_conn->log_name, entry->len); - - if (subcmd == ROUTE_SUBCMD_NODEINFO) { - nodeinfo_dump_log(data, entry->len); - route_bgp_process_nodeinfo(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_WITHDRAW) { - route_bgp_process_withdraw(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_REQUEST_TABLE) { - route_bgp_handle_request_table(bgp, from_conn); - } else if (subcmd == ROUTE_SUBCMD_PING_REQ) { - route_ping_handle_req(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_PING_RESP) { - route_ping_handle_resp(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_NAT_INFO) { - route_bgp_handle_nat_info(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) { - route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len); - } else if (subcmd == ROUTE_SUBCMD_TABLE_COMPLETE) { - etcp_set_routing_exchange_state(from_conn, 3); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP initial sync complete with %s", from_conn->log_name); - } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP recv %s from %s len=%zu", bgp_subcmd_name(subcmd), from_conn->log_name, entry->len); + + if (subcmd == ROUTE_SUBCMD_NODEINFO) { nodeinfo_dump_log(data, entry->len); route_bgp_process_nodeinfo(bgp, from_conn, data, entry->len); } + else if (subcmd == ROUTE_SUBCMD_WITHDRAW) route_bgp_process_withdraw(bgp, from_conn, data, entry->len); + else if (subcmd == ROUTE_SUBCMD_REQUEST_TABLE) route_bgp_handle_request_table(bgp, from_conn); + else if (subcmd == ROUTE_SUBCMD_PING_REQ) route_ping_handle_req(bgp, from_conn, data, entry->len); + else if (subcmd == ROUTE_SUBCMD_PING_RESP) route_ping_handle_resp(bgp, from_conn, data, entry->len); + else if (subcmd == ROUTE_SUBCMD_NAT_INFO) route_bgp_handle_nat_info(bgp, from_conn, data, entry->len); + else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len); + else if (subcmd == ROUTE_SUBCMD_TABLE_COMPLETE) { etcp_set_routing_exchange_state(from_conn, 3); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP initial sync complete with %s", from_conn->log_name); } - queue_dgram_free(entry); - queue_entry_free(entry); + queue_dgram_free(entry); queue_entry_free(entry); } @@ -219,103 +171,48 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* // Init / Destroy / New / Remove conn // ============================================================================ -// Callback для готовности ETCP соединения - отправляет маршруты static void route_bgp_on_conn_up(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->bgp) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer UP: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); - route_bgp_new_conn(conn); - } + (void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer UP: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); route_bgp_new_conn(conn); } } - static void route_bgp_on_conn_down(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->bgp) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer DOWN: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); - route_bgp_remove_conn(conn); - } + (void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer DOWN: %s peer=%016llx", conn->log_name, (unsigned long long)conn->peer_node_id); route_bgp_remove_conn(conn); } } - -// Callback для новых ETCP соединений - устанавливает ready callback static void route_bgp_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) { - (void)arg; - if (conn && conn->instance && conn->instance->bgp) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP set callbacks: %s", conn->log_name); - etcp_conn_add_up_cbk(conn, route_bgp_on_conn_up, conn->instance->bgp); - etcp_conn_add_down_cbk(conn, route_bgp_on_conn_down, conn->instance->bgp); - } + (void)arg; if (conn && conn->instance && conn->instance->bgp) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP set callbacks: %s", conn->log_name); etcp_conn_add_up_cbk(conn, route_bgp_on_conn_up, conn->instance->bgp); etcp_conn_add_down_cbk(conn, route_bgp_on_conn_down, conn->instance->bgp); } } struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) { - if (!instance) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: instance is NULL"); - return NULL; - } - - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_init: node_id=%016llx", - (unsigned long long)instance->node_id); + if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: instance is NULL"); return NULL; } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_init: node_id=%016llx", (unsigned long long)instance->node_id); struct ROUTE_BGP* bgp = u_calloc(1, sizeof(struct ROUTE_BGP)); - if (!bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: alloc failed"); - return NULL; - } - + if (!bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: alloc failed"); return NULL; } bgp->instance = instance; - bgp->ping_pending = NULL; - bgp->next_ping_req_id = 1; - bgp->nodeinfo_env = NULL; - bgp->nodeinfo_dbi = 0; + bgp->ping_pending = NULL; bgp->next_ping_req_id = 1; + bgp->nodeinfo_env = NULL; bgp->nodeinfo_dbi = 0; sc_derive_ed25519_pubkey(instance->my_keys.private_key, bgp->ed25519_public_key); DEBUG_INFO(DEBUG_CATEGORY_BGP, "Ed25519 pubkey derived from X25519 private key"); - // Создаём/открываем LMDB базу nodeinfo если задан db_path в конфиге - if (instance->config && instance->config->global.db_path[0]) { - route_node_lmdb_init(bgp, instance->config->global.db_path); - } + if (instance->config && instance->config->global.db_path[0]) route_node_lmdb_init(bgp, instance->config->global.db_path); - // Create nodes queue with hash support for fast lookup by node_id - bgp->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct NODEINFO_Q, node.node_id)-sizeof(struct ll_entry), 8, "bgp_nodes"); - if (!bgp->nodes) { - u_free(bgp); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: nodes queue creation failed"); - return NULL; - } + bgp->nodes = queue_new(instance->ua, BGP_NODES_HASH_SIZE, offsetof(struct NODEINFO_Q, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes"); + if (!bgp->nodes) { u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: nodes queue creation failed"); return NULL; } bgp->senders_list = queue_new(instance->ua, 0, 0, 0, "BGP_senders"); - if (!bgp->senders_list) { - queue_free(bgp->nodes); - u_free(bgp); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: senders_list queue creation failed"); - return NULL; - } + if (!bgp->senders_list) { queue_free(bgp->nodes); u_free(bgp); DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: senders_list queue creation failed"); return NULL; } - int vc = 0; - struct CFG_ROUTE_ENTRY* s = instance->config->my_subnets; - while (s) { - if (s->ip.family == AF_INET) vc++; - s = s->next; - } - size_t d = vc * sizeof(struct NODEINFO_IPV4_SUBNET); - bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + d); - if (!bgp->local_node) { - queue_free(bgp->nodes); - queue_free(bgp->senders_list); - u_free(bgp); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_init: local_node alloc failed"); - return NULL; - } + bgp->v4_sock_meta_pool = memory_pool_init(sizeof(struct NI_IPV4_SOCKET_META), "ni_v4sock"); + bgp->v4_addr_pool = memory_pool_init(sizeof(struct NI_IPV4_ADDR), "ni_v4addr"); + bgp->v6_sock_meta_pool = memory_pool_init(sizeof(struct NI_IPV6_SOCKET_META), "ni_v6sock"); + bgp->v6_addr_pool = memory_pool_init(sizeof(struct NI_IPV6_ADDR), "ni_v6addr"); + bgp->v4_subnet_pool = memory_pool_init(sizeof(struct NI_IPV4_SUBNET), "ni_v4sub"); + bgp->v6_subnet_pool = memory_pool_init(sizeof(struct NI_IPV6_SUBNET), "ni_v6sub"); - bgp->local_node->node.node_id = instance->node_id; - bgp->local_node->node.hop_count = 0; - bgp->local_node->node.ver = 1; - bgp->local_node->dirty = 0; + bgp->local_node = NULL; route_bgp_update_my_nodeinfo(instance, bgp); etcp_bind(instance, ETCP_ID_ROUTE_ENTRY, route_bgp_receive_cbk); - - // Устанавливаем callback для новых ETCP соединений etcp_add_new_conn_cbk(instance, route_bgp_etcp_conn_cbk, NULL); DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized (NODEINFO based routing)"); @@ -323,142 +220,68 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) { } void route_bgp_destroy(struct UTUN_INSTANCE* instance) { - if (!instance) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: instance is NULL"); - return; - } - if (!instance->bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: bgp is NULL"); - return; - } - - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_destroy: node_id=%016llx", - (unsigned long long)instance->node_id); + if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: instance is NULL"); return; } + if (!instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_destroy: bgp is NULL"); return; } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_destroy: node_id=%016llx", (unsigned long long)instance->node_id); etcp_unbind(instance, ETCP_ID_ROUTE_ENTRY); - route_connectivity_cancel_all(instance); -// route_ping_destroy_pending(instance->bgp); - struct ll_entry* e; - while ((e = queue_data_get(instance->bgp->senders_list)) != NULL) { - queue_entry_free(e); - } + while ((e = queue_data_get(instance->bgp->senders_list)) != NULL) queue_entry_free(e); queue_free(instance->bgp->senders_list); - if (instance->bgp->local_node) { - if (instance->bgp->local_node->paths) { - queue_free(instance->bgp->local_node->paths); - } - u_free(instance->bgp->local_node); - } + if (instance->bgp->local_node) { nodeinfo_free_lists(instance->bgp, instance->bgp->local_node); u_free(instance->bgp->local_node); } route_node_lmdb_destroy(instance->bgp); - if (instance->bgp->nodes) { - queue_free(instance->bgp->nodes); - } + if (instance->bgp->nodes) queue_free(instance->bgp->nodes); - u_free(instance->bgp); - instance->bgp = NULL; -} + memory_pool_destroy(instance->bgp->v4_sock_meta_pool); + memory_pool_destroy(instance->bgp->v4_addr_pool); + memory_pool_destroy(instance->bgp->v6_sock_meta_pool); + memory_pool_destroy(instance->bgp->v6_addr_pool); + memory_pool_destroy(instance->bgp->v4_subnet_pool); + memory_pool_destroy(instance->bgp->v6_subnet_pool); -void route_bgp_set_nat_check_local(struct ROUTE_BGP* bgp, int allow) { - if (!bgp) return; - bgp->allow_nat_check_local = allow ? 1 : 0; + u_free(instance->bgp); instance->bgp = NULL; } +void route_bgp_set_nat_check_local(struct ROUTE_BGP* bgp, int allow) { if (!bgp) return; bgp->allow_nat_check_local = allow ? 1 : 0; } + void route_bgp_new_conn(struct ETCP_CONN* conn) { - if (!conn) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn is NULL"); - return; - } - if (!conn->instance) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance is NULL"); - return; - } - if (!conn->instance->bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->bgp is NULL"); - return; - } - if (!conn->instance->rt) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->rt is NULL"); - return; - } + if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn is NULL"); return; } + if (!conn->instance) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance is NULL"); return; } + if (!conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->bgp is NULL"); return; } + if (!conn->instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn->instance->rt is NULL"); return; } struct ROUTE_BGP* bgp = conn->instance->bgp; struct NODEINFO_Q* peer_nq = nodeinfo_find_by_id(bgp, conn->peer_node_id); - route_bgp_add_to_senders(bgp, conn); + if (peer_nq && peer_nq->alien) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: peer 0x%016llx is alien, skipping route exchange", (unsigned long long)conn->peer_node_id); return; } - if (peer_nq && peer_nq->alien) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: peer 0x%016llx is alien, skipping route exchange", - (unsigned long long)conn->peer_node_id); - return; - } - - // Scan ALL connections and ALL links in instance - start NAT check if not started struct ETCP_CONN* c = conn->instance->connections; - while (c) { - struct ETCP_LINK* l = c->links; - while (l) { - if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) { - route_bgp_start_link_nat_check(bgp, l); - } - l = l->next; - } - c = c->next; - } + while (c) { struct ETCP_LINK* l = c->links; while (l) { if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) route_bgp_start_link_nat_check(bgp, l); l = l->next; } c = c->next; } route_bgp_send_table_request(bgp, conn); } void route_bgp_remove_conn(struct ETCP_CONN* conn) { - if (!conn) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn is NULL"); - return; - } - if (!conn->instance || !conn->instance->bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: invalid instance/bgp"); - return; - } - + if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn is NULL"); return; } + if (!conn->instance || !conn->instance->bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: invalid instance/bgp"); return; } struct ROUTE_BGP* bgp = conn->instance->bgp; - // SAFETY: проверяем что conn ещё есть в senders_list bool found_in_list = false; struct ll_entry* e = bgp->senders_list->head; - while (e) { - struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; - if (item->conn == conn) { - found_in_list = true; - break; - } - e = e->next; - } - - if (!found_in_list) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn already removed or not in list, skipping"); - return; - } + while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; if (item->conn == conn) { found_in_list = true; break; } e = e->next; } + if (!found_in_list) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: conn already removed or not in list, skipping"); return; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: peer=%016llx", - (unsigned long long)conn->peer_node_id); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_remove_conn: peer=%016llx", (unsigned long long)conn->peer_node_id); - // Cancel pending NAT checks for this connection's links route_ping_cancel_for_conn(bgp, conn); - struct ETCP_LINK* lnk = conn->links; - while (lnk) { - if (lnk->nat_check_status == NAT_CHECK_IN_PROGRESS) { - lnk->nat_check_status = NAT_CHECK_NONE; - } - lnk = lnk->next; - } + struct ETCP_LINK* lnk = conn->links; while (lnk) { if (lnk->nat_check_status == NAT_CHECK_IN_PROGRESS) lnk->nat_check_status = NAT_CHECK_NONE; lnk = lnk->next; } struct ROUTE_TABLE* rt = conn->instance->rt; - - // Remove this connection from all nodes' path lists int nodes_removed = 0; struct ll_entry* node_entry = bgp->nodes ? bgp->nodes->head : NULL; while (node_entry) { @@ -466,12 +289,12 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) { struct NODEINFO_Q* nq = (struct NODEINFO_Q*)node_entry; if (route_bgp_remove_path(nq, conn) == 1) { if (rt) route_delete(rt, nq); - if (conn->instance && conn->instance->control_srv) - control_server_notify_node_removed(conn->instance->control_srv, nq->node.node_id); + if (conn->instance && conn->instance->control_srv) control_server_notify_node_removed(conn->instance->control_srv, nq->hash_node_id); nq->dirty = 1; route_connectivity_cancel_node(conn->instance, nq); if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } - uint64_t key = nq->node.node_id; + uint64_t key = nq->hash_node_id; + nodeinfo_free_lists(bgp, nq); struct ll_entry* entry = node_entry; if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); } nodes_removed++; @@ -483,70 +306,41 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) { node_entry = next; } - // Удаляем из списка рассылки e = bgp->senders_list->head; - while (e) { - struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; - if (item->conn == conn) { - queue_remove_data(bgp->senders_list, e); - queue_entry_free(e); - break; - } - e = e->next; - } + while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; if (item->conn == conn) { queue_remove_data(bgp->senders_list, e); queue_entry_free(e); break; } e = e->next; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", - conn->log_name, nodes_removed); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP peer removed: %s nodes=%d", conn->log_name, nodes_removed); } -/* ================================================ - * NEW NODEINFO BASED IMPLEMENTATION - * ================================================ */ +// ============================================================================ +// NEW NODEINFO BASED IMPLEMENTATION +// ============================================================================ struct ETCP_CONN* route_bgp_find_conn_for_node(struct ROUTE_BGP* bgp, uint64_t node_id) { if (!bgp) return NULL; struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, node_id); if (!nq || !nq->paths || !nq->paths->head) return NULL; struct ll_entry* e = nq->paths->head; - struct NODEINFO_PATH* best_live = NULL; - uint8_t best_live_hops = 255; - struct NODEINFO_PATH* best_any = NULL; - uint8_t best_any_hops = 255; + struct NODEINFO_PATH* best_live = NULL; uint8_t best_live_hops = 255; + struct NODEINFO_PATH* best_any = NULL; uint8_t best_any_hops = 255; while (e) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e; - if (path->conn) { - if (path->conn->links_up && path->hop_count < best_live_hops) { best_live = path; best_live_hops = path->hop_count; } - if (path->hop_count < best_any_hops) { best_any = path; best_any_hops = path->hop_count; } - } + if (path->conn) { if (path->conn->links_up && path->hop_count < best_live_hops) { best_live = path; best_live_hops = path->hop_count; } if (path->hop_count < best_any_hops) { best_any = path; best_any_hops = path->hop_count; } } e = e->next; } - if (!best_live && best_any) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "find_conn_for_node %016llx: no live paths, fallback to best (hops=%d links_up=%d)", - (unsigned long long)node_id, best_any_hops, best_any->conn->links_up); - } + if (!best_live && best_any) DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "find_conn_for_node %016llx: no live paths, fallback to best (hops=%d links_up=%d)", (unsigned long long)node_id, best_any_hops, best_any->conn->links_up); return best_live ? best_live->conn : (best_any ? best_any->conn : NULL); } int route_bgp_add_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn, uint64_t* hop_list, uint8_t hop_count) { - if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args"); - return -1; - } - if (!nq->paths) { - nq->paths = queue_new(conn->instance->ua, 0, 0, 0, "node_paths"); - if (!nq->paths) return -1; - } - size_t hop_size = hop_count * 8; - size_t path_size = sizeof(struct NODEINFO_PATH) - sizeof(struct ll_entry) + hop_size; - struct ll_entry* pe = queue_entry_new(path_size); - if (!pe) return -1; + if (!nq || !conn || hop_count > MAX_HOPS || !hop_list) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "add_path: invalid args"); return -1; } + if (!nq->paths) { nq->paths = queue_new(conn->instance->ua, 0, 0, 0, "node_paths"); if (!nq->paths) return -1; } + size_t path_size = sizeof(struct NODEINFO_PATH) - sizeof(struct ll_entry) + hop_count * 8; + struct ll_entry* pe = queue_entry_new(path_size); if (!pe) return -1; struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe; - path->conn = conn; - path->hop_count = hop_count; - uint64_t* stored = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); - memcpy(stored, hop_list, hop_size); - DEBUG_TRACE(DEBUG_CATEGORY_BGP, "Added path for node %016llx via conn %s with %d hops", (unsigned long long)nq->node.node_id, conn->log_name, hop_count); + path->conn = conn; path->hop_count = hop_count; + memcpy((uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)), hop_list, hop_count * 8); queue_data_put(nq->paths, pe); return 0; } @@ -557,232 +351,100 @@ int route_bgp_remove_path_by_hop(struct NODEINFO_Q* nq, uint64_t wd_source) { struct ll_entry* e = nq->paths->head; while (e) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e; - // parse hoplist in dyn after hop_count (after fixed PATH) uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); - bool has_wd = false; - for (uint8_t i = 0; i < path->hop_count; i++) { - if (hop[i] == wd_source) { - has_wd = true; - break; - } - } - if (has_wd) { - struct ll_entry* next = e->next; - queue_remove_data(nq->paths, e); - queue_entry_free(e); - removed++; - e = next; - continue; - } + bool has_wd = false; for (uint8_t i = 0; i < path->hop_count; i++) if (hop[i] == wd_source) { has_wd = true; break; } + if (has_wd) { struct ll_entry* next = e->next; queue_remove_data(nq->paths, e); queue_entry_free(e); removed++; e = next; continue; } e = e->next; } - if (removed > 0 && nq->paths && queue_entry_count(nq->paths) == 0) { - queue_free(nq->paths); - nq->paths = NULL; - return 1; // unreachable - } + if (removed > 0 && nq->paths && queue_entry_count(nq->paths) == 0) { queue_free(nq->paths); nq->paths = NULL; return 1; } return removed; } -int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) -{ - if (!nq || !conn || !nq->paths) { - return -1; - } - - // Remove conn from paths queue +int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn) { + if (!nq || !conn || !nq->paths) return -1; struct ll_entry* e = nq->paths->head; - while (e) { - struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e; - if (path->conn == conn) { - queue_remove_data(nq->paths, e); - queue_entry_free(e); - break; - } - e = e->next; - } - + while (e) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e; if (path->conn == conn) { queue_remove_data(nq->paths, e); queue_entry_free(e); break; } e = e->next; } int remaining = nq->paths ? queue_entry_count(nq->paths) : 0; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Removed path for node %016llx via %s, remaining paths: %d", - (unsigned long long)nq->node.node_id, conn->log_name, remaining); - - // If no paths left - node is unreachable - if (remaining == 0) { - if (nq->paths) { - queue_free(nq->paths); - nq->paths = NULL; - } - return 1; // signal that node became unreachable - } + if (remaining == 0) { if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } return 1; } return 0; } -int nodeinfo_dyn_size(struct NODEINFO* node) { - return node->node_name_len + - node->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET_META) + - node->local_v4_addrs * sizeof(struct NODEINFO_IPV4_ADDR) + - node->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET_META) + - node->local_v6_addrs * sizeof(struct NODEINFO_IPV6_ADDR) + - node->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET) + - node->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET) + - node->tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE) + - node->hop_count * 8; -} - // NAT check context -static void nat_link_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent, uint8_t count_ok, - void* arg) { +static void nat_link_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent, uint8_t count_ok, void* arg) { (void)avg_rtt; (void)count_sent; (void)count_ok; struct nat_check_arg* na = (struct nat_check_arg*)arg; if (!na || !na->link) { u_free(na); return; } struct ETCP_LINK* link = na->link; - // Защита: если conn упал, статус уже сброшен в NONE - if (link->nat_check_status != NAT_CHECK_IN_PROGRESS) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "nat check cb: link status=%d, skip (conn down?)", link->nat_check_status); - u_free(na); - return; - } - uint8_t nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT; - link->nat_type = nat_type; + if (link->nat_check_status != NAT_CHECK_IN_PROGRESS) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "nat check cb: link status=%d, skip (conn down?)", link->nat_check_status); u_free(na); return; } + link->nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT; link->nat_check_status = success ? NAT_CHECK_EIM : NAT_CHECK_STRICT; - // Send NAT_INFO to peer (via their connection) - if (link->etcp) { - uint8_t socket_id = link->remote_socket_id; - route_bgp_send_nat_info(link->etcp, socket_id, na->nat_ip, na->nat_port, nat_type); - } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check result: type=%s for conn=%s nat=%s:%u", - success ? "EIM" : "STRICT", link->etcp->log_name, - ip_to_str(&na->nat_ip, AF_INET).str, na->nat_port); + if (link->etcp) route_bgp_send_nat_info(link->etcp, link->remote_socket_id, na->nat_ip, na->nat_port, link->nat_type); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check result: type=%s for conn=%s nat=%s:%u", success ? "EIM" : "STRICT", link->etcp->log_name, ip_to_str(&na->nat_ip, AF_INET).str, na->nat_port); u_free(na); } static struct ETCP_CONN* route_bgp_find_third_node(struct ROUTE_BGP* bgp, struct ETCP_CONN* exclude) { if (!bgp || !bgp->senders_list) return NULL; struct ll_entry* e = bgp->senders_list->head; - while (e) { - struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; - if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0) { - // Skip nodes with private socket type - they can't help with NAT detection - if (item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE - && item->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) return item->conn; - } - e = e->next; - } + while (e) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; if (item && item->conn && item->conn != exclude && item->conn->links && item->conn->links->remote_only_local==0 && item->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE && item->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) return item->conn; e = e->next; } return NULL; } static void route_bgp_extract_nat_addr(struct ETCP_CONN* conn, uint32_t* nat_ip, uint16_t* nat_port) { - *nat_ip = 0; *nat_port = 0; - if (!conn) return; - struct ETCP_LINK* l = conn->links; - while (l) { - if (l->nat_ip != 0) { - *nat_ip = l->nat_ip; - *nat_port = l->nat_port; - return; - } - l = l->next; - } + *nat_ip = 0; *nat_port = 0; if (!conn) return; + struct ETCP_LINK* l = conn->links; while (l) { if (l->nat_ip != 0) { *nat_ip = l->nat_ip; *nat_port = l->nat_port; return; } l = l->next; } } -void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) {// проверяем тип нат для линка link +void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) { if (!bgp || !link || !link->conn || !link->etcp) return; if (link->nat_type == NAT_TYPE_DIRECT) return; if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; - // Skip NAT check for private sockets - they are not reachable from outside - if (link->conn->type == CFG_SERVER_TYPE_PRIVATE || link->conn->type == CFG_SERVER_TYPE_LOCAL) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private/local socket link"); - return; - } - // Find third node to send ping through + if (link->conn->type == CFG_SERVER_TYPE_PRIVATE || link->conn->type == CFG_SERVER_TYPE_LOCAL) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "skip nat check for private/local socket link"); return; } struct ETCP_CONN* third_conn = route_bgp_find_third_node(bgp, link->etcp); - if (!third_conn) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no third node found for link"); - return; - } + if (!third_conn) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no third node found for link"); return; } - // Get target address - use nat_ip/nat_port if set, otherwise use remote_addr - /* link->nat_ip и sin_addr.s_addr в network byte order */ - uint32_t target_ip; - uint16_t target_port; - if (link->nat_ip != 0 && link->nat_port != 0) { - target_ip = link->nat_ip; - target_port = link->nat_port; - } else { - struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; - target_ip = sin->sin_addr.s_addr; - target_port = ntohs(sin->sin_port); /* port в host order для API */ - } + uint32_t target_ip; uint16_t target_port; + if (link->nat_ip != 0 && link->nat_port != 0) { target_ip = link->nat_ip; target_port = link->nat_port; } + else { struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; target_ip = sin->sin_addr.s_addr; target_port = ntohs(sin->sin_port); } - if (!bgp->allow_nat_check_local && is_local_subnet(target_ip)) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "local connection: %s, skip nat check", ip_to_str(&target_ip, AF_INET).str); - return; - } + if (!bgp->allow_nat_check_local && is_local_subnet(target_ip)) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "local connection: %s, skip nat check", ip_to_str(&target_ip, AF_INET).str); return; } - // Allocate callback arg struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg)); - if (!arg) return; - arg->link = link; - arg->nat_ip = target_ip; - arg->nat_port = target_port; - // Use peer public key from the connection's crypto context + if (!arg) return; arg->link = link; arg->nat_ip = target_ip; arg->nat_port = target_port; const uint8_t* pubkey = link->etcp->crypto_ctx.peer_key_set ? link->etcp->crypto_ctx.peer_public_key : NULL; - if (!pubkey) { - u_free(arg); - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no peer pubkey for link=%p", (void*)link); - return; - } - // Send ping via third node - embed peer pubkey for NAT detection - int ret = route_ping_send_req_addr(bgp, third_conn, target_ip, target_port, - 3, 500, 1000, 5000, nat_link_check_cb, arg, - pubkey); - if (ret == 0) { - link->nat_check_status = NAT_CHECK_IN_PROGRESS; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping remote request via=%s (%s:%d)", - third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); - } else { - u_free(arg); - DEBUG_WARN(DEBUG_CATEGORY_BGP, "failed to start for link=%s (%s:%d)", - third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); - } + if (!pubkey) { u_free(arg); DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no peer pubkey for link=%p", (void*)link); return; } + int ret = route_ping_send_req_addr(bgp, third_conn, target_ip, target_port, 3, 500, 1000, 5000, nat_link_check_cb, arg, pubkey); + if (ret == 0) { link->nat_check_status = NAT_CHECK_IN_PROGRESS; DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping remote request via=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); } + else { u_free(arg); DEBUG_WARN(DEBUG_CATEGORY_BGP, "failed to start for link=%s (%s:%d)", third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); } } +// ===== NODEINFO process ===== + int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, const uint8_t* data, size_t len) { if (!bgp || !from || len < sizeof(struct BGP_NODEINFO_PACKET)) return -1; struct BGP_NODEINFO_PACKET* pkt = (struct BGP_NODEINFO_PACKET*)data; - struct NODEINFO* ni = &pkt->node; - int dyn_size=nodeinfo_dyn_size(ni); - if (len!=dyn_size + sizeof(struct BGP_NODEINFO_PACKET)) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "Incorrect packet size (%s)",from->log_name); - return -1; - } + struct NODEINFO_MSG* ni = &pkt->node; + int dyn = nodeinfo_dyn_size(ni); + if ((size_t)dyn + sizeof(struct BGP_NODEINFO_PACKET) != len) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "Incorrect packet size (%s)", from->log_name); return -1; } uint64_t node_id = ni->node_id; - - if (ni->hop_count >= MAX_HOPS) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)", - from->log_name, ni->hop_count); - return -1; - } + if (ni->hop_count >= MAX_HOPS) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "NODEINFO from %s dropped: too many hops (%d)", from->log_name, ni->hop_count); return -1; } + if (node_id == bgp->instance->node_id) return 0; struct NODEINFO_Q* nodeinfo1 = nodeinfo_find_by_id(bgp, node_id); uint8_t new_ver = ni->ver; - if (node_id == bgp->instance->node_id) return 0; - - if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver-new_ver)>=0) { + if (nodeinfo1 && (int8_t)(nodeinfo1->last_ver - new_ver) >= 0) { int new_hops = ni->hop_count + 1; if (new_hops <= MAX_HOPS) { uint64_t hop_list[MAX_HOPS]; - uint64_t* pkt_hops = (uint64_t*)((uint8_t*)ni + sizeof(struct NODEINFO) + dyn_size); - memcpy(hop_list, pkt_hops, ni->hop_count * 8); + const uint8_t* hop_src = (const uint8_t*)ni + sizeof(struct NODEINFO_MSG) + dyn - ni->hop_count * 8; + memcpy(hop_list, hop_src, ni->hop_count * 8); hop_list[ni->hop_count] = from->peer_node_id; - route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); + route_bgp_remove_path(nodeinfo1, from); route_bgp_add_path(nodeinfo1, from, hop_list, new_hops); } - DEBUG_TRACE(DEBUG_CATEGORY_BGP, "NODEINFO old ver: node=%016llx ver=%d<=%d from=%s (paths updated)", - (unsigned long long)node_id, new_ver, nodeinfo1->last_ver, from->log_name); return 0; } @@ -790,33 +452,44 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co (unsigned long long)node_id, new_ver, ni->local_v4_sockets, ni->local_v4_addrs, ni->local_v6_sockets, ni->local_v6_addrs, ni->hop_count, from->log_name); - int new_data_size=sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + dyn_size + 8; - struct ll_queue* paths=NULL; - int need_alloc=0; + struct ll_queue* paths = NULL; int is_new_node = 0; - int socks_changed = 0; if (nodeinfo1) { - paths=nodeinfo1->paths; - socks_changed = (nodeinfo1->node.local_v4_sockets != ni->local_v4_sockets) || - (nodeinfo1->node.local_v4_addrs != ni->local_v4_addrs) || - (nodeinfo1->node.local_v6_sockets != ni->local_v6_sockets) || - (nodeinfo1->node.local_v6_addrs != ni->local_v6_addrs); - if (nodeinfo1->ll.size < new_data_size) need_alloc=1; - } else { - need_alloc=1; - is_new_node = 1; + nodeinfo_free_lists(bgp, nodeinfo1); + paths = nodeinfo1->paths; nodeinfo1->paths = NULL; + } else { is_new_node = 1; } + + // deserialize from protocol + const uint8_t* ser_data = data + 2; + size_t ser_len = len - 2; + struct NODEINFO* new_ni = NULL; + struct NODEINFO_ROUTES* new_routes = NULL; + struct NODEINFO_TRANZIT_NODE* new_tranzit = NULL; uint8_t new_tranzit_count = 0; + uint64_t* new_hop_list = NULL; uint8_t new_hop_count = 0; + if (nodeinfo_deserialize(bgp, ser_data, ser_len, &new_ni, &new_routes, &new_tranzit, &new_tranzit_count, &new_hop_list, &new_hop_count) != 0) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO deserialize failed from %s", from->log_name); + if (nodeinfo1) { queue_remove_data(bgp->nodes, &nodeinfo1->ll); queue_free(paths); queue_entry_free(&nodeinfo1->ll); } + return -1; } - if (need_alloc) { - if (nodeinfo1) { - if (bgp->instance->rt) route_delete(bgp->instance->rt, nodeinfo1); - queue_remove_data(bgp->nodes, &nodeinfo1->ll); - queue_free(paths); - queue_entry_free(&nodeinfo1->ll); - } - nodeinfo1 = (struct NODEINFO_Q*)queue_entry_new(new_data_size); - paths = queue_new(bgp->instance->ua, 0, 0, 0, "node_paths"); - memcpy(&nodeinfo1->node, ni, sizeof(struct NODEINFO) + dyn_size); + if (nodeinfo1) { + nodeinfo1->node = new_ni; nodeinfo_ref(new_ni); + nodeinfo1->hash_node_id = new_ni->node_id; + nodeinfo1->routes = new_routes; + u_free(nodeinfo1->tranzit_data); nodeinfo1->tranzit_data = new_tranzit; + nodeinfo1->tranzit_count = new_tranzit_count; + u_free(nodeinfo1->hop_list); nodeinfo1->hop_list = new_hop_list; + nodeinfo1->hop_count = new_hop_count; + } else { + struct ll_entry* qe = queue_entry_new(sizeof(struct NODEINFO_Q)); + if (!qe) { nodeinfo_unref(new_ni); u_free(new_tranzit); u_free(new_hop_list); u_free(new_routes); return -1; } + nodeinfo1 = (struct NODEINFO_Q*)qe; + memset((uint8_t*)nodeinfo1 + sizeof(struct ll_entry), 0, sizeof(*nodeinfo1) - sizeof(struct ll_entry)); + nodeinfo1->node = new_ni; nodeinfo_ref(new_ni); + nodeinfo1->hash_node_id = new_ni->node_id; + nodeinfo1->routes = new_routes; + nodeinfo1->tranzit_data = new_tranzit; nodeinfo1->tranzit_count = new_tranzit_count; + nodeinfo1->hop_list = new_hop_list; nodeinfo1->hop_count = new_hop_count; nodeinfo1->connectivity.probe_status = PROBE_STATUS_NONE; nodeinfo1->connectivity.interface_status = PROBE_RESULT_UNKNOWN; nodeinfo1->connectivity.nat_status = PROBE_RESULT_UNKNOWN; @@ -824,64 +497,48 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co nodeinfo1->connectivity.ping_req_time = 0; nodeinfo1->alien = 0; queue_data_put_with_index(bgp->nodes, &nodeinfo1->ll); - } else { - socks_changed = (nodeinfo1->node.local_v4_sockets != ni->local_v4_sockets) || - (nodeinfo1->node.local_v4_addrs != ni->local_v4_addrs) || - (nodeinfo1->node.local_v6_sockets != ni->local_v6_sockets) || - (nodeinfo1->node.local_v6_addrs != ni->local_v6_addrs); - memcpy(&nodeinfo1->node, ni, sizeof(struct NODEINFO) + dyn_size); } - nodeinfo1->paths = paths; - nodeinfo1->last_ver = new_ver; + nodeinfo1->paths = paths; nodeinfo1->last_ver = new_ver; - // add last hop - uint64_t* hop_list = (uint64_t*)((uint8_t*)&nodeinfo1->node + sizeof(struct NODEINFO) + dyn_size); - uint64_t sender = from->peer_node_id; - memcpy(hop_list, &sender, 8); - nodeinfo1->node.hop_count++; + // add this hop + uint64_t hop_list[MAX_HOPS]; + if (nodeinfo1->hop_count > 0) memcpy(hop_list, nodeinfo1->hop_list, nodeinfo1->hop_count * 8); + hop_list[nodeinfo1->hop_count] = from->peer_node_id; + nodeinfo1->hop_count++; - // update node path - route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); - route_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->node.hop_count); - - if (bgp->instance->rt) { - route_insert(bgp->instance->rt, nodeinfo1); - } + u_free(nodeinfo1->hop_list); + nodeinfo1->hop_list = u_malloc(nodeinfo1->hop_count * 8); + memcpy(nodeinfo1->hop_list, hop_list, nodeinfo1->hop_count * 8); - if (node_id != bgp->instance->node_id) { - route_node_lmdb_put(bgp, nodeinfo1); - } + route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); + route_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->hop_count); + if (bgp->instance->rt) route_insert(bgp->instance->rt, nodeinfo1); + if (node_id != bgp->instance->node_id) route_node_lmdb_put(bgp, nodeinfo1); if (bgp->instance->control_srv) control_server_notify_node_change(bgp->instance->control_srv, nodeinfo1); - int hop_count=nodeinfo1->node.hop_count; - - // рассылаем по узлам которых нет в hop_list этой ноды (loop prevention) - struct ll_entry* e = bgp->senders_list ? bgp->senders_list->head : NULL; - while (e) { - struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)e->data; + int hop_count = nodeinfo1->hop_count; + struct ll_entry* se = bgp->senders_list ? bgp->senders_list->head : NULL; + while (se) { + struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data; if (item->conn) { - uint64_t id=item->conn->peer_node_id; + uint64_t id = item->conn->peer_node_id; if (id != node_id) { - int found=0; - for (int i=0; iconn); - else DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Skip send NODEINFO to node %016llx (loop prevention)",id); + int found = 0; for (int i = 0; i < hop_count; i++) if (hop_list[i] == id) found = 1; + if (found == 0) route_bgp_send_nodeinfo(nodeinfo1, item->conn); } } - e = e->next; + se = se->next; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Processed NODEINFO from %s (node=%016llx,ver=%d,paths=%d,addrs=%d)", - from->log_name, (unsigned long long)node_id, new_ver, - nodeinfo1->paths ? queue_entry_count(nodeinfo1->paths) : 0, - ni->local_v4_addrs); + int socks_changed = 1; + if (!is_new_node) socks_changed = 1; - // Запуск connectivity probing для нового или обновлённого узла - if (node_id != bgp->instance->node_id && (is_new_node || socks_changed) && - (nodeinfo1->node.local_v4_addrs > 0 || nodeinfo1->node.local_v6_addrs > 0)) { - route_connectivity_probe_node(bgp->instance, nodeinfo1); + if (node_id != bgp->instance->node_id && (is_new_node || socks_changed)) { + int v4a = ni_list_count((struct _ni_head*)nodeinfo1->node->v4_addrs); + int v6a = ni_list_count((struct _ni_head*)nodeinfo1->node->v6_addrs); + if (v4a > 0 || v6a > 0) route_connectivity_probe_node(bgp->instance, nodeinfo1); } return 0; @@ -889,102 +546,64 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co int route_bgp_process_withdraw(struct ROUTE_BGP* bgp, struct ETCP_CONN* sender, const uint8_t* data, size_t len) { if (!bgp || len < sizeof(struct BGP_WITHDRAW_PACKET)) return -1; - struct BGP_WITHDRAW_PACKET* wp = (struct BGP_WITHDRAW_PACKET*)data; - uint64_t node_id = wp->node_id; - uint64_t wd_source = wp->wd_source; + uint64_t node_id = wp->node_id, wd_source = wp->wd_source; struct NODEINFO_Q* nq = nodeinfo_find_by_id(bgp, node_id); - if (!nq) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found"); - return 0; - } - int ret=route_bgp_remove_path_by_hop(nq, wd_source); + if (!nq) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "node not found"); return 0; } + int ret = route_bgp_remove_path_by_hop(nq, wd_source); if (ret == 1) { if (bgp->instance && bgp->instance->rt) route_delete(bgp->instance->rt, nq); if (bgp->instance->control_srv) control_server_notify_node_removed(bgp->instance->control_srv, node_id); nq->dirty = 1; route_connectivity_cancel_node(bgp->instance, nq); if (nq->paths) { queue_free(nq->paths); nq->paths = NULL; } - uint64_t key = node_id; - struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &key); + nodeinfo_free_lists(bgp, nq); + struct ll_entry* entry = queue_find_data_by_index(bgp->nodes, &node_id); if (entry) { queue_remove_data(bgp->nodes, entry); queue_entry_free(entry); } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Removed node %016llx after WITHDRAW", (unsigned long long)node_id); route_bgp_broadcast_withdraw(bgp, node_id, wd_source, sender); } - return 0; } void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn) { - if (!node || !conn) { - return; - } - - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "Sending NODEINFO to %s", conn->log_name); - - int dyn = nodeinfo_dyn_size(&node->node); + if (!node || !conn) return; - size_t ps = sizeof(struct BGP_NODEINFO_PACKET) + dyn; + size_t max_sz = sizeof(struct BGP_NODEINFO_PACKET) + 4096; + uint8_t* p = u_malloc(max_sz); + if (!p) return; - uint8_t* p = u_malloc(ps); - if (!p) { - return; - } - - p[0] = ETCP_ID_ROUTE_ENTRY; - p[1] = ROUTE_SUBCMD_NODEINFO; - memcpy(p + 2, &node->node, sizeof(struct NODEINFO)); + p[0] = ETCP_ID_ROUTE_ENTRY; p[1] = ROUTE_SUBCMD_NODEINFO; - uint8_t* ds = (uint8_t*)&node->node + sizeof(struct NODEINFO); - memcpy(p + sizeof(struct BGP_NODEINFO_PACKET), ds, dyn); + int ser_len = nodeinfo_serialize(conn->instance->bgp, node, p + 2, max_sz - 2); + if (ser_len < 0) { u_free(p); return; } struct ll_entry* e = queue_entry_new(0); - if (!e) { - u_free(p); - return; - } + if (!e) { u_free(p); return; } + e->dgram = p; e->len = (size_t)ser_len + 2; - e->dgram = p; - e->len = ps; - - int ret = etcp_send(conn, e); - if (ret != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NODEINFO failed: %d", ret); - u_free(p); - queue_entry_free(e); - } + if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NODEINFO failed"); u_free(p); queue_entry_free(e); } } static void route_bgp_add_to_senders(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) { if (!bgp || !conn || !bgp->senders_list) return; bool already = false; struct ll_entry* e = bgp->senders_list->head; - while (e) { - if (((struct ROUTE_BGP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } - e = e->next; - } + while (e) { if (((struct ROUTE_BGP_CONN_ITEM*)e->data)->conn == conn) { already = true; break; } e = e->next; } if (!already) { struct ll_entry* item_entry = queue_entry_new(sizeof(struct ROUTE_BGP_CONN_ITEM)); - if (item_entry) { - ((struct ROUTE_BGP_CONN_ITEM*)item_entry->data)->conn = conn; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Added to senders_list: %s", conn->log_name); - queue_data_put(bgp->senders_list, item_entry); - } + if (item_entry) { ((struct ROUTE_BGP_CONN_ITEM*)item_entry->data)->conn = conn; queue_data_put(bgp->senders_list, item_entry); } } } static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t target_id) { - if (!nq || !nq->paths) return false; - if (target_id == nq->node.node_id) return false; + if (!nq || !nq->node || !nq->paths) return false; + if (target_id == nq->node->node_id) return false; struct ll_entry* e = nq->paths->head; while (e) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)e; uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); - bool has_id = false; - for (uint8_t i = 0; i < path->hop_count; i++) { - if (hop[i] == target_id) { has_id = true; break; } - } + bool has_id = false; for (uint8_t i = 0; i < path->hop_count; i++) if (hop[i] == target_id) { has_id = true; break; } if (!has_id) return true; e = e->next; } @@ -997,24 +616,15 @@ static void route_bgp_send_full_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* c struct ll_entry* e = bgp->nodes ? bgp->nodes->head : NULL; while (e) { struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e; - if (nq->node.hop_count == 0) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "local node in learned list"); - e = e->next; continue; - } - if (!nq->paths) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "node has no paths"); - e = e->next; continue; - } - if (route_bgp_should_send_to(nq, target)) { - route_bgp_send_nodeinfo(nq, conn); - } + if (nq->hop_count == 0) { e = e->next; continue; } + if (!nq->paths) { DEBUG_WARN(DEBUG_CATEGORY_BGP, "node has no paths"); e = e->next; continue; } + if (route_bgp_should_send_to(nq, target)) route_bgp_send_nodeinfo(nq, conn); e = e->next; } } static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn) { if (!bgp || !conn) return; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "Received table request from %s", conn->log_name); route_bgp_send_nodeinfo(bgp->local_node, conn); route_bgp_send_full_table(bgp, conn); route_bgp_add_to_senders(bgp, conn); @@ -1022,18 +632,12 @@ static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CO } static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { - if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_INFO) || !bgp->local_node) return; + if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_INFO) || !bgp->local_node || !bgp->local_node->node) return; const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data; - uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) | - (info->nat_ip[2] << 8) | info->nat_ip[3]; - uint16_t nat_port = ntohs(info->nat_port); - uint8_t socket_id = info->socket_id; - - // Обновить тип в socket meta - uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO); - dynamic += bgp->local_node->node.node_name_len; - struct NODEINFO_IPV4_SOCKET_META* meta = (struct NODEINFO_IPV4_SOCKET_META*)dynamic; + uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) | (info->nat_ip[2] << 8) | info->nat_ip[3]; + uint16_t nat_port = ntohs(info->nat_port); uint8_t socket_id = info->socket_id; + uint8_t verified_type; if (info->nat_type == NAT_TYPE_EIM) verified_type = NAT_VERIFIED_EIM; else if (info->nat_type == NAT_TYPE_STRICT) verified_type = NAT_VERIFIED_STRICT; @@ -1041,197 +645,67 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f else verified_type = NAT_VERIFIED_UNKNOWN; int data_changed = 0; - for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) { - if (meta[i].id == socket_id) { - if (meta[i].nat_type != verified_type) { - meta[i].nat_type = verified_type; - data_changed = 1; - } - break; - } - } + { struct NI_IPV4_SOCKET_META* sm = bgp->local_node->node->v4_sock_meta; while (sm) { if (sm->id == socket_id) { if (sm->nat_type != verified_type) { sm->nat_type = verified_type; data_changed = 1; } break; } sm = sm->next; } } - // Обновить ETCP_SOCKET struct ETCP_SOCKET* es = bgp->instance->etcp_sockets; - while (es) { - if (es->sock_id == socket_id) { - if (verified_type == NAT_VERIFIED_STRICT) { - struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; - nat_sin->sin_family = AF_INET; - nat_sin->sin_addr.s_addr = nat_ip; - nat_sin->sin_port = htons(nat_port); - es->nat_type = verified_type; - } else { - struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; - uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; - uint16_t old_nat_port = ntohs(nat_sin->sin_port); - nat_sin->sin_family = AF_INET; - nat_sin->sin_addr.s_addr = nat_ip; - nat_sin->sin_port = htons(nat_port); - if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; - es->nat_type = verified_type; - } - break; - } - es = es->next; - } + while (es) { if (es->sock_id == socket_id) { + if (verified_type == NAT_VERIFIED_STRICT) { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); es->nat_type = verified_type; } + else { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; uint16_t old_nat_port = ntohs(nat_sin->sin_port); nat_sin->sin_family = AF_INET; nat_sin->sin_addr.s_addr = nat_ip; nat_sin->sin_port = htons(nat_port); if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; es->nat_type = verified_type; } break; } + es = es->next; } - // Обновить local_node и разослать если изменилось if (data_changed) { - int prev_v4_addrs = bgp->local_node->node.local_v4_addrs; + int prev_v4a = ni_list_count((struct _ni_head*)bgp->local_node->node->v4_addrs); route_bgp_update_my_nodeinfo(bgp->instance, bgp); - if (bgp->local_node->node.local_v4_addrs != prev_v4_addrs) { + if (ni_list_count((struct _ni_head*)bgp->local_node->node->v4_addrs) != prev_v4a) { bgp->local_node->dirty = 1; - bgp->local_node->node.ver = (bgp->local_node->node.ver % 255) + 1; - bgp->local_node->last_ver = bgp->local_node->node.ver; + bgp->local_node->node->ver = (bgp->local_node->node->ver % 255) + 1; + bgp->local_node->last_ver = bgp->local_node->node->ver; } if (bgp->local_node->dirty && bgp->senders_list) { struct ll_entry* se = bgp->senders_list->head; - while (se) { - struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data; - if (item && item->conn) route_bgp_send_nodeinfo(bgp->local_node, item->conn); - se = se->next; - } + while (se) { struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data; if (item && item->conn) route_bgp_send_nodeinfo(bgp->local_node, item->conn); se = se->next; } } } - // NAT type for the link - struct ETCP_LINK* l = from_conn->links; - while (l) { l->nat_type = info->nat_type; l = l->next; } - - DEBUG_INFO(DEBUG_CATEGORY_NAT, "NAT_INFO from %s: sock_id=%u type=%s ip=%s port=%u matched_sock=%s old_nat_type=%d", - from_conn->log_name, socket_id, - info->nat_type == NAT_TYPE_EIM ? "EIM" : info->nat_type == NAT_TYPE_DIRECT ? "DIRECT" : "STRICT", - ip_to_str(info->nat_ip, AF_INET).str, (unsigned)nat_port, - es ? es->name : "none", es ? (int)es->nat_type : -1); + struct ETCP_LINK* l = from_conn->links; while (l) { l->nat_type = info->nat_type; l = l->next; } } -static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {// поиск нужного линка и запуск nat_check +static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { if (!bgp || !from_conn || !data || len < sizeof(struct BGP_NAT_CHECK_REQ)) return; - const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data; uint8_t socket_id = req->socket_id; - struct sockaddr_storage dummy; - memset(&dummy, 0, sizeof(dummy)); - if (req->interface_ip != 0) { - struct sockaddr_in* sin = (struct sockaddr_in*)&dummy; - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = req->interface_ip; - sin->sin_port = req->interface_port; - } - struct ETCP_LINK* target_link = NULL; - struct ETCP_LINK* l = from_conn->links; - while (l) { - if (l->remote_socket_id == socket_id) { - target_link = l; - break; - } - l = l->next; - } - - if (!target_link) { - struct sockaddr_in* sin = (struct sockaddr_in*)&dummy; - DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u interface=%s:%u", - from_conn->log_name, socket_id, - sin->sin_addr.s_addr ? ip_to_str(&sin->sin_addr, AF_INET).str : "none", - (unsigned)ntohs(sin->sin_port)); - } else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) { - DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u", - from_conn->log_name, socket_id); - } else { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u", - from_conn->log_name, socket_id); - route_bgp_start_link_nat_check(bgp, target_link); - } + struct ETCP_LINK* l = from_conn->links; while (l) { if (l->remote_socket_id == socket_id) { target_link = l; break; } l = l->next; } + if (!target_link) return; + if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; + route_bgp_start_link_nat_check(bgp, target_link); } void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) { if (!conn) return; - struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); - if (!pkt) return; - pkt->cmd = ETCP_ID_ROUTE_ENTRY; - pkt->subcmd = ROUTE_SUBCMD_NAT_INFO; + struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); if (!pkt) return; + pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_NAT_INFO; pkt->socket_id = socket_id; - /* IP уже в network byte order */ - pkt->nat_ip[0] = (nat_ip >> 24) & 0xFF; - pkt->nat_ip[1] = (nat_ip >> 16) & 0xFF; - pkt->nat_ip[2] = (nat_ip >> 8) & 0xFF; - pkt->nat_ip[3] = nat_ip & 0xFF; - pkt->nat_port = htons(nat_port); - pkt->nat_type = nat_type; - - struct ll_entry* e = queue_entry_new(0); - if (!e) { - u_free(pkt); - return; - } - e->dgram = (uint8_t*)pkt; - e->len = sizeof(struct BGP_NAT_INFO); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_send_nat_info to %s: socket_id=%u type=%s ip=%s port=%u", - conn->log_name, socket_id, - nat_type == NAT_TYPE_EIM ? "EIM" : "STRICT", - ip_to_str(pkt->nat_ip, AF_INET).str, (unsigned)nat_port); - int ret = etcp_send(conn, e); - if (ret != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_INFO failed: %d", ret); - u_free(pkt); - queue_entry_free(e); - } + pkt->nat_ip[0] = (nat_ip >> 24) & 0xFF; pkt->nat_ip[1] = (nat_ip >> 16) & 0xFF; + pkt->nat_ip[2] = (nat_ip >> 8) & 0xFF; pkt->nat_ip[3] = nat_ip & 0xFF; + pkt->nat_port = htons(nat_port); pkt->nat_type = nat_type; + struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(pkt); return; } + e->dgram = (uint8_t*)pkt; e->len = sizeof(struct BGP_NAT_INFO); + if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_INFO failed"); u_free(pkt); queue_entry_free(e); } } void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) { if (!conn) return; - struct BGP_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct BGP_NAT_CHECK_REQ)); - if (!pkt) return; - pkt->cmd = ETCP_ID_ROUTE_ENTRY; - pkt->subcmd = ROUTE_SUBCMD_NAT_CHECK_REQ; - pkt->socket_id = socket_id; - - struct ETCP_LINK* l = conn->links; - while (l) { - if (l->remote_socket_id == socket_id) { - struct sockaddr_in* sin = (struct sockaddr_in*)&l->conn->interface_addr; - if (sin->sin_family == AF_INET) { - pkt->interface_ip = sin->sin_addr.s_addr; - pkt->interface_port = sin->sin_port; - } - break; - } - l = l->next; - } - - struct ll_entry* e = queue_entry_new(0); - if (!e) { - u_free(pkt); - return; - } - e->dgram = (uint8_t*)pkt; - e->len = sizeof(struct BGP_NAT_CHECK_REQ); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_send_nat_check_req to %s: socket_id=%u interface=%s:%u", - conn->log_name, socket_id, - ip_to_str(&pkt->interface_ip, AF_INET).str, - (unsigned)ntohs(pkt->interface_port)); - int ret = etcp_send(conn, e); - if (ret != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_CHECK_REQ failed: %d", ret); - u_free(pkt); - queue_entry_free(e); - } + struct BGP_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct BGP_NAT_CHECK_REQ)); if (!pkt) return; + pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_NAT_CHECK_REQ; pkt->socket_id = socket_id; + struct ETCP_LINK* l = conn->links; while (l) { if (l->remote_socket_id == socket_id) { struct sockaddr_in* sin = (struct sockaddr_in*)&l->conn->interface_addr; if (sin->sin_family == AF_INET) { pkt->interface_ip = sin->sin_addr.s_addr; pkt->interface_port = sin->sin_port; } break; } l = l->next; } + struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(pkt); return; } + e->dgram = (uint8_t*)pkt; e->len = sizeof(struct BGP_NAT_CHECK_REQ); + if (etcp_send(conn, e) != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send NAT_CHECK_REQ failed"); u_free(pkt); queue_entry_free(e); } } void route_bgp_request_nat_check_all(struct ROUTE_BGP* bgp) { if (!bgp || !bgp->instance) return; int count = 0; - struct ETCP_CONN* conn = bgp->instance->connections; - while (conn) { - struct ETCP_LINK* link = conn->links; - while (link) { - if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) route_bgp_start_link_nat_check(bgp, link); - count++; - link = link->next; - } - conn = conn->next; - } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check requested for all links, count=%d", count); + struct ETCP_CONN* conn = bgp->instance->connections; while (conn) { struct ETCP_LINK* link = conn->links; while (link) { if (link->nat_check_status < NAT_CHECK_IN_PROGRESS) route_bgp_start_link_nat_check(bgp, link); count++; link = link->next; } conn = conn->next; } } diff --git a/src/route_bgp.h b/src/route_bgp.h index e6d9e593..b1e1d3f3 100644 --- a/src/route_bgp.h +++ b/src/route_bgp.h @@ -9,6 +9,7 @@ extern "C" { #include #include #include "../lib/ll_queue.h" +#include "../lib/memory_pool.h" #include "../lib/liblmdb/lmdb.h" #include "route_lib.h" #include "route_node.h" @@ -35,7 +36,7 @@ extern "C" { struct BGP_NODEINFO_PACKET { uint8_t cmd; // ETCP_ID_ROUTE_ENTRY uint8_t subcmd; // ROUTE_SUBCMD_NODEINFO - struct NODEINFO node; + struct NODEINFO_MSG node; } __attribute__((packed)); /** @@ -94,10 +95,16 @@ struct ROUTE_BGP { struct NODEINFO_Q* local_node; struct route_ping_pending* ping_pending; uint32_t next_ping_req_id; - uint8_t allow_nat_check_local; // 1 = разрешить NAT check для локальных подсетей (для тестов) - uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; // свой Ed25519 pubkey (для подписи сообщений) - MDB_env* nodeinfo_env; // LMDB environment handle - MDB_dbi nodeinfo_dbi; // LMDB database handle for nodeinfo table + uint8_t allow_nat_check_local; + uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; + MDB_env* nodeinfo_env; + MDB_dbi nodeinfo_dbi; + struct memory_pool* v4_sock_meta_pool; + struct memory_pool* v4_addr_pool; + struct memory_pool* v6_sock_meta_pool; + struct memory_pool* v6_addr_pool; + struct memory_pool* v4_subnet_pool; + struct memory_pool* v6_subnet_pool; }; /** @@ -161,8 +168,6 @@ void route_bgp_send_nodeinfo(struct NODEINFO_Q* node, struct ETCP_CONN* conn); */ void route_bgp_send_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id); -int nodeinfo_dyn_size(struct NODEINFO* node); - /** * @brief Поиск оптимального ETCP соединения для указанного node_id. * diff --git a/src/route_connectivity.c b/src/route_connectivity.c index 296c18e2..0405b6bc 100644 --- a/src/route_connectivity.c +++ b/src/route_connectivity.c @@ -277,7 +277,7 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) { if (c->pending_count == 0) { c->probe_status = PROBE_STATUS_DONE; DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe DONE for node %016llx: intf=%d nat=%d real=%d", - (unsigned long long)ctx->nq->node.node_id, + (unsigned long long)ctx->nq->node->node_id, c->interface_status, c->nat_status, c->real_status); } } @@ -289,9 +289,9 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) { void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEINFO_Q* nq) { if (!instance || !nq) return; - if (nq->node.node_id == instance->node_id) return; // не пингуем себя + if (nq->node->node_id == instance->node_id) return; // не пингуем себя if (nq->connectivity.probe_status == PROBE_STATUS_IN_PROGRESS) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe already in progress for node %016llx", (unsigned long long)nq->node.node_id); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe already in progress for node %016llx", (unsigned long long)nq->node->node_id); return; } @@ -308,131 +308,71 @@ void route_connectivity_probe_node(struct UTUN_INSTANCE* instance, struct NODEIN int pend = 0; // ---- IPv4 addresses ---- - const struct NODEINFO_IPV4_ADDR* addrs; - int addr_count = get_node_v4_addrs(nq, &addrs); - if (addr_count > 0) { - uint32_t seen_ips[16]; uint16_t seen_ports[16]; - int seen_count = 0; - - for (int i = 0; i < addr_count; i++) { - uint32_t ip; memcpy(&ip, addrs[i].addr, 4); - uint16_t port = addrs[i].port; + if (nq->node && nq->node->v4_addrs) { + uint32_t seen_ips[16]; uint16_t seen_ports[16]; int seen_count = 0; + for (const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; a; a = a->next) { + uint32_t ip; memcpy(&ip, a->addr, 4); uint16_t port = a->port; if (ip == 0 || port == 0) continue; - - int dup = 0; - for (int j = 0; j < seen_count; j++) { - if (seen_ips[j] == ip && seen_ports[j] == port) { dup = 1; break; } - } + int dup = 0; for (int j = 0; j < seen_count; j++) { if (seen_ips[j] == ip && seen_ports[j] == port) { dup = 1; break; } } if (dup) continue; if (seen_count >= 16) break; seen_ips[seen_count] = ip; seen_ports[seen_count] = port; seen_count++; - struct sockaddr_storage target; - memset(&target, 0, sizeof(target)); - struct sockaddr_in* sin = (struct sockaddr_in*)⌖ - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = ip; - sin->sin_port = htons(port); + struct sockaddr_storage target; memset(&target, 0, sizeof(target)); + struct sockaddr_in* sin = (struct sockaddr_in*)⌖ sin->sin_family = AF_INET; sin->sin_addr.s_addr = ip; sin->sin_port = htons(port); struct ETCP_SOCKET* candidates[CONN_MAX_SOCKET_CANDIDATES]; - int cand_count = conn_match_candidate_sockets(instance, addrs[i].type, &target, - candidates, CONN_MAX_SOCKET_CANDIDATES); - if (cand_count == 0) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe: no local sockets for target %s:%u type=%d", - ip_to_str(&ip, AF_INET).str, port, addrs[i].type); - continue; - } + int cand_count = conn_match_candidate_sockets(instance, a->type, &target, candidates, CONN_MAX_SOCKET_CANDIDATES); + if (cand_count == 0) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe: no local sockets for target %s:%u type=%d", ip_to_str(&ip, AF_INET).str, port, a->type); continue; } - struct conn_probe_ctx* ctx = u_calloc(1, sizeof(struct conn_probe_ctx)); - if (!ctx) continue; - ctx->instance = instance; - ctx->nq = nq; - ctx->addr_type = addrs[i].type; - ctx->target_addr = target; - memcpy(ctx->peer_pubkey, nq->node.public_key, SC_PUBKEY_SIZE); + struct conn_probe_ctx* ctx = u_calloc(1, sizeof(struct conn_probe_ctx)); if (!ctx) continue; + ctx->instance = instance; ctx->nq = nq; ctx->addr_type = a->type; ctx->target_addr = target; + memcpy(ctx->peer_pubkey, nq->node->public_key, SC_PUBKEY_SIZE); memcpy(ctx->candidate_sockets, candidates, cand_count * sizeof(struct ETCP_SOCKET*)); - ctx->candidate_count = cand_count; - ctx->candidate_index = 0; - ctx->count_total = CONN_PROBE_COUNT; - ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; - ctx->best_across_sockets = 65535; - - ctx->next = (struct conn_probe_ctx*)nq->connectivity.probe_list; - nq->connectivity.probe_list = ctx; - pend++; + ctx->candidate_count = cand_count; ctx->candidate_index = 0; ctx->count_total = CONN_PROBE_COUNT; ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; ctx->best_across_sockets = 65535; + ctx->next = (struct conn_probe_ctx*)nq->connectivity.probe_list; nq->connectivity.probe_list = ctx; pend++; conn_probe_start_series(ctx); } } // ---- IPv6 addresses ---- - const struct NODEINFO_IPV6_ADDR* addrs6; - int addr6_count = get_node_v6_addrs(nq, &addrs6); - if (addr6_count > 0) { - uint8_t seen_ip6s[16][16]; uint16_t seen_ports6[16]; - int seen6_count = 0; - - for (int i = 0; i < addr6_count; i++) { - if (addrs6[i].port == 0) continue; - // skip zero address - int zero = 1; - for (int z = 0; z < 16; z++) if (addrs6[i].addr[z] != 0) { zero = 0; break; } - if (zero) continue; - - int dup = 0; - for (int j = 0; j < seen6_count; j++) { - if (memcmp(seen_ip6s[j], addrs6[i].addr, 16) == 0 && seen_ports6[j] == addrs6[i].port) { dup = 1; break; } - } + if (nq->node && nq->node->v6_addrs) { + uint8_t seen_ip6s[16][16]; uint16_t seen_ports6[16]; int seen6_count = 0; + for (const struct NI_IPV6_ADDR* a6 = nq->node->v6_addrs; a6; a6 = a6->next) { + if (a6->port == 0) continue; + int zero = 1; for (int z = 0; z < 16; z++) if (a6->addr[z] != 0) { zero = 0; break; } if (zero) continue; + int dup = 0; for (int j = 0; j < seen6_count; j++) { if (memcmp(seen_ip6s[j], a6->addr, 16) == 0 && seen_ports6[j] == a6->port) { dup = 1; break; } } if (dup) continue; if (seen6_count >= 16) break; - memcpy(seen_ip6s[seen6_count], addrs6[i].addr, 16); - seen_ports6[seen6_count] = addrs6[i].port; - seen6_count++; + memcpy(seen_ip6s[seen6_count], a6->addr, 16); seen_ports6[seen6_count] = a6->port; seen6_count++; - struct sockaddr_storage target; - memset(&target, 0, sizeof(target)); - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)⌖ - sin6->sin6_family = AF_INET6; - memcpy(&sin6->sin6_addr, addrs6[i].addr, 16); - sin6->sin6_port = htons(addrs6[i].port); + struct sockaddr_storage target; memset(&target, 0, sizeof(target)); + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)⌖ sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, a6->addr, 16); sin6->sin6_port = htons(a6->port); struct ETCP_SOCKET* candidates[CONN_MAX_SOCKET_CANDIDATES]; - int cand_count = conn_match_candidate_sockets(instance, addrs6[i].type, &target, - candidates, CONN_MAX_SOCKET_CANDIDATES); - if (cand_count == 0) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe: no local sockets for IPv6 target type=%d", addrs6[i].type); - continue; - } + int cand_count = conn_match_candidate_sockets(instance, a6->type, &target, candidates, CONN_MAX_SOCKET_CANDIDATES); + if (cand_count == 0) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "probe: no local sockets for IPv6 target type=%d", a6->type); continue; } - struct conn_probe_ctx* ctx = u_calloc(1, sizeof(struct conn_probe_ctx)); - if (!ctx) continue; - ctx->instance = instance; - ctx->nq = nq; - ctx->addr_type = addrs6[i].type; - ctx->target_addr = target; - memcpy(ctx->peer_pubkey, nq->node.public_key, SC_PUBKEY_SIZE); + struct conn_probe_ctx* ctx = u_calloc(1, sizeof(struct conn_probe_ctx)); if (!ctx) continue; + ctx->instance = instance; ctx->nq = nq; ctx->addr_type = a6->type; ctx->target_addr = target; + memcpy(ctx->peer_pubkey, nq->node->public_key, SC_PUBKEY_SIZE); memcpy(ctx->candidate_sockets, candidates, cand_count * sizeof(struct ETCP_SOCKET*)); - ctx->candidate_count = cand_count; - ctx->candidate_index = 0; - ctx->count_total = CONN_PROBE_COUNT; - ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; - ctx->best_across_sockets = 65535; - - ctx->next = (struct conn_probe_ctx*)nq->connectivity.probe_list; - nq->connectivity.probe_list = ctx; - pend++; + ctx->candidate_count = cand_count; ctx->candidate_index = 0; ctx->count_total = CONN_PROBE_COUNT; ctx->timeout_ms = CONN_PROBE_TIMEOUT_MS; ctx->best_across_sockets = 65535; + ctx->next = (struct conn_probe_ctx*)nq->connectivity.probe_list; nq->connectivity.probe_list = ctx; pend++; conn_probe_start_series(ctx); } } if (pend == 0) { nq->connectivity.probe_status = PROBE_STATUS_DONE; - if (addr_count == 0 && addr6_count == 0) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, "no addresses to probe for node %016llx", (unsigned long long)nq->node.node_id); + if (!nq->node->v4_addrs && !nq->node->v6_addrs) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, "no addresses to probe for node %016llx", (unsigned long long)nq->node->node_id); } } else { nq->connectivity.pending_count = pend; DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe started for node %016llx: %d series pending", - (unsigned long long)nq->node.node_id, pend); + (unsigned long long)nq->node->node_id, pend); } } @@ -443,7 +383,7 @@ void route_connectivity_cancel_node(struct UTUN_INSTANCE* instance, struct NODEI struct conn_probe_ctx* ctx = (struct conn_probe_ctx*)nq->connectivity.probe_list; while (ctx) { ctx->nq = NULL; ctx = ctx->next; } nq->connectivity.probe_list = NULL; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe cancelled for node %016llx", (unsigned long long)nq->node.node_id); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "connectivity probe cancelled for node %016llx", (unsigned long long)nq->node->node_id); } void route_connectivity_cancel_all(struct UTUN_INSTANCE* instance) { diff --git a/src/route_lib.c b/src/route_lib.c index 941442dc..732c9ead 100644 --- a/src/route_lib.c +++ b/src/route_lib.c @@ -146,103 +146,62 @@ void route_table_destroy(struct ROUTE_TABLE *table) { } bool route_insert(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) { - if (!table || !node) { - DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: invalid arguments"); - return false; - } - - // === Вызов сторонней функции (теперь без malloc) === - const struct NODEINFO_IPV4_SUBNET *subnets = NULL; - int cnt = get_node_routes(node, &subnets); + if (!table || !node) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: invalid arguments"); return false; } - if (cnt <= 0) { - DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: get_node_routes returned %d subnets", cnt); + if (!node->routes || !node->routes->v4_subnets) { + DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: node has no v4 subnets"); return false; } - + const struct NI_IPV4_SUBNET* sub = node->routes->v4_subnets; + int cnt = 0; for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) cnt++; + if (cnt == 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: 0 subnets"); return false; } size_t count = (size_t)cnt; - // === Проверка пересечений === - for (size_t i = 0; i < count; i++) { - uint32_t network; - memcpy(&network, subnets[i].addr, 4); - network = ntohl(network); - uint8_t prefix = subnets[i].prefix_length; - - if (check_route_overlap_in_table(network, prefix, - table->entries, table->count)) { - DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: overlap detected for %s/%d", - ip_to_string(network).a, prefix); + for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) { + uint32_t network; memcpy(&network, s->addr, 4); network = ntohl(network); + if (check_route_overlap_in_table(network, s->prefix_length, table->entries, table->count)) { + DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_insert: overlap detected for %s/%d", ip_to_string(network).a, s->prefix_length); return false; } } - // === Реаллокация при необходимости === if (table->count + count > table->capacity) { size_t new_cap = table->capacity * 2; while (new_cap < table->count + count) new_cap *= 2; - struct ROUTE_ENTRY *new_entries = u_realloc(table->entries, new_cap * sizeof(struct ROUTE_ENTRY)); - if (!new_entries) { - DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: realloc failed"); - return false; - } - table->entries = new_entries; - table->capacity = new_cap; + struct ROUTE_ENTRY* new_entries = u_realloc(table->entries, new_cap * sizeof(struct ROUTE_ENTRY)); + if (!new_entries) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_insert: realloc failed"); return false; } + table->entries = new_entries; table->capacity = new_cap; } - // === Вставка каждого префикса (таблица остаётся отсортированной) === - for (size_t i = 0; i < count; i++) { - uint32_t network; - memcpy(&network, subnets[i].addr, 4); - network = ntohl(network); - uint8_t prefix_length = subnets[i].prefix_length; - - int pos = binary_search_insert_pos(table->entries, table->count, network, prefix_length); - - if (pos < (int)table->count) { - memmove(&table->entries[pos + 1], &table->entries[pos], - (table->count - pos) * sizeof(struct ROUTE_ENTRY)); - } - - struct ROUTE_ENTRY *e = &table->entries[pos]; - e->network = network; - e->prefix_length = prefix_length; - e->v_node_info = node; - + for (const struct NI_IPV4_SUBNET* s = sub; s; s = s->next) { + uint32_t network; memcpy(&network, s->addr, 4); network = ntohl(network); + int pos = binary_search_insert_pos(table->entries, table->count, network, s->prefix_length); + if (pos < (int)table->count) memmove(&table->entries[pos + 1], &table->entries[pos], (table->count - pos) * sizeof(struct ROUTE_ENTRY)); + struct ROUTE_ENTRY* e = &table->entries[pos]; + e->network = network; e->prefix_length = s->prefix_length; e->v_node_info = node; table->count++; - if (node && node->node.hop_count == 0) table->stats.local_routes++; else table->stats.learned_routes++; + if (node->hop_count == 0) table->stats.local_routes++; else table->stats.learned_routes++; } DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_insert: added %zu route(s) for node=%016llx", - count, node ? (unsigned long long)node->node.node_id : 0ULL); + count, (unsigned long long)node->node->node_id); return true; } void route_delete(struct ROUTE_TABLE *table, struct NODEINFO_Q *node) { if (!table || !node) return; - - DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removing all routes for node=%016llx", - (unsigned long long)node->node.node_id); - - size_t i = 0; - size_t removed = 0; + DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removing all routes for node=%016llx", (unsigned long long)node->node->node_id); + size_t i = 0, removed = 0; while (i < table->count) { if (table->entries[i].v_node_info == node) { - if (i < table->count - 1) { - memmove(&table->entries[i], &table->entries[i + 1], - (table->count - i - 1) * sizeof(struct ROUTE_ENTRY)); - } + if (i < table->count - 1) memmove(&table->entries[i], &table->entries[i + 1], (table->count - i - 1) * sizeof(struct ROUTE_ENTRY)); table->count--; - if (node && node->node.hop_count == 0) table->stats.local_routes--; else table->stats.learned_routes--; - removed++; - continue; + if (node->hop_count == 0) table->stats.local_routes--; else table->stats.learned_routes--; + removed++; continue; } i++; } - - if (removed > 0) { - DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removed %zu route(s)", removed); - } + if (removed > 0) DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_delete: removed %zu route(s)", removed); } struct ROUTE_ENTRY* route_lookup(struct ROUTE_TABLE *table, uint32_t dest_ip) { @@ -277,7 +236,7 @@ void route_table_print(const struct ROUTE_TABLE *table) { const struct ROUTE_ENTRY *entry = &table->entries[i]; DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " %zu: %s/%d", i + 1, ip_to_string(entry->network).a, entry->prefix_length); - if (entry->v_node_info && entry->v_node_info->node.hop_count != 0) { + if (entry->v_node_info && entry->v_node_info->hop_count != 0) { DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " v_node_info=%p", (void*)entry->v_node_info); } else { DEBUG_INFO(DEBUG_CATEGORY_ROUTING, " LOCAL"); diff --git a/src/route_node.c b/src/route_node.c index 9149659e..4c6959e4 100644 --- a/src/route_node.c +++ b/src/route_node.c @@ -5,6 +5,7 @@ #include "../lib/ll_queue.h" #include "../lib/debug_config.h" #include "../lib/mem.h" +#include "../lib/memory_pool.h" #include "utun_instance.h" #include "etcp.h" #include "config_parser.h" @@ -13,113 +14,245 @@ #include "route_lib.h" #include "etcp_debug.h" -static const uint8_t* node_dyn_start(const struct NODEINFO* info) { - return (const uint8_t*)info + sizeof(struct NODEINFO); +void nodeinfo_ref(struct NODEINFO* ni) { + if (!ni) return; + ni->ref_count++; } -static const uint8_t* skip_name(const uint8_t* p, uint8_t name_len) { - return p + name_len; +void nodeinfo_unref(struct NODEINFO* ni) { + if (!ni) return; + if (--ni->ref_count == 0) { + u_free(ni->node_name); + u_free(ni); + } } -static const uint8_t* skip_v4_sockets_meta(const uint8_t* p, uint8_t count) { - return p + count * sizeof(struct NODEINFO_IPV4_SOCKET_META); +static void free_v4_sock_list(struct memory_pool* pool, struct NI_IPV4_SOCKET_META* head) { + while (head) { struct NI_IPV4_SOCKET_META* next = head->next; memory_pool_free(pool, head); head = next; } } - -static const uint8_t* skip_v4_addrs(const uint8_t* p, uint8_t count) { - return p + count * sizeof(struct NODEINFO_IPV4_ADDR); +static void free_v4_addr_list(struct memory_pool* pool, struct NI_IPV4_ADDR* head) { + while (head) { struct NI_IPV4_ADDR* next = head->next; memory_pool_free(pool, head); head = next; } } - -static const uint8_t* skip_v6_sockets_meta(const uint8_t* p, uint8_t count) { - return p + count * sizeof(struct NODEINFO_IPV6_SOCKET_META); +static void free_v6_sock_list(struct memory_pool* pool, struct NI_IPV6_SOCKET_META* head) { + while (head) { struct NI_IPV6_SOCKET_META* next = head->next; memory_pool_free(pool, head); head = next; } } - -static const uint8_t* skip_v6_addrs(const uint8_t* p, uint8_t count) { - return p + count * sizeof(struct NODEINFO_IPV6_ADDR); +static void free_v6_addr_list(struct memory_pool* pool, struct NI_IPV6_ADDR* head) { + while (head) { struct NI_IPV6_ADDR* next = head->next; memory_pool_free(pool, head); head = next; } } - -static const uint8_t* skip_v4_subnets(const uint8_t* p, uint8_t count) { - return p + count * sizeof(struct NODEINFO_IPV4_SUBNET); +static void free_v4_sub_list(struct memory_pool* pool, struct NI_IPV4_SUBNET* head) { + while (head) { struct NI_IPV4_SUBNET* next = head->next; memory_pool_free(pool, head); head = next; } } - -int get_node_v4_sockets_meta(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SOCKET_META **out_meta) { - if (!node || !out_meta) return -1; - *out_meta = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v4_sockets == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - *out_meta = (const struct NODEINFO_IPV4_SOCKET_META *)dynamic; - return (int)info->local_v4_sockets; +static void free_v6_sub_list(struct memory_pool* pool, struct NI_IPV6_SUBNET* head) { + while (head) { struct NI_IPV6_SUBNET* next = head->next; memory_pool_free(pool, head); head = next; } } -int get_node_v4_addrs(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_ADDR **out_addrs) { - if (!node || !out_addrs) return -1; - *out_addrs = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v4_addrs == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - dynamic = skip_v4_sockets_meta(dynamic, info->local_v4_sockets); - *out_addrs = (const struct NODEINFO_IPV4_ADDR *)dynamic; - return (int)info->local_v4_addrs; +void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) { + if (!bgp || !nq) return; + if (nq->node) { + free_v4_sock_list(bgp->v4_sock_meta_pool, nq->node->v4_sock_meta); + free_v4_addr_list(bgp->v4_addr_pool, nq->node->v4_addrs); + free_v6_sock_list(bgp->v6_sock_meta_pool, nq->node->v6_sock_meta); + free_v6_addr_list(bgp->v6_addr_pool, nq->node->v6_addrs); + nq->node->v4_sock_meta = NULL; nq->node->v4_addrs = NULL; + nq->node->v6_sock_meta = NULL; nq->node->v6_addrs = NULL; + nodeinfo_unref(nq->node); + nq->node = NULL; + } + if (nq->routes) { + free_v4_sub_list(bgp->v4_subnet_pool, nq->routes->v4_subnets); + free_v6_sub_list(bgp->v6_subnet_pool, nq->routes->v6_subnets); + u_free(nq->routes); + nq->routes = NULL; + } + u_free(nq->tranzit_data); nq->tranzit_data = NULL; nq->tranzit_count = 0; + u_free(nq->hop_list); nq->hop_list = NULL; nq->hop_count = 0; } -int get_node_v6_sockets_meta(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SOCKET_META **out_meta) { - if (!node || !out_meta) return -1; - *out_meta = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v6_sockets == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - dynamic = skip_v4_sockets_meta(dynamic, info->local_v4_sockets); - dynamic = skip_v4_addrs(dynamic, info->local_v4_addrs); - *out_meta = (const struct NODEINFO_IPV6_SOCKET_META *)dynamic; - return (int)info->local_v6_sockets; +// ===== serialization ===== + +int nodeinfo_dyn_size(const struct NODEINFO_MSG* msg) { + return msg->node_name_len + + msg->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET_META) + + msg->local_v4_addrs * sizeof(struct NODEINFO_IPV4_ADDR) + + msg->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET_META) + + msg->local_v6_addrs * sizeof(struct NODEINFO_IPV6_ADDR) + + ((msg->flags & NODEINFO_FLAG_SEND_SUBNETS) + ? (msg->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET) + msg->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET)) + : 0) + + msg->tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE) + + msg->hop_count * 8; } -int get_node_v6_addrs(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_ADDR **out_addrs) { - if (!node || !out_addrs) return -1; - *out_addrs = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v6_addrs == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - dynamic = skip_v4_sockets_meta(dynamic, info->local_v4_sockets); - dynamic = skip_v4_addrs(dynamic, info->local_v4_addrs); - dynamic = skip_v6_sockets_meta(dynamic, info->local_v6_sockets); - *out_addrs = (const struct NODEINFO_IPV6_ADDR *)dynamic; - return (int)info->local_v6_addrs; +int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* out, size_t out_max) { + if (!bgp || !nq || !nq->node || !out) return -1; + struct NODEINFO* ni = nq->node; + + struct NODEINFO_MSG msg; + memset(&msg, 0, sizeof(msg)); + msg.flags = ni->flags; + msg.group_id = ni->group_id; + msg.node_id = ni->node_id; + msg.ver = ni->ver; + memcpy(msg.public_key, ni->public_key, SC_PUBKEY_SIZE); + memcpy(msg.ed25519_public_key, ni->ed25519_public_key, SC_PUBKEY_SIZE); + msg.node_name_len = ni->node_name ? (uint8_t)strlen(ni->node_name) : 0; + msg.local_v4_sockets = ni_list_count((struct _ni_head*)ni->v4_sock_meta); + msg.local_v4_addrs = ni_list_count((struct _ni_head*)ni->v4_addrs); + msg.local_v6_sockets = ni_list_count((struct _ni_head*)ni->v6_sock_meta); + msg.local_v6_addrs = ni_list_count((struct _ni_head*)ni->v6_addrs); + msg.local_v4_subnets = nq->routes ? ni_list_count((struct _ni_head*)nq->routes->v4_subnets) : 0; + msg.local_v6_subnets = nq->routes ? ni_list_count((struct _ni_head*)nq->routes->v6_subnets) : 0; + msg.tranzit_nodes = nq->tranzit_count; + msg.hop_count = nq->hop_count; + + size_t total = NODEINFO_MSG_HDR_SIZE + (size_t)nodeinfo_dyn_size(&msg); + if (total > out_max) return -1; + + memcpy(out, &msg, NODEINFO_MSG_HDR_SIZE); + uint8_t* dp = out + NODEINFO_MSG_HDR_SIZE; + + if (msg.node_name_len) { memcpy(dp, ni->node_name, msg.node_name_len); dp += msg.node_name_len; } + + { struct NI_IPV4_SOCKET_META* e = ni->v4_sock_meta; while (e) { + struct NODEINFO_IPV4_SOCKET_META w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type }; + memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + { struct NI_IPV4_ADDR* e = ni->v4_addrs; while (e) { + struct NODEINFO_IPV4_ADDR w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol }; + memcpy(w.addr, e->addr, 4); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + { struct NI_IPV6_SOCKET_META* e = ni->v6_sock_meta; while (e) { + struct NODEINFO_IPV6_SOCKET_META w = { .id=e->id, .config_type=e->config_type, .nat_type=e->nat_type }; + memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + { struct NI_IPV6_ADDR* e = ni->v6_addrs; while (e) { + struct NODEINFO_IPV6_ADDR w = { .port=e->port, .type=e->type, .socket_id=e->socket_id, .protocol=e->protocol }; + memcpy(w.addr, e->addr, 16); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + if (msg.flags & NODEINFO_FLAG_SEND_SUBNETS) { + if (nq->routes) { + { struct NI_IPV4_SUBNET* e = nq->routes->v4_subnets; while (e) { + struct NODEINFO_IPV4_SUBNET w = { .prefix_length=e->prefix_length }; + memcpy(w.addr, e->addr, 4); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + { struct NI_IPV6_SUBNET* e = nq->routes->v6_subnets; while (e) { + struct NODEINFO_IPV6_SUBNET w = { .prefix_length=e->prefix_length }; + memcpy(w.addr, e->addr, 16); memcpy(dp, &w, sizeof(w)); dp += sizeof(w); e = e->next; + }} + } + } + if (msg.tranzit_nodes && nq->tranzit_data) { + size_t sz = msg.tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE); + memcpy(dp, nq->tranzit_data, sz); dp += sz; + } + if (msg.hop_count && nq->hop_list) { + size_t sz = msg.hop_count * 8; + memcpy(dp, nq->hop_list, sz); dp += sz; + } + return (int)(dp - out); } -int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets) { - if (!node || !out_subnets) return -1; - *out_subnets = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v4_subnets == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - dynamic = skip_v4_sockets_meta(dynamic, info->local_v4_sockets); - dynamic = skip_v4_addrs(dynamic, info->local_v4_addrs); - dynamic = skip_v6_sockets_meta(dynamic, info->local_v6_sockets); - dynamic = skip_v6_addrs(dynamic, info->local_v6_addrs); - *out_subnets = (const struct NODEINFO_IPV4_SUBNET *)dynamic; - return (int)info->local_v4_subnets; -} +// ===== deserialization ===== + +int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len, struct NODEINFO** out_ni, struct NODEINFO_ROUTES** out_routes, + struct NODEINFO_TRANZIT_NODE** out_tranzit, uint8_t* out_tranzit_count, + uint64_t** out_hop_list, uint8_t* out_hop_count) { + if (!bgp || !data || len < NODEINFO_MSG_HDR_SIZE || !out_ni) return -1; + + const struct NODEINFO_MSG* msg = (const struct NODEINFO_MSG*)data; + int dyn = nodeinfo_dyn_size(msg); + if ((size_t)dyn + NODEINFO_MSG_HDR_SIZE != len) return -1; + + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!ni) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "nodeinfo_deserialize: alloc NODEINFO failed"); return -1; } + ni->ref_count = 1; + ni->flags = msg->flags; + ni->group_id = msg->group_id; + ni->node_id = msg->node_id; + ni->ver = msg->ver; + memcpy(ni->public_key, msg->public_key, SC_PUBKEY_SIZE); + memcpy(ni->ed25519_public_key, msg->ed25519_public_key, SC_PUBKEY_SIZE); + + const uint8_t* dp = data + NODEINFO_MSG_HDR_SIZE; + + if (msg->node_name_len) { + ni->node_name = u_malloc(msg->node_name_len + 1); + if (ni->node_name) { memcpy(ni->node_name, dp, msg->node_name_len); ni->node_name[msg->node_name_len] = 0; } + dp += msg->node_name_len; + } + + for (int i = 0; i < msg->local_v4_sockets; i++) { + const struct NODEINFO_IPV4_SOCKET_META* w = (const struct NODEINFO_IPV4_SOCKET_META*)dp; dp += sizeof(*w); + struct NI_IPV4_SOCKET_META* e = memory_pool_alloc(bgp->v4_sock_meta_pool); + if (!e) { nodeinfo_unref(ni); return -1; } + e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; + e->next = ni->v4_sock_meta; ni->v4_sock_meta = e; + } + for (int i = 0; i < msg->local_v4_addrs; i++) { + const struct NODEINFO_IPV4_ADDR* w = (const struct NODEINFO_IPV4_ADDR*)dp; dp += sizeof(*w); + struct NI_IPV4_ADDR* e = memory_pool_alloc(bgp->v4_addr_pool); + if (!e) { nodeinfo_unref(ni); return -1; } + memcpy(e->addr, w->addr, 4); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; + e->next = ni->v4_addrs; ni->v4_addrs = e; + } + for (int i = 0; i < msg->local_v6_sockets; i++) { + const struct NODEINFO_IPV6_SOCKET_META* w = (const struct NODEINFO_IPV6_SOCKET_META*)dp; dp += sizeof(*w); + struct NI_IPV6_SOCKET_META* e = memory_pool_alloc(bgp->v6_sock_meta_pool); + if (!e) { nodeinfo_unref(ni); return -1; } + e->id = w->id; e->config_type = w->config_type; e->nat_type = w->nat_type; + e->next = ni->v6_sock_meta; ni->v6_sock_meta = e; + } + for (int i = 0; i < msg->local_v6_addrs; i++) { + const struct NODEINFO_IPV6_ADDR* w = (const struct NODEINFO_IPV6_ADDR*)dp; dp += sizeof(*w); + struct NI_IPV6_ADDR* e = memory_pool_alloc(bgp->v6_addr_pool); + if (!e) { nodeinfo_unref(ni); return -1; } + memcpy(e->addr, w->addr, 16); e->port = w->port; e->type = w->type; e->socket_id = w->socket_id; e->protocol = w->protocol; + e->next = ni->v6_addrs; ni->v6_addrs = e; + } + + if (out_routes && (msg->flags & NODEINFO_FLAG_SEND_SUBNETS) && (msg->local_v4_subnets || msg->local_v6_subnets)) { + struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES)); + if (!r) { nodeinfo_unref(ni); return -1; } + for (int i = 0; i < msg->local_v4_subnets; i++) { + const struct NODEINFO_IPV4_SUBNET* w = (const struct NODEINFO_IPV4_SUBNET*)dp; dp += sizeof(*w); + struct NI_IPV4_SUBNET* e = memory_pool_alloc(bgp->v4_subnet_pool); + if (!e) { u_free(r); nodeinfo_unref(ni); return -1; } + memcpy(e->addr, w->addr, 4); e->prefix_length = w->prefix_length; + e->next = r->v4_subnets; r->v4_subnets = e; + } + for (int i = 0; i < msg->local_v6_subnets; i++) { + const struct NODEINFO_IPV6_SUBNET* w = (const struct NODEINFO_IPV6_SUBNET*)dp; dp += sizeof(*w); + struct NI_IPV6_SUBNET* e = memory_pool_alloc(bgp->v6_subnet_pool); + if (!e) { u_free(r); nodeinfo_unref(ni); return -1; } + memcpy(e->addr, w->addr, 16); e->prefix_length = w->prefix_length; + e->next = r->v6_subnets; r->v6_subnets = e; + } + *out_routes = r; + } else if (!(msg->flags & NODEINFO_FLAG_SEND_SUBNETS)) { + dp += msg->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET) + + msg->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET); + if (out_routes) *out_routes = NULL; + } else { + if (out_routes) *out_routes = NULL; + } + + if (out_tranzit && msg->tranzit_nodes > 0) { + size_t tsz = msg->tranzit_nodes * sizeof(struct NODEINFO_TRANZIT_NODE); + *out_tranzit = u_malloc(tsz); + if (!*out_tranzit) { nodeinfo_unref(ni); return -1; } + memcpy(*out_tranzit, dp, tsz); dp += tsz; + *out_tranzit_count = msg->tranzit_nodes; + } + if (out_hop_list && msg->hop_count > 0) { + size_t hsz = msg->hop_count * 8; + *out_hop_list = u_malloc(hsz); + if (!*out_hop_list) { nodeinfo_unref(ni); return -1; } + memcpy(*out_hop_list, dp, hsz); dp += hsz; + *out_hop_count = msg->hop_count; + } -int get_node_v6_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SUBNET **out_subnets) { - if (!node || !out_subnets) return -1; - *out_subnets = NULL; - const struct NODEINFO *info = &node->node; - if (info->local_v6_subnets == 0) return 0; - const uint8_t *dynamic = node_dyn_start(info); - dynamic = skip_name(dynamic, info->node_name_len); - dynamic = skip_v4_sockets_meta(dynamic, info->local_v4_sockets); - dynamic = skip_v4_addrs(dynamic, info->local_v4_addrs); - dynamic = skip_v6_sockets_meta(dynamic, info->local_v6_sockets); - dynamic = skip_v6_addrs(dynamic, info->local_v6_addrs); - dynamic = skip_v4_subnets(dynamic, info->local_v4_subnets); - *out_subnets = (const struct NODEINFO_IPV6_SUBNET *)dynamic; - return (int)info->local_v6_subnets; + *out_ni = ni; + return 0; } struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id) { @@ -129,6 +262,8 @@ struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id) return e ? (struct NODEINFO_Q*)e : NULL; } +// ===== dump / format (updated for new structures) ===== + static int is_node_connectivity_active(struct NODE_CONNECTIVITY* c) { return c->probe_status != PROBE_STATUS_NONE || c->interface_status != PROBE_RESULT_UNKNOWN @@ -157,83 +292,55 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) { struct ll_entry* e = bgp->nodes->head; while (e) { struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e; - struct NODEINFO* ni = &nq->node; + struct NODEINFO* ni = nq->node; + if (!ni) { e = e->next; continue; } int is_local = (bgp->local_node == nq); - const char* name_s = (ni->node_name_len > 0) ? (const char*)((const uint8_t*)ni + sizeof(struct NODEINFO)) : ""; + const char* name_s = ni->node_name ? ni->node_name : ""; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "--- Node #%d: id=%016llx name=\"%.*s\" ver=%u dirty=%u alien=%u%s ---", - idx, (unsigned long long)ni->node_id, ni->node_name_len, name_s, - ni->ver, nq->dirty, nq->alien, is_local ? " [LOCAL]" : ""); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "--- Node #%d: id=%016llx name=\"%s\" ver=%u dirty=%u alien=%u grp=%llu%s ---", + idx, (unsigned long long)ni->node_id, name_s, ni->ver, nq->dirty, nq->alien, + (unsigned long long)ni->group_id, is_local ? " [LOCAL]" : ""); if (nq->best_socket) DEBUG_INFO(DEBUG_CATEGORY_BGP, " best_socket=%p", (void*)nq->best_socket); log_dump(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_BGP, " pubkey ", ni->public_key, SC_PUBKEY_SIZE); log_dump(DEBUG_LEVEL_INFO, DEBUG_CATEGORY_BGP, " ed25519", ni->ed25519_public_key, SC_PUBKEY_SIZE); - const struct NODEINFO_IPV4_SOCKET_META* v4sm; - int v4sm_cnt = get_node_v4_sockets_meta(nq, &v4sm); - if (v4sm_cnt > 0) for (int i = 0; i < v4sm_cnt; i++) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sock[%d]: id=%u config=%u nat=%u", i, v4sm[i].id, v4sm[i].config_type, v4sm[i].nat_type); - } - - const struct NODEINFO_IPV4_ADDR* v4a; - int v4a_cnt = get_node_v4_addrs(nq, &v4a); - if (v4a_cnt > 0) { - const char* atn[] = {"INTERFACE","NAT","REAL"}; - for (int i = 0; i < v4a_cnt; i++) { - const char* proto = (v4a[i].protocol & NODE_PROTO_TCP) ? "tcp" : (v4a[i].protocol & NODE_PROTO_UDP) ? "udp" : "?"; - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4addr[%d]: %s:%u %s sock=%u proto=%s", - i, ip_to_str(v4a[i].addr, AF_INET).str, v4a[i].port, - (v4a[i].type<=2)?atn[v4a[i].type]:"?", v4a[i].socket_id, proto); - } - } - - const struct NODEINFO_IPV6_SOCKET_META* v6sm; - int v6sm_cnt = get_node_v6_sockets_meta(nq, &v6sm); - if (v6sm_cnt > 0) for (int i = 0; i < v6sm_cnt; i++) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sock[%d]: id=%u config=%u nat=%u", i, v6sm[i].id, v6sm[i].config_type, v6sm[i].nat_type); + int si = 0; + { struct NI_IPV4_SOCKET_META* sm = ni->v4_sock_meta; while (sm) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sock[%d]: id=%u config=%u nat=%u", si++, sm->id, sm->config_type, sm->nat_type); + sm = sm->next; + }} + { const char* atn[] = {"INTERFACE","NAT","REAL"}; + int ai = 0; struct NI_IPV4_ADDR* a = ni->v4_addrs; while (a) { + const char* proto = (a->protocol & NODE_PROTO_TCP) ? "tcp" : (a->protocol & NODE_PROTO_UDP) ? "udp" : "?"; + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4addr[%d]: %s:%u %s sock=%u proto=%s", ai++, + ip_to_str(a->addr, AF_INET).str, a->port, (a->type<=2)?atn[a->type]:"?", a->socket_id, proto); + a = a->next; + }} + { int si6 = 0; struct NI_IPV6_SOCKET_META* sm6 = ni->v6_sock_meta; while (sm6) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sock[%d]: id=%u config=%u nat=%u", si6++, sm6->id, sm6->config_type, sm6->nat_type); + sm6 = sm6->next; + }} + { int ai6 = 0; struct NI_IPV6_ADDR* a6 = ni->v6_addrs; while (a6) { + const char* proto = (a6->protocol & NODE_PROTO_TCP) ? "tcp" : (a6->protocol & NODE_PROTO_UDP) ? "udp" : "?"; + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6addr[%d]: %s:%u type=%u sock=%u proto=%s", ai6++, + ip_to_str(a6->addr, AF_INET6).str, a6->port, a6->type, a6->socket_id, proto); + a6 = a6->next; + }} + if (nq->routes) { + { int ri = 0; struct NI_IPV4_SUBNET* sub = nq->routes->v4_subnets; while (sub) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sub[%d]: %s/%d", ri++, ip_to_str(sub->addr, AF_INET).str, sub->prefix_length); + sub = sub->next; + }} + { int ri6 = 0; struct NI_IPV6_SUBNET* sub6 = nq->routes->v6_subnets; while (sub6) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sub[%d]: %s/%d", ri6++, ip_to_str(sub6->addr, AF_INET6).str, sub6->prefix_length); + sub6 = sub6->next; + }} } - - const struct NODEINFO_IPV6_ADDR* v6a; - int v6a_cnt = get_node_v6_addrs(nq, &v6a); - if (v6a_cnt > 0) { - for (int i = 0; i < v6a_cnt; i++) { - const char* proto = (v6a[i].protocol & NODE_PROTO_TCP) ? "tcp" : (v6a[i].protocol & NODE_PROTO_UDP) ? "udp" : "?"; - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6addr[%d]: %s:%u type=%u sock=%u proto=%s", - i, ip_to_str(v6a[i].addr, AF_INET6).str, v6a[i].port, - v6a[i].type, v6a[i].socket_id, proto); - } - } - - const struct NODEINFO_IPV4_SUBNET* sub4; - int sub4_cnt = get_node_routes(nq, &sub4); - if (sub4_cnt > 0) for (int i = 0; i < sub4_cnt; i++) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v4sub[%d]: %s/%d", i, - ip_to_str(sub4[i].addr, AF_INET).str, sub4[i].prefix_length); - } - - const struct NODEINFO_IPV6_SUBNET* sub6; - int sub6_cnt = get_node_v6_routes(nq, &sub6); - if (sub6_cnt > 0) for (int i = 0; i < sub6_cnt; i++) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, " v6sub[%d]: %s/%d", i, - ip_to_str(sub6[i].addr, AF_INET6).str, sub6[i].prefix_length); - } - - if (ni->tranzit_nodes > 0) { - const uint8_t* dyn = node_dyn_start(ni); - dyn = skip_name(dyn, ni->node_name_len); - dyn = skip_v4_sockets_meta(dyn, ni->local_v4_sockets); - dyn = skip_v4_addrs(dyn, ni->local_v4_addrs); - dyn = skip_v6_sockets_meta(dyn, ni->local_v6_sockets); - dyn = skip_v6_addrs(dyn, ni->local_v6_addrs); - dyn = skip_v4_subnets(dyn, ni->local_v4_subnets); - const struct NODEINFO_IPV6_SUBNET* sub6_dyn = (const struct NODEINFO_IPV6_SUBNET*)dyn; - dyn += ni->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET); - const struct NODEINFO_TRANZIT_NODE* tr = (const struct NODEINFO_TRANZIT_NODE*)dyn; - for (uint8_t i = 0; i < ni->tranzit_nodes; i++) { - DEBUG_INFO(DEBUG_CATEGORY_BGP, " tranzit[%d]: node=%016llx rtt=%u linkq=%u", - i, (unsigned long long)tr[i].node_id, tr[i].rtt, tr[i].link_q); - } + for (int i = 0; i < nq->tranzit_count; i++) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, " tranzit[%d]: node=%016llx rtt=%u linkq=%u", + i, (unsigned long long)nq->tranzit_data[i].node_id, nq->tranzit_data[i].rtt, nq->tranzit_data[i].link_q); } int path_idx = 0; @@ -242,44 +349,31 @@ void route_node_dump_all(struct ROUTE_BGP* bgp) { while (pe) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe; uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); - char hop_buf[256] = ""; - int hop_pos = 0; - for (uint8_t hi = 0; hi < path->hop_count && hop_pos < (int)sizeof(hop_buf)-20; hi++) { - hop_pos += snprintf(hop_buf + hop_pos, sizeof(hop_buf) - hop_pos, - "%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]); - } + char hop_buf[256] = ""; int hop_pos = 0; + for (uint8_t hi = 0; hi < path->hop_count && hop_pos < (int)sizeof(hop_buf)-20; hi++) + hop_pos += snprintf(hop_buf + hop_pos, sizeof(hop_buf) - hop_pos, "%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]); DEBUG_INFO(DEBUG_CATEGORY_BGP, " path[%d]: conn=%s hop_count=%u hops=[%s]", - path_idx, path->conn ? path->conn->log_name : "NULL", - path->hop_count, hop_buf); - path_idx++; - pe = pe->next; + path_idx, path->conn ? path->conn->log_name : "NULL", path->hop_count, hop_buf); + path_idx++; pe = pe->next; } } struct NODE_CONNECTIVITY* c = &nq->connectivity; if (is_node_connectivity_active(c)) { DEBUG_INFO(DEBUG_CATEGORY_BGP, " connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu", - probe_status_str(c->probe_status), - probe_result_str(c->interface_status), c->interface_min_rtt, - probe_result_str(c->nat_status), c->nat_min_rtt, - probe_result_str(c->real_status), c->real_min_rtt, + probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt, + probe_result_str(c->nat_status), c->nat_min_rtt, probe_result_str(c->real_status), c->real_min_rtt, c->pending_count, c->interface_min_rtt, c->nat_min_rtt, c->real_min_rtt, (unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time); } - if (nq->conn_mgr_type != CONN_TYPE_NONE) { - char interm_buf[200] = ""; - int ipos = 0; - for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count && ipos < (int)sizeof(interm_buf)-19; i++) { - ipos += snprintf(interm_buf + ipos, sizeof(interm_buf) - ipos, - "%s%016llx", i ? "," : "", (unsigned long long)nq->conn_mgr_intermediaries[i]); - } - DEBUG_INFO(DEBUG_CATEGORY_BGP, " conn_mgr: type=%s intermediates=[%s]", - conn_mgr_type_str(nq->conn_mgr_type), interm_buf); + char interm_buf[200] = ""; int ipos = 0; + for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count && ipos < (int)sizeof(interm_buf)-19; i++) + ipos += snprintf(interm_buf + ipos, sizeof(interm_buf) - ipos, "%s%016llx", i ? "," : "", (unsigned long long)nq->conn_mgr_intermediaries[i]); + DEBUG_INFO(DEBUG_CATEGORY_BGP, " conn_mgr: type=%s intermediates=[%s]", conn_mgr_type_str(nq->conn_mgr_type), interm_buf); } - e = e->next; - idx++; + e = e->next; idx++; } } @@ -294,394 +388,243 @@ int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size) { struct ll_entry* e = bgp->nodes->head; while (e && (size_t)pos < buf_size) { struct NODEINFO_Q* nq = (struct NODEINFO_Q*)e; - struct NODEINFO* ni = &nq->node; + struct NODEINFO* ni = nq->node; + if (!ni) { e = e->next; continue; } int is_local = (bgp->local_node == nq); - const char* name_s = (ni->node_name_len > 0) ? (const char*)((const uint8_t*)ni + sizeof(struct NODEINFO)) : ""; - - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - "--- Node #%d: id=%016llx name=\"%.*s\" ver=%u dirty=%u alien=%u%s ---\n", - idx, (unsigned long long)ni->node_id, ni->node_name_len, name_s, - ni->ver, nq->dirty, nq->alien, is_local ? " [LOCAL]" : ""); - - if (nq->best_socket) - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - " best_socket=%p\n", (void*)nq->best_socket); - - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, " pubkey: "); - for (int k = 0; k < SC_PUBKEY_SIZE; k++) - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "%02x", ni->public_key[k]); - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "\n"); - - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, " ed25519: "); - for (int k = 0; k < SC_PUBKEY_SIZE; k++) - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "%02x", ni->ed25519_public_key[k]); - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "\n"); - -#define FMT_ADD(fmt, ...) \ - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, fmt, ##__VA_ARGS__) - - const struct NODEINFO_IPV4_SOCKET_META* v4sm; - int v4sm_cnt = get_node_v4_sockets_meta(nq, &v4sm); - for (int i = 0; i < v4sm_cnt; i++) - FMT_ADD(" v4sock[%d]: id=%u config=%u nat=%u\n", i, v4sm[i].id, v4sm[i].config_type, v4sm[i].nat_type); - - const struct NODEINFO_IPV4_ADDR* v4a; - int v4a_cnt = get_node_v4_addrs(nq, &v4a); - if (v4a_cnt > 0) { - const char* atn[] = {"INTERFACE","NAT","REAL"}; - for (int i = 0; i < v4a_cnt; i++) { - const char* proto = (v4a[i].protocol & NODE_PROTO_TCP) ? "tcp" : (v4a[i].protocol & NODE_PROTO_UDP) ? "udp" : "?"; - FMT_ADD(" v4addr[%d]: %s:%u %s sock=%u proto=%s\n", - i, ip_to_str(v4a[i].addr, AF_INET).str, v4a[i].port, - (v4a[i].type<=2)?atn[v4a[i].type]:"?", v4a[i].socket_id, proto); - } - } - - const struct NODEINFO_IPV6_SOCKET_META* v6sm; - int v6sm_cnt = get_node_v6_sockets_meta(nq, &v6sm); - for (int i = 0; i < v6sm_cnt; i++) - FMT_ADD(" v6sock[%d]: id=%u config=%u nat=%u\n", i, v6sm[i].id, v6sm[i].config_type, v6sm[i].nat_type); - - const struct NODEINFO_IPV6_ADDR* v6a; - int v6a_cnt = get_node_v6_addrs(nq, &v6a); - for (int i = 0; i < v6a_cnt; i++) { - const char* proto = (v6a[i].protocol & NODE_PROTO_TCP) ? "tcp" : (v6a[i].protocol & NODE_PROTO_UDP) ? "udp" : "?"; + const char* name_s = ni->node_name ? ni->node_name : ""; + +#define FMT_ADD(fmt, ...) pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, fmt, ##__VA_ARGS__) + + FMT_ADD("--- Node #%d: id=%016llx name=\"%s\" ver=%u dirty=%u alien=%u grp=%llu%s ---\n", + idx, (unsigned long long)ni->node_id, name_s, ni->ver, nq->dirty, nq->alien, + (unsigned long long)ni->group_id, is_local ? " [LOCAL]" : ""); + + if (nq->best_socket) FMT_ADD(" best_socket=%p\n", (void*)nq->best_socket); + + FMT_ADD(" pubkey: "); for (int k = 0; k < SC_PUBKEY_SIZE; k++) FMT_ADD("%02x", ni->public_key[k]); FMT_ADD("\n"); + FMT_ADD(" ed25519: "); for (int k = 0; k < SC_PUBKEY_SIZE; k++) FMT_ADD("%02x", ni->ed25519_public_key[k]); FMT_ADD("\n"); + + { struct NI_IPV4_SOCKET_META* sm = ni->v4_sock_meta; int si = 0; while (sm) { + FMT_ADD(" v4sock[%d]: id=%u config=%u nat=%u\n", si++, sm->id, sm->config_type, sm->nat_type); sm = sm->next; + }} + { const char* atn[] = {"INTERFACE","NAT","REAL"}; struct NI_IPV4_ADDR* a = ni->v4_addrs; int ai = 0; while (a) { + const char* proto = (a->protocol & NODE_PROTO_TCP) ? "tcp" : (a->protocol & NODE_PROTO_UDP) ? "udp" : "?"; + FMT_ADD(" v4addr[%d]: %s:%u %s sock=%u proto=%s\n", + ai++, ip_to_str(a->addr, AF_INET).str, a->port, (a->type<=2)?atn[a->type]:"?", a->socket_id, proto); + a = a->next; + }} + { struct NI_IPV6_SOCKET_META* sm6 = ni->v6_sock_meta; int s6i = 0; while (sm6) { + FMT_ADD(" v6sock[%d]: id=%u config=%u nat=%u\n", s6i++, sm6->id, sm6->config_type, sm6->nat_type); sm6 = sm6->next; + }} + { struct NI_IPV6_ADDR* a6 = ni->v6_addrs; int a6i = 0; while (a6) { + const char* proto = (a6->protocol & NODE_PROTO_TCP) ? "tcp" : (a6->protocol & NODE_PROTO_UDP) ? "udp" : "?"; FMT_ADD(" v6addr[%d]: %s:%u type=%u sock=%u proto=%s\n", - i, ip_to_str(v6a[i].addr, AF_INET6).str, v6a[i].port, - v6a[i].type, v6a[i].socket_id, proto); - } - - const struct NODEINFO_IPV4_SUBNET* sub4; - int sub4_cnt = get_node_routes(nq, &sub4); - for (int i = 0; i < sub4_cnt; i++) - FMT_ADD(" v4sub[%d]: %s/%d\n", i, - ip_to_str(sub4[i].addr, AF_INET).str, sub4[i].prefix_length); - - const struct NODEINFO_IPV6_SUBNET* sub6; - int sub6_cnt = get_node_v6_routes(nq, &sub6); - for (int i = 0; i < sub6_cnt; i++) - FMT_ADD(" v6sub[%d]: %s/%d\n", i, - ip_to_str(sub6[i].addr, AF_INET6).str, sub6[i].prefix_length); - - if (ni->tranzit_nodes > 0) { - const uint8_t* dyn = node_dyn_start(ni); - dyn = skip_name(dyn, ni->node_name_len); - dyn = skip_v4_sockets_meta(dyn, ni->local_v4_sockets); - dyn = skip_v4_addrs(dyn, ni->local_v4_addrs); - dyn = skip_v6_sockets_meta(dyn, ni->local_v6_sockets); - dyn = skip_v6_addrs(dyn, ni->local_v6_addrs); - dyn = skip_v4_subnets(dyn, ni->local_v4_subnets); - dyn += ni->local_v6_subnets * sizeof(struct NODEINFO_IPV6_SUBNET); - const struct NODEINFO_TRANZIT_NODE* tr = (const struct NODEINFO_TRANZIT_NODE*)dyn; - for (uint8_t i = 0; i < ni->tranzit_nodes; i++) - FMT_ADD(" tranzit[%d]: node=%016llx rtt=%u linkq=%u\n", - i, (unsigned long long)tr[i].node_id, tr[i].rtt, tr[i].link_q); + a6i++, ip_to_str(a6->addr, AF_INET6).str, a6->port, a6->type, a6->socket_id, proto); + a6 = a6->next; + }} + if (nq->routes) { + { struct NI_IPV4_SUBNET* sub = nq->routes->v4_subnets; int ri = 0; while (sub) { + FMT_ADD(" v4sub[%d]: %s/%d\n", ri++, ip_to_str(sub->addr, AF_INET).str, sub->prefix_length); sub = sub->next; + }} + { struct NI_IPV6_SUBNET* sub6 = nq->routes->v6_subnets; int r6i = 0; while (sub6) { + FMT_ADD(" v6sub[%d]: %s/%d\n", r6i++, ip_to_str(sub6->addr, AF_INET6).str, sub6->prefix_length); sub6 = sub6->next; + }} } + for (int i = 0; i < nq->tranzit_count; i++) + FMT_ADD(" tranzit[%d]: node=%016llx rtt=%u linkq=%u\n", + i, (unsigned long long)nq->tranzit_data[i].node_id, nq->tranzit_data[i].rtt, nq->tranzit_data[i].link_q); if (nq->paths) { - int path_idx = 0; - struct ll_entry* pe = nq->paths->head; + struct ll_entry* pe = nq->paths->head; int pi = 0; while (pe) { struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)pe; uint64_t* hop = (uint64_t*)((uint8_t*)path + sizeof(struct NODEINFO_PATH)); - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - " path[%d]: conn=%s hop_count=%u hops=[", - path_idx, path->conn ? path->conn->log_name : "NULL", path->hop_count); + FMT_ADD(" path[%d]: conn=%s hop_count=%u hops=[", pi++, path->conn ? path->conn->log_name : "NULL", path->hop_count); for (uint8_t hi = 0; hi < path->hop_count; hi++) - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - "%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]); - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "]\n"); - path_idx++; - pe = pe->next; + FMT_ADD("%s%016llx", hi ? "->" : "", (unsigned long long)hop[hi]); + FMT_ADD("]\n"); pe = pe->next; } } struct NODE_CONNECTIVITY* c = &nq->connectivity; if (is_node_connectivity_active(c)) { FMT_ADD(" connectivity: probe=%s iface=%s(%u) nat=%s(%u) real=%s(%u) pend=%u iface_rtt=%u nat_rtt=%u real_rtt=%u start_tb=%llu ping_req_tb=%llu\n", - probe_status_str(c->probe_status), - probe_result_str(c->interface_status), c->interface_min_rtt, - probe_result_str(c->nat_status), c->nat_min_rtt, - probe_result_str(c->real_status), c->real_min_rtt, + probe_status_str(c->probe_status), probe_result_str(c->interface_status), c->interface_min_rtt, + probe_result_str(c->nat_status), c->nat_min_rtt, probe_result_str(c->real_status), c->real_min_rtt, c->pending_count, c->interface_min_rtt, c->nat_min_rtt, c->real_min_rtt, (unsigned long long)c->probe_start_time, (unsigned long long)c->ping_req_time); } - if (nq->conn_mgr_type != CONN_TYPE_NONE) { - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - " conn_mgr: type=%s intermediates=[", - conn_mgr_type_str(nq->conn_mgr_type)); + FMT_ADD(" conn_mgr: type=%s intermediates=[", conn_mgr_type_str(nq->conn_mgr_type)); for (uint8_t i = 0; i < nq->conn_mgr_intermediariy_count; i++) - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, - "%s%016llx", i ? "," : "", - (unsigned long long)nq->conn_mgr_intermediaries[i]); - pos += snprintf(buf + pos, buf_size > (size_t)pos ? buf_size - pos : 0, "]\n"); + FMT_ADD("%s%016llx", i ? "," : "", (unsigned long long)nq->conn_mgr_intermediaries[i]); + FMT_ADD("]\n"); } #undef FMT_ADD - e = e->next; - idx++; + e = e->next; idx++; } if ((size_t)pos >= buf_size) { - pos = (int)buf_size - 14; - if (pos < 0) pos = 0; + pos = (int)buf_size - 14; if (pos < 0) pos = 0; pos += snprintf(buf + pos, buf_size - pos, "\n[TRUNCATED]\n"); } - return pos; } +// ===== update my nodeinfo (rewritten for new structures) ===== + int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp) { - if (!instance || !bgp) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_update_my_nodeinfo: invalid args"); - return -1; - } + if (!instance || !bgp) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_update_my_nodeinfo: invalid args"); return -1; } size_t name_len = 0; - if (instance->name[0]) { - name_len = strlen(instance->name); - if (name_len > 63) name_len = 63; - } + if (instance->name[0]) { name_len = strlen(instance->name); if (name_len > 63) name_len = 63; } int vc = 0, vc6 = 0; struct CFG_ROUTE_ENTRY* s = instance->config->my_subnets; while (s) { if (s->ip.family == AF_INET) vc++; else if (s->ip.family == AF_INET6) vc6++; s = s->next; } - int sock_count = 0, addr_count = 0; - int sock6_count = 0, addr6_count = 0; + int sock_count = 0, addr_count = 0, sock6_count = 0, addr6_count = 0; struct ETCP_SOCKET* e_sock = instance->etcp_sockets; while (e_sock) { if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } if (e_sock->local_addr.ss_family == AF_INET) { - sock_count++; - addr_count++; // INTERFACE + sock_count++; addr_count++; if (e_sock->nat_addr.ss_family == AF_INET) { struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr; - if (nat_sin->sin_addr.s_addr != 0) { - if (e_sock->nat_type != NAT_VERIFIED_STRICT) addr_count++; - } + if (nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) addr_count++; } - if (e_sock->nat_type == NAT_VERIFIED_DIRECT || - ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) - && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) addr_count++; - } else if (e_sock->local_addr.ss_family == AF_INET6) { - sock6_count++; - addr6_count++; // INTERFACE only (no NAT for IPv6) - } + if (e_sock->nat_type == NAT_VERIFIED_DIRECT || ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) addr_count++; + } else if (e_sock->local_addr.ss_family == AF_INET6) { sock6_count++; addr6_count++; } e_sock = e_sock->next; } - - int tcp_v4_count = 0, tcp_v6_count = 0; { struct CFG_SERVER* srv = instance->config->servers; - while (srv) { - if (srv->transport) { - if (srv->ip.ss_family == AF_INET) tcp_v4_count++; - else if (srv->ip.ss_family == AF_INET6) tcp_v6_count++; - } - srv = srv->next; - } + while (srv) { if (srv->transport) { if (srv->ip.ss_family == AF_INET) addr_count++; else if (srv->ip.ss_family == AF_INET6) addr6_count++; } srv = srv->next; } } - addr_count += tcp_v4_count; - addr6_count += tcp_v6_count; - - size_t dyn = name_len + sock_count * sizeof(struct NODEINFO_IPV4_SOCKET_META) - + addr_count * sizeof(struct NODEINFO_IPV4_ADDR) - + sock6_count * sizeof(struct NODEINFO_IPV6_SOCKET_META) - + addr6_count * sizeof(struct NODEINFO_IPV6_ADDR) - + vc * sizeof(struct NODEINFO_IPV4_SUBNET) - + vc6 * sizeof(struct NODEINFO_IPV6_SUBNET); - - int changed = 1; - uint8_t old_ver = 0; - if (bgp->local_node) { - old_ver = bgp->local_node->node.ver; - changed = (vc != (int)bgp->local_node->node.local_v4_subnets) - || (sock_count != (int)bgp->local_node->node.local_v4_sockets) - || (addr_count != (int)bgp->local_node->node.local_v4_addrs) - || (name_len != bgp->local_node->node.node_name_len) - || (memcmp(bgp->local_node->node.public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE) != 0) - || (vc6 != (int)bgp->local_node->node.local_v6_subnets) - || (sock6_count != (int)bgp->local_node->node.local_v6_sockets) - || (addr6_count != (int)bgp->local_node->node.local_v6_addrs); - if (bgp->local_node && bgp->instance && bgp->instance->bgp) { - if (memcmp(bgp->local_node->node.ed25519_public_key, bgp->instance->bgp->ed25519_public_key, SC_PUBKEY_SIZE) != 0) changed = 1; - } + + int changed = 1; uint8_t old_ver = 0; + if (bgp->local_node && bgp->local_node->node) { + struct NODEINFO* oni = bgp->local_node->node; + old_ver = oni->ver; + int v4a_cnt = ni_list_count((struct _ni_head*)oni->v4_addrs); + changed = (vc != (bgp->local_node->routes ? ni_list_count((struct _ni_head*)bgp->local_node->routes->v4_subnets) : 0)) + || (sock_count != ni_list_count((struct _ni_head*)oni->v4_sock_meta)) + || (addr_count != v4a_cnt) + || (name_len != (oni->node_name ? strlen(oni->node_name) : 0)) + || (memcmp(oni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE) != 0) + || (vc6 != (bgp->local_node->routes ? ni_list_count((struct _ni_head*)bgp->local_node->routes->v6_subnets) : 0)) + || (sock6_count != ni_list_count((struct _ni_head*)oni->v6_sock_meta)) + || (addr6_count != ni_list_count((struct _ni_head*)oni->v6_addrs)); + if (bgp->local_node && bgp->instance && bgp->instance->bgp) + if (memcmp(oni->ed25519_public_key, bgp->instance->bgp->ed25519_public_key, SC_PUBKEY_SIZE) != 0) changed = 1; } - if (changed) { + if (changed) { if (bgp->local_node) { if (instance->rt) route_delete(instance->rt, bgp->local_node); + nodeinfo_free_lists(bgp, bgp->local_node); u_free(bgp->local_node); + bgp->local_node = NULL; } - bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn); + + bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q)); if (!bgp->local_node) return -1; - bgp->local_node->node.node_id = instance->node_id; - bgp->local_node->node.hop_count = 0; - bgp->local_node->node.ver = (old_ver % 255) + 1; - bgp->local_node->node.local_v4_sockets = sock_count; - bgp->local_node->node.local_v4_addrs = addr_count; - bgp->local_node->node.local_v6_sockets = sock6_count; - bgp->local_node->node.local_v6_addrs = addr6_count; - bgp->local_node->node.local_v4_subnets = vc; - bgp->local_node->node.local_v6_subnets = vc6; - bgp->local_node->node.node_name_len = name_len; - memcpy(bgp->local_node->node.public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE); - memcpy(bgp->local_node->node.ed25519_public_key, bgp->ed25519_public_key, SC_PUBKEY_SIZE); - bgp->local_node->dirty = 1; - bgp->local_node->last_ver = bgp->local_node->node.ver; - - uint8_t* dp = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO); - if (name_len) { memcpy(dp, instance->name, name_len); dp += name_len; } - - // Write IPv4 socket meta - struct NODEINFO_IPV4_SOCKET_META* meta = (struct NODEINFO_IPV4_SOCKET_META*)dp; - e_sock = instance->etcp_sockets; - int midx = 0; - while (e_sock) { - if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } - if (e_sock->local_addr.ss_family == AF_INET) { - meta[midx].id = e_sock->sock_id; - meta[midx].config_type = e_sock->type; - meta[midx].nat_type = e_sock->nat_type; - midx++; - } - e_sock = e_sock->next; - } - dp += sock_count * sizeof(struct NODEINFO_IPV4_SOCKET_META); + struct NODEINFO_Q* lq = bgp->local_node; + + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!ni) { u_free(lq); bgp->local_node = NULL; return -1; } + ni->ref_count = 1; + ni->flags = NODEINFO_FLAG_SEND_SUBNETS; + ni->group_id = NODEINFO_GROUP_UTUN; + ni->node_id = instance->node_id; + ni->ver = (old_ver % 255) + 1; + memcpy(ni->public_key, instance->my_keys.public_key, SC_PUBKEY_SIZE); + memcpy(ni->ed25519_public_key, bgp->ed25519_public_key, SC_PUBKEY_SIZE); + if (name_len) { ni->node_name = u_malloc(name_len + 1); if (ni->node_name) { memcpy(ni->node_name, instance->name, name_len); ni->node_name[name_len] = 0; } } + + lq->node = ni; + lq->hash_node_id = ni->node_id; + lq->hop_count = 0; + lq->dirty = 1; + lq->last_ver = ni->ver; - // Write IPv4 addresses - struct NODEINFO_IPV4_ADDR* addrs = (struct NODEINFO_IPV4_ADDR*)dp; - int aidx = 0; e_sock = instance->etcp_sockets; while (e_sock) { if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } if (e_sock->local_addr.ss_family == AF_INET) { + { struct NI_IPV4_SOCKET_META* sm = memory_pool_alloc(bgp->v4_sock_meta_pool); + sm->id = e_sock->sock_id; sm->config_type = e_sock->type; sm->nat_type = e_sock->nat_type; + sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; } + struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr; struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr; - memcpy(addrs[aidx].addr, &if_sin->sin_addr.s_addr, 4); - addrs[aidx].port = ntohs(if_sin->sin_port); - addrs[aidx].type = ADDR_TYPE_INTERFACE; - addrs[aidx].socket_id = e_sock->sock_id; - addrs[aidx].protocol = NODE_PROTO_UDP; - aidx++; - - if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0) { - if (e_sock->nat_type != NAT_VERIFIED_STRICT) { - memcpy(addrs[aidx].addr, &nat_sin->sin_addr.s_addr, 4); - addrs[aidx].port = ntohs(nat_sin->sin_port); - addrs[aidx].type = ADDR_TYPE_NAT; - addrs[aidx].socket_id = e_sock->sock_id; - addrs[aidx].protocol = NODE_PROTO_UDP; - aidx++; - } + { struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool); + memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); + a->type = ADDR_TYPE_INTERFACE; a->socket_id = e_sock->sock_id; a->protocol = NODE_PROTO_UDP; + a->next = ni->v4_addrs; ni->v4_addrs = a; } + if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) { + struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool); + memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port); + a->type = ADDR_TYPE_NAT; a->socket_id = e_sock->sock_id; a->protocol = NODE_PROTO_UDP; + a->next = ni->v4_addrs; ni->v4_addrs = a; } - if (e_sock->nat_type == NAT_VERIFIED_DIRECT || - ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) - && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) { - memcpy(addrs[aidx].addr, &if_sin->sin_addr.s_addr, 4); - addrs[aidx].port = ntohs(if_sin->sin_port); - addrs[aidx].type = ADDR_TYPE_REAL; - addrs[aidx].socket_id = e_sock->sock_id; - addrs[aidx].protocol = NODE_PROTO_UDP; - aidx++; + if (e_sock->nat_type == NAT_VERIFIED_DIRECT || ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) { + struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool); + memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); + a->type = ADDR_TYPE_REAL; a->socket_id = e_sock->sock_id; a->protocol = NODE_PROTO_UDP; + a->next = ni->v4_addrs; ni->v4_addrs = a; } + } else if (e_sock->local_addr.ss_family == AF_INET6) { + { struct NI_IPV6_SOCKET_META* sm6 = memory_pool_alloc(bgp->v6_sock_meta_pool); + sm6->id = e_sock->sock_id; sm6->config_type = e_sock->type; sm6->nat_type = e_sock->nat_type; + sm6->next = ni->v6_sock_meta; ni->v6_sock_meta = sm6; } + struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr; + { struct NI_IPV6_ADDR* a6 = memory_pool_alloc(bgp->v6_addr_pool); + memcpy(a6->addr, &if_sin6->sin6_addr, 16); a6->port = ntohs(if_sin6->sin6_port); + a6->type = ADDR_TYPE_INTERFACE; a6->socket_id = e_sock->sock_id; a6->protocol = NODE_PROTO_UDP; + a6->next = ni->v6_addrs; ni->v6_addrs = a6; } } e_sock = e_sock->next; } - - // Write TCP IPv4 addresses from config servers { struct CFG_SERVER* srv = instance->config->servers; - while (srv) { - if (srv->transport && srv->ip.ss_family == AF_INET) { - struct sockaddr_in* tcp_sin = (struct sockaddr_in*)&srv->ip; - memcpy(addrs[aidx].addr, &tcp_sin->sin_addr.s_addr, 4); - addrs[aidx].port = ntohs(tcp_sin->sin_port); - addrs[aidx].type = ADDR_TYPE_INTERFACE; - addrs[aidx].socket_id = 0; - addrs[aidx].protocol = NODE_PROTO_TCP; - aidx++; - } - srv = srv->next; - } - } - dp += addr_count * sizeof(struct NODEINFO_IPV4_ADDR); - - // Write IPv6 socket meta - struct NODEINFO_IPV6_SOCKET_META* meta6 = (struct NODEINFO_IPV6_SOCKET_META*)dp; - e_sock = instance->etcp_sockets; - int m6idx = 0; - while (e_sock) { - if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } - if (e_sock->local_addr.ss_family == AF_INET6) { - meta6[m6idx].id = e_sock->sock_id; - meta6[m6idx].config_type = e_sock->type; - meta6[m6idx].nat_type = e_sock->nat_type; - m6idx++; - } - e_sock = e_sock->next; + while (srv) { if (srv->transport && srv->ip.ss_family == AF_INET) { + struct sockaddr_in* tcp_sin = (struct sockaddr_in*)&srv->ip; + struct NI_IPV4_ADDR* a = memory_pool_alloc(bgp->v4_addr_pool); + memcpy(a->addr, &tcp_sin->sin_addr.s_addr, 4); a->port = ntohs(tcp_sin->sin_port); + a->type = ADDR_TYPE_INTERFACE; a->socket_id = 0; a->protocol = NODE_PROTO_TCP; + a->next = ni->v4_addrs; ni->v4_addrs = a; + } else if (srv->transport && srv->ip.ss_family == AF_INET6) { + struct sockaddr_in6* tcp_sin6 = (struct sockaddr_in6*)&srv->ip; + struct NI_IPV6_ADDR* a6 = memory_pool_alloc(bgp->v6_addr_pool); + memcpy(a6->addr, &tcp_sin6->sin6_addr, 16); a6->port = ntohs(tcp_sin6->sin6_port); + a6->type = ADDR_TYPE_INTERFACE; a6->socket_id = 0; a6->protocol = NODE_PROTO_TCP; + a6->next = ni->v6_addrs; ni->v6_addrs = a6; + } srv = srv->next; } } - dp += sock6_count * sizeof(struct NODEINFO_IPV6_SOCKET_META); - // Write IPv6 addresses (INTERFACE only) - struct NODEINFO_IPV6_ADDR* addrs6 = (struct NODEINFO_IPV6_ADDR*)dp; - int a6idx = 0; - e_sock = instance->etcp_sockets; - while (e_sock) { - if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) { e_sock = e_sock->next; continue; } - if (e_sock->local_addr.ss_family == AF_INET6) { - struct sockaddr_in6* if_sin6 = (struct sockaddr_in6*)&e_sock->interface_addr; - memcpy(addrs6[a6idx].addr, &if_sin6->sin6_addr, 16); - addrs6[a6idx].port = ntohs(if_sin6->sin6_port); - addrs6[a6idx].type = ADDR_TYPE_INTERFACE; - addrs6[a6idx].socket_id = e_sock->sock_id; - addrs6[a6idx].protocol = NODE_PROTO_UDP; - a6idx++; + if (vc || vc6) { + struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES)); + s = instance->config->my_subnets; + while (s) { + if (s->ip.family == AF_INET) { + struct NI_IPV4_SUBNET* sub = memory_pool_alloc(bgp->v4_subnet_pool); + memcpy(sub->addr, &s->ip.addr.v4, 4); sub->prefix_length = s->netmask; + sub->next = r->v4_subnets; r->v4_subnets = sub; + } else if (s->ip.family == AF_INET6) { + struct NI_IPV6_SUBNET* sub6 = memory_pool_alloc(bgp->v6_subnet_pool); + memcpy(sub6->addr, &s->ip.addr.v6, 16); sub6->prefix_length = s->netmask; + sub6->next = r->v6_subnets; r->v6_subnets = sub6; + } + s = s->next; } - e_sock = e_sock->next; - } - - // Write TCP IPv6 addresses from config servers - { struct CFG_SERVER* srv = instance->config->servers; - while (srv) { - if (srv->transport && srv->ip.ss_family == AF_INET6) { - struct sockaddr_in6* tcp_sin6 = (struct sockaddr_in6*)&srv->ip; - memcpy(addrs6[a6idx].addr, &tcp_sin6->sin6_addr, 16); - addrs6[a6idx].port = ntohs(tcp_sin6->sin6_port); - addrs6[a6idx].type = ADDR_TYPE_INTERFACE; - addrs6[a6idx].socket_id = 0; - addrs6[a6idx].protocol = NODE_PROTO_TCP; - a6idx++; - } - srv = srv->next; - } - } - dp += addr6_count * sizeof(struct NODEINFO_IPV6_ADDR); - - // Write IPv4 subnets - struct NODEINFO_IPV4_SUBNET* ra = (struct NODEINFO_IPV4_SUBNET*)dp; - s = instance->config->my_subnets; - while (s) { - if (s->ip.family == AF_INET) { memcpy(ra->addr, &s->ip.addr.v4, 4); ra->prefix_length = s->netmask; ra++; } - s = s->next; - } - dp += vc * sizeof(struct NODEINFO_IPV4_SUBNET); - - // Write IPv6 subnets - struct NODEINFO_IPV6_SUBNET* ra6 = (struct NODEINFO_IPV6_SUBNET*)dp; - s = instance->config->my_subnets; - while (s) { - if (s->ip.family == AF_INET6) { memcpy(ra6->addr, &s->ip.addr.v6, 16); ra6->prefix_length = s->netmask; ra6++; } - s = s->next; + lq->routes = r; } DEBUG_INFO(DEBUG_CATEGORY_BGP, "my_nodeinfo updated: v4s=%d v4a=%d v6s=%d v6a=%d v4sub=%d v6sub=%d ver=%d", - sock_count, addr_count, sock6_count, addr6_count, vc, vc6, bgp->local_node->node.ver); - if (instance->rt) { - if (!route_insert(instance->rt, bgp->local_node)) - DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_bgp_update_my_nodeinfo: failed to re-insert local routes after update"); - } + sock_count, addr_count, sock6_count, addr6_count, vc, vc6, ni->ver); + if (instance->rt && !route_insert(instance->rt, lq)) + DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_bgp_update_my_nodeinfo: failed to insert local routes"); } else { - bgp->local_node->last_ver = bgp->local_node->node.ver; + bgp->local_node->last_ver = bgp->local_node->node->ver; } return vc; } diff --git a/src/route_node.h b/src/route_node.h index b595d737..a0c8dcd2 100644 --- a/src/route_node.h +++ b/src/route_node.h @@ -47,87 +47,66 @@ struct UTUN_INSTANCE; #define CONN_TYPE_INDIRECT 3 #define CONN_MGR_MAX_INTERMEDIARIES 3 +// ---- флаги nodeinfo (protocol) ---- +#define NODEINFO_FLAG_SEND_SUBNETS 0x01 + +// ---- group_id по умолчанию ---- +#define NODEINFO_GROUP_UTUN 1 + // ---- состояние связности с удалённым узлом (локальное, не передаётся по BGP) ---- struct NODE_CONNECTIVITY { - uint8_t probe_status; // PROBE_STATUS_* - uint8_t pending_count; // активных probe series - uint64_t probe_start_time; // timebase - uint16_t interface_min_rtt; // x0.1ms + uint8_t probe_status; + uint8_t pending_count; + uint64_t probe_start_time; + uint16_t interface_min_rtt; uint16_t nat_min_rtt; uint16_t real_min_rtt; - uint8_t interface_status; // PROBE_RESULT_* + uint8_t interface_status; uint8_t nat_status; uint8_t real_status; uint8_t reserved; uint64_t interface_probe_time; uint64_t nat_probe_time; uint64_t real_probe_time; - uint64_t ping_req_time; // время последнего полученного ping request от этого узла (0.1ms tb) - void* probe_list; // linked list of active conn_probe_ctx (для cancel) + uint64_t ping_req_time; + void* probe_list; }; -/** - * @brief Информация о узле (передаётся по BGP) - */ -struct NODEINFO { - uint64_t node_id; // (big-endian) - uint8_t ver; // версия пакета (циклический счетчик чтобы быстро сравнивать с локальной копией - были ли обновления) - uint8_t public_key[SC_PUBKEY_SIZE]; // X25519 pubkey - uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; // Ed25519 pubkey for signature verification - uint8_t node_name_len; // размер в байтах (без null терминации) - uint8_t local_v4_sockets; // NODEINFO_IPV4_SOCKET_META число метаданных ipv4 сокетов - uint8_t local_v4_addrs; // NODEINFO_IPV4_ADDR число типизированных ipv4 адресов узла (плоский список) - uint8_t local_v6_sockets; // NODEINFO_IPV6_SOCKET_META число метаданных ipv6 сокетов - uint8_t local_v6_addrs; // NODEINFO_IPV6_ADDR число типизированных ipv6 адресов узла - uint8_t local_v4_subnets; // NODEINFO_IPV4_SUBNET число локальных ipv4 подсетей узла - uint8_t local_v6_subnets; // NODEINFO_IPV6_SUBNET число локальных ipv6 подсетей узла - uint8_t tranzit_nodes; // NODEINFO_TRANZIT_NODE лучшие транзитные узлы для этой ноды >>> надо перенести в group-specific struct - uint8_t hop_count; // hop list: маршрут по которому распространялся этот NODEINFO_PACKET >>> надо перенести в group-specific struct -// далее идут динамические поля по порядку: -// char node_name[node_name_len] -// NODEINFO_IPV4_SOCKET_META[local_v4_sockets] -// NODEINFO_IPV4_ADDR[local_v4_addrs] -// NODEINFO_IPV6_SOCKET_META[local_v6_sockets] -// NODEINFO_IPV6_ADDR[local_v6_addrs] -// NODEINFO_IPV4_SUBNET[local_v4_subnets] -// NODEINFO_IPV6_SUBNET[local_v6_subnets] -// NODEINFO_TRANZIT_NODE[tranzit_nodes] -// uint64_t hop_list[hop_count] -} __attribute__((packed)); +// ======================================================================= +// Протокольные структуры (wire-format, packed, без next) +// ======================================================================= -// метаданные одного сокета struct NODEINFO_IPV4_SOCKET_META { - uint8_t id; // unique socket id (0-255) - uint8_t config_type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE - uint8_t nat_type; // NAT_TYPE_* / NAT_VERIFIED_* + uint8_t id; + uint8_t config_type; + uint8_t nat_type; } __attribute__((packed)); -// одна типизированная адресная запись (плоский список) struct NODEINFO_IPV4_ADDR { - uint8_t addr[4]; // IP (network byte order) - uint16_t port; // port (host byte order) - uint8_t type; // ADDR_TYPE_INTERFACE/NAT/REAL - uint8_t socket_id; // к какому сокету относится - uint8_t protocol; // битовая маска NODE_PROTO_UDP/NODE_PROTO_TCP + uint8_t addr[4]; + uint16_t port; + uint8_t type; + uint8_t socket_id; + uint8_t protocol; } __attribute__((packed)); struct NODEINFO_IPV6_SOCKET_META { - uint8_t id; // unique socket id (0-255) - uint8_t config_type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE - uint8_t nat_type; // NAT_TYPE_* / NAT_VERIFIED_* + uint8_t id; + uint8_t config_type; + uint8_t nat_type; } __attribute__((packed)); struct NODEINFO_IPV6_ADDR { - uint8_t addr[16]; + uint8_t addr[16]; uint16_t port; - uint8_t type; - uint8_t socket_id; - uint8_t protocol; // битовая маска NODE_PROTO_UDP/NODE_PROTO_TCP + uint8_t type; + uint8_t socket_id; + uint8_t protocol; } __attribute__((packed)); struct NODEINFO_IPV4_SUBNET { - uint8_t addr[4];// network byte order + uint8_t addr[4]; uint8_t prefix_length; } __attribute__((packed)); @@ -137,68 +116,127 @@ struct NODEINFO_IPV6_SUBNET { } __attribute__((packed)); struct NODEINFO_TRANZIT_NODE { - uint64_t node_id; // (big-endian) - uint16_t rtt; // x0.1 ms (измеренный удаленным узлом RTT до транзитного узла) - uint16_t link_q; // меньше - лучше (потери + 1/BW) + uint64_t node_id; + uint16_t rtt; + uint16_t link_q; +} __attribute__((packed)); + +/** + * @brief Протокольный формат NODEINFO сообщения (wire-format) + */ +struct NODEINFO_MSG { + uint8_t flags; + uint64_t group_id; + uint64_t node_id; + uint8_t ver; + uint8_t public_key[SC_PUBKEY_SIZE]; + uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; + uint8_t node_name_len; + uint8_t local_v4_sockets; + uint8_t local_v4_addrs; + uint8_t local_v6_sockets; + uint8_t local_v6_addrs; + uint8_t local_v4_subnets; + uint8_t local_v6_subnets; + uint8_t tranzit_nodes; + uint8_t hop_count; } __attribute__((packed)); +#define NODEINFO_MSG_HDR_SIZE sizeof(struct NODEINFO_MSG) + +// ======================================================================= +// Структуры для хранения в памяти (linked list с next* первым полем) +// ======================================================================= + +struct NI_IPV4_SOCKET_META { struct NI_IPV4_SOCKET_META* next; uint8_t id, config_type, nat_type; }; +struct NI_IPV4_ADDR { struct NI_IPV4_ADDR* next; uint8_t addr[4]; uint16_t port; uint8_t type, socket_id, protocol; }; +struct NI_IPV6_SOCKET_META { struct NI_IPV6_SOCKET_META* next; uint8_t id, config_type, nat_type; }; +struct NI_IPV6_ADDR { struct NI_IPV6_ADDR* next; uint8_t addr[16]; uint16_t port; uint8_t type, socket_id, protocol; }; +struct NI_IPV4_SUBNET { struct NI_IPV4_SUBNET* next; uint8_t addr[4]; uint8_t prefix_length; }; +struct NI_IPV6_SUBNET { struct NI_IPV6_SUBNET* next; uint8_t addr[16]; uint8_t prefix_length; }; + +// Универсальная голова списка (next — первое поле во всех NI_*) +struct _ni_head { struct _ni_head* next; }; + +static inline int ni_list_count(struct _ni_head* head) { int n = 0; while (head) { n++; head = head->next; } return n; } + +/** + * @brief Идентификационная информация об узле (память, разделяется между группами) + */ +struct NODEINFO { + uint32_t ref_count; + uint8_t flags; + uint64_t group_id; + uint64_t node_id; + uint8_t ver; + uint8_t public_key[SC_PUBKEY_SIZE]; + uint8_t ed25519_public_key[SC_PUBKEY_SIZE]; + char* node_name; // отдельный u_strdup/u_free + struct NI_IPV4_SOCKET_META* v4_sock_meta; // linked list head + struct NI_IPV4_ADDR* v4_addrs; // linked list head + struct NI_IPV6_SOCKET_META* v6_sock_meta; + struct NI_IPV6_ADDR* v6_addrs; +}; + +/** + * @brief Маршруты узла (отдельный malloc, NULL если нет подсетей) + */ +struct NODEINFO_ROUTES { + struct NI_IPV4_SUBNET* v4_subnets; // linked list head + struct NI_IPV6_SUBNET* v6_subnets; +}; + struct NODEINFO_PATH { struct ll_entry ll; struct ETCP_CONN* conn; - uint8_t hop_count; // hop list: маршрут этого path + uint8_t hop_count; }; struct NODEINFO_Q { struct ll_entry ll; - struct ll_queue* paths; // сюда помещаем struct NODEINFO_PATH + uint64_t hash_node_id; // копия node_id для хеш-индекса + struct NODEINFO* node; // отдельный malloc, ref_count + struct NODEINFO_ROUTES* routes; // отдельный malloc (NULL если без подсетей) + struct NODEINFO_TRANZIT_NODE* tranzit_data; // отдельный malloc + uint64_t* hop_list; // отдельный malloc + uint8_t tranzit_count; + uint8_t hop_count; + struct ll_queue* paths; uint8_t dirty; uint8_t last_ver; - uint8_t alien; // 1 = чужой узел (не запрашиваем роутинг при connect) - uint8_t conn_mgr_type; // CONN_TYPE_* — тип managed-подключения - uint64_t conn_mgr_intermediaries[CONN_MGR_MAX_INTERMEDIARIES]; // посредники для INDIRECT + uint8_t alien; + uint8_t conn_mgr_type; + uint64_t conn_mgr_intermediaries[CONN_MGR_MAX_INTERMEDIARIES]; uint8_t conn_mgr_intermediariy_count; - struct NODE_CONNECTIVITY connectivity; // состояние связности (локальное) + struct NODE_CONNECTIVITY connectivity; struct ETCP_SOCKET* best_socket; - struct NODEINFO node; // Всегда в конце структуры - динамически расширяемый блок }; -/** - * @brief Создаёт/обновляет nodeinfo для собственного узла - */ -int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp); - -/** - * @brief Получает указатель на массив IPv4-подсетей узла (без malloc/копирования). - */ -int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets); - -/** - * @brief Получает указатель на массив IPv6-подсетей узла (без malloc/копирования). - */ -int get_node_v6_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SUBNET **out_subnets); +// ======================================================================= +// API +// ======================================================================= -/** - * @brief Получает указатель на массив метаданных IPv4-сокетов узла. - */ -int get_node_v4_sockets_meta(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SOCKET_META **out_meta); +struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id); -/** - * @brief Получает указатель на плоский список IPv4-адресов узла. - */ -int get_node_v4_addrs(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_ADDR **out_addrs); +void nodeinfo_ref(struct NODEINFO* ni); +void nodeinfo_unref(struct NODEINFO* ni); +void nodeinfo_free_lists(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq); +int nodeinfo_dyn_size(const struct NODEINFO_MSG* msg); -/** - * @brief Получает указатель на массив метаданных IPv6-сокетов узла. - */ -int get_node_v6_sockets_meta(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SOCKET_META **out_meta); +// convenience accessors +static inline const struct NI_IPV4_SOCKET_META* ni_v4_sock_meta(const struct NODEINFO* ni) { return ni->v4_sock_meta; } +static inline const struct NI_IPV4_ADDR* ni_v4_addrs(const struct NODEINFO* ni) { return ni->v4_addrs; } +static inline const struct NI_IPV6_SOCKET_META* ni_v6_sock_meta(const struct NODEINFO* ni) { return ni->v6_sock_meta; } +static inline const struct NI_IPV6_ADDR* ni_v6_addrs(const struct NODEINFO* ni) { return ni->v6_addrs; } +static inline const struct NI_IPV4_SUBNET* ni_v4_subnets(const struct NODEINFO_ROUTES* r) { return r ? r->v4_subnets : NULL; } +static inline const struct NI_IPV6_SUBNET* ni_v6_subnets(const struct NODEINFO_ROUTES* r) { return r ? r->v6_subnets : NULL; } -/** - * @brief Получает указатель на плоский список IPv6-адресов узла. - */ -int get_node_v6_addrs(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_ADDR **out_addrs); +int nodeinfo_serialize(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq, uint8_t* out, size_t out_max); +int nodeinfo_deserialize(struct ROUTE_BGP* bgp, const uint8_t* data, size_t len, struct NODEINFO** out_ni, struct NODEINFO_ROUTES** out_routes, + struct NODEINFO_TRANZIT_NODE** out_tranzit, uint8_t* out_tranzit_count, uint64_t** out_hop_list, uint8_t* out_hop_count); -struct NODEINFO_Q* nodeinfo_find_by_id(struct ROUTE_BGP* bgp, uint64_t node_id); +int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BGP* bgp); void route_node_dump_all(struct ROUTE_BGP* bgp); int route_node_format_all(struct ROUTE_BGP* bgp, char* buf, size_t buf_size); diff --git a/src/route_node_lmdb.c b/src/route_node_lmdb.c index 2134e46c..8e394ddb 100644 --- a/src/route_node_lmdb.c +++ b/src/route_node_lmdb.c @@ -11,140 +11,56 @@ int route_node_lmdb_init(struct ROUTE_BGP* bgp, const char* db_path) { if (!bgp || !db_path || !db_path[0]) return -1; - int rc = mdb_env_create(&bgp->nodeinfo_env); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_create failed: %s", mdb_strerror(rc)); - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_create failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_env_set_mapsize(bgp->nodeinfo_env, NODEINFO_DB_MAPSIZE); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_mapsize failed: %s", mdb_strerror(rc)); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_mapsize failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_env_set_maxdbs(bgp->nodeinfo_env, 2); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_maxdbs failed: %s", mdb_strerror(rc)); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_set_maxdbs failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_env_open(bgp->nodeinfo_env, db_path, 0, 0644); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_open(%s) failed: %s", db_path, mdb_strerror(rc)); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - - MDB_txn* txn = NULL; - rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_begin failed: %s", mdb_strerror(rc)); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_env_open(%s) failed: %s", db_path, mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } + MDB_txn* txn = NULL; rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_begin failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_dbi_open(txn, "nodeinfo", MDB_CREATE, &bgp->nodeinfo_dbi); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_dbi_open(nodeinfo) failed: %s", mdb_strerror(rc)); - mdb_txn_abort(txn); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_dbi_open(nodeinfo) failed: %s", mdb_strerror(rc)); mdb_txn_abort(txn); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } rc = mdb_txn_commit(txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_commit failed: %s", mdb_strerror(rc)); - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_txn_commit failed: %s", mdb_strerror(rc)); mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; return -1; } DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database opened: %s", db_path); return 0; } void route_node_lmdb_destroy(struct ROUTE_BGP* bgp) { if (!bgp) return; - if (bgp->nodeinfo_env) { - mdb_env_close(bgp->nodeinfo_env); - bgp->nodeinfo_env = NULL; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database closed"); - } + if (bgp->nodeinfo_env) { mdb_env_close(bgp->nodeinfo_env); bgp->nodeinfo_env = NULL; DEBUG_INFO(DEBUG_CATEGORY_BGP, "LMDB nodeinfo database closed"); } } int route_node_lmdb_put(struct ROUTE_BGP* bgp, struct NODEINFO_Q* nq) { - if (!bgp || !bgp->nodeinfo_env || !nq) return -1; - - int dyn_size = nodeinfo_dyn_size(&nq->node); - size_t val_size = sizeof(struct NODEINFO) + dyn_size; + if (!bgp || !bgp->nodeinfo_env || !nq || !nq->node) return -1; + uint8_t buf[8192]; + int ser_len = nodeinfo_serialize(bgp, nq, buf, sizeof(buf)); + if (ser_len < 0) return -1; MDB_val key, data; - key.mv_size = 8; - key.mv_data = &nq->node.node_id; - - data.mv_size = val_size; - data.mv_data = (void*)&nq->node; - - MDB_txn* txn = NULL; - int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_begin failed: %s", mdb_strerror(rc)); - return -1; - } + key.mv_size = 8; key.mv_data = &nq->node->node_id; + data.mv_size = (size_t)ser_len; data.mv_data = buf; + MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_begin failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_put(txn, bgp->nodeinfo_dbi, &key, &data, 0); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_put node %016llx failed: %s", - (unsigned long long)nq->node.node_id, mdb_strerror(rc)); - mdb_txn_abort(txn); - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_put node %016llx failed: %s", (unsigned long long)nq->node->node_id, mdb_strerror(rc)); mdb_txn_abort(txn); return -1; } rc = mdb_txn_commit(txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_commit failed: %s", mdb_strerror(rc)); - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB put mdb_txn_commit failed: %s", mdb_strerror(rc)); return -1; } return 0; } int route_node_lmdb_del(struct ROUTE_BGP* bgp, uint64_t node_id) { if (!bgp || !bgp->nodeinfo_env) return -1; - - MDB_val key; - key.mv_size = 8; - key.mv_data = &node_id; - - MDB_txn* txn = NULL; - int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_begin failed: %s", mdb_strerror(rc)); - return -1; - } - + MDB_val key; key.mv_size = 8; key.mv_data = &node_id; + MDB_txn* txn = NULL; int rc = mdb_txn_begin(bgp->nodeinfo_env, NULL, 0, &txn); + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_begin failed: %s", mdb_strerror(rc)); return -1; } rc = mdb_del(txn, bgp->nodeinfo_dbi, &key, NULL); - if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_del node %016llx failed: %s", - (unsigned long long)node_id, mdb_strerror(rc)); - mdb_txn_abort(txn); - return -1; - } - + if (rc != MDB_SUCCESS && rc != MDB_NOTFOUND) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB mdb_del node %016llx failed: %s", (unsigned long long)node_id, mdb_strerror(rc)); mdb_txn_abort(txn); return -1; } rc = mdb_txn_commit(txn); - if (rc != MDB_SUCCESS) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_commit failed: %s", mdb_strerror(rc)); - return -1; - } - + if (rc != MDB_SUCCESS) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "LMDB del mdb_txn_commit failed: %s", mdb_strerror(rc)); return -1; } return 0; } diff --git a/src/routing.c b/src/routing.c index 0cfe2e80..09de357d 100644 --- a/src/routing.c +++ b/src/routing.c @@ -139,12 +139,12 @@ void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry, uint64_t } struct NODEINFO_Q* nq = route->v_node_info; - if (!nq || nq->node.hop_count == 0) { + if (!nq || !nq->node || nq->hop_count == 0) { DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "Local route to %s", ip_to_str(&addr, AF_INET).str); } else { DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to node %016llx dst=%s", - ip_len, (unsigned long long)nq->node.node_id, ip_to_str(&addr, AF_INET).str); - int send_err = etcp_route_send(instance, nq->node.node_id, entry, 1); + ip_len, (unsigned long long)nq->node->node_id, ip_to_str(&addr, AF_INET).str); + int send_err = etcp_route_send(instance, nq->node->node_id, entry, 1); if (send_err != 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_route_send failed: dst=%s err=%d", ip_to_str(&addr, AF_INET).str, send_err); diff --git a/tests/test_bgp_route_exchange.c b/tests/test_bgp_route_exchange.c index 326a9906..beb9b8a3 100644 --- a/tests/test_bgp_route_exchange.c +++ b/tests/test_bgp_route_exchange.c @@ -215,7 +215,7 @@ static int check_learned_route(struct UTUN_INSTANCE* inst, uint32_t network, uin for (size_t i = 0; i < inst->rt->count; i++) { struct ROUTE_ENTRY* e = &inst->rt->entries[i]; if (e->network == network && e->prefix_length == prefix_len && - e->v_node_info && e->v_node_info->node.node_id == expected_be) return 1; + e->v_node_info && e->v_node_info->node->node_id == expected_be) return 1; } return 0; } diff --git a/tests/test_bgp_triangle.c b/tests/test_bgp_triangle.c index 7609dbfd..c36c51e1 100644 --- a/tests/test_bgp_triangle.c +++ b/tests/test_bgp_triangle.c @@ -156,7 +156,7 @@ static int route_count_for_node(struct UTUN_INSTANCE* inst, uint64_t node_id) { int cnt = 0; for (size_t i = 0; i < inst->rt->count; i++) if (inst->rt->entries[i].v_node_info && - inst->rt->entries[i].v_node_info->node.node_id == expected_be) cnt++; + inst->rt->entries[i].v_node_info->node->node_id == expected_be) cnt++; return cnt; } diff --git a/tests/test_etcp_connect.c b/tests/test_etcp_connect.c index 0bee3e51..b5b2c02b 100644 --- a/tests/test_etcp_connect.c +++ b/tests/test_etcp_connect.c @@ -66,24 +66,17 @@ static void connect_ccb(void* a, struct ETCP_CONN* conn, int type) { cb_type = t /* ----- helper: create minimal NODEINFO_Q with 1 v4 addr ----- */ static struct NODEINFO_Q* mknode(uint64_t nid, const uint8_t pubkey[32], uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) { - size_t extra = sizeof(struct NODEINFO_IPV4_SOCKET_META) + sizeof(struct NODEINFO_IPV4_ADDR); - size_t data_sz = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + extra; - struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(data_sz); - if (!nq) return NULL; - - struct NODEINFO* ni = &nq->node; - ni->node_id = nid; ni->ver = 0; + struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q)); + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; } + ni->ref_count = 1; ni->node_id = nid; ni->ver = 0; memcpy(ni->public_key, pubkey, SC_PUBKEY_SIZE); - ni->local_v4_sockets = 1; - ni->local_v4_addrs = 1; - - uint8_t* dyn = (uint8_t*)(ni + 1); - struct NODEINFO_IPV4_SOCKET_META* meta = (struct NODEINFO_IPV4_SOCKET_META*)dyn; - meta->id = 0; meta->config_type = CFG_SERVER_TYPE_PUBLIC; meta->nat_type = NAT_TYPE_UNKNOWN; - dyn += sizeof(struct NODEINFO_IPV4_SOCKET_META); - struct NODEINFO_IPV4_ADDR* addr = (struct NODEINFO_IPV4_ADDR*)dyn; - addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; - addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; + nq->ll.size = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry); + nq->node = ni; nq->hash_node_id = nid; + struct NI_IPV4_SOCKET_META* sm = u_calloc(1, sizeof(struct NI_IPV4_SOCKET_META)); + if (sm) { sm->id = 0; sm->config_type = CFG_SERVER_TYPE_PUBLIC; sm->nat_type = NAT_TYPE_UNKNOWN; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; } + struct NI_IPV4_ADDR* addr = u_calloc(1, sizeof(struct NI_IPV4_ADDR)); + if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; } return nq; } diff --git a/tests/test_etcp_router_reconnect.c b/tests/test_etcp_router_reconnect.c index 4db3c2d6..23ea2e2e 100644 --- a/tests/test_etcp_router_reconnect.c +++ b/tests/test_etcp_router_reconnect.c @@ -80,22 +80,16 @@ static void gen_payload(uint32_t seq, uint8_t* buf, int len) { static struct NODEINFO_Q* mknode(uint64_t nid, const uint8_t pubkey[32], uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port) { - size_t extra = sizeof(struct NODEINFO_IPV4_SOCKET_META) + sizeof(struct NODEINFO_IPV4_ADDR); - size_t data_sz = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry) + extra; - struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(data_sz); - if (!nq) return NULL; - struct NODEINFO* ni = &nq->node; - ni->node_id = nid; ni->ver = 0; + struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q)); + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; } + ni->ref_count = 1; ni->node_id = nid; ni->ver = 0; memcpy(ni->public_key, pubkey, SC_PUBKEY_SIZE); - ni->local_v4_sockets = 1; - ni->local_v4_addrs = 1; - uint8_t* dyn = (uint8_t*)(ni + 1); - struct NODEINFO_IPV4_SOCKET_META* meta = (struct NODEINFO_IPV4_SOCKET_META*)dyn; - meta->id = 0; meta->config_type = CFG_SERVER_TYPE_PUBLIC; meta->nat_type = NAT_TYPE_UNKNOWN; - dyn += sizeof(struct NODEINFO_IPV4_SOCKET_META); - struct NODEINFO_IPV4_ADDR* addr = (struct NODEINFO_IPV4_ADDR*)dyn; - addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; - addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; + nq->node = ni; nq->hash_node_id = nid; + struct NI_IPV4_SOCKET_META* sm = u_calloc(1, sizeof(struct NI_IPV4_SOCKET_META)); + if (sm) { sm->id = 0; sm->config_type = CFG_SERVER_TYPE_PUBLIC; sm->nat_type = NAT_TYPE_UNKNOWN; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; } + struct NI_IPV4_ADDR* addr = u_calloc(1, sizeof(struct NI_IPV4_ADDR)); + if (addr) { addr->addr[0] = a; addr->addr[1] = b; addr->addr[2] = c; addr->addr[3] = d; addr->port = port; addr->type = ADDR_TYPE_INTERFACE; addr->socket_id = 0; addr->next = ni->v4_addrs; ni->v4_addrs = addr; } return nq; } diff --git a/tests/test_etcp_router_unit.c b/tests/test_etcp_router_unit.c index 3c9769a5..2f332ffe 100644 --- a/tests/test_etcp_router_unit.c +++ b/tests/test_etcp_router_unit.c @@ -144,16 +144,18 @@ static void setup_bgp_for_sign_test(struct UTUN_INSTANCE* inst, int with_ed25519 if (!bgp) { printf(" setup_bgp: u_calloc failed\n"); return; } bgp->instance = inst; bgp->nodes = queue_new(inst->ua, BGP_NODES_HASH_SIZE, - offsetof(struct NODEINFO_Q, node.node_id) - sizeof(struct ll_entry), 8, "bgp_nodes_test"); + offsetof(struct NODEINFO_Q, hash_node_id) - sizeof(struct ll_entry), 8, "bgp_nodes_test"); if (!bgp->nodes) { printf(" setup_bgp: queue_new failed\n"); u_free(bgp); return; } inst->bgp = bgp; - size_t dsize = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry); - struct NODEINFO_Q* nq = (struct NODEINFO_Q*)queue_entry_new(dsize); - if (!nq) { printf(" setup_bgp: queue_entry_new failed\n"); return; } - memset(&nq->node, 0, sizeof(nq->node)); - nq->node.node_id = SIGNER_NODE; - if (with_ed25519_key) memcpy(nq->node.ed25519_public_key, g_sign_ed25519_pubkey, SC_PUBKEY_SIZE); + struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q)); + if (!nq) { printf(" setup_bgp: nq alloc failed\n"); return; } + nq->ll.size = sizeof(struct NODEINFO_Q) - sizeof(struct ll_entry); + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!ni) { printf(" setup_bgp: ni alloc failed\n"); u_free(nq); return; } + ni->ref_count = 1; ni->node_id = SIGNER_NODE; + if (with_ed25519_key) memcpy(ni->ed25519_public_key, g_sign_ed25519_pubkey, SC_PUBKEY_SIZE); + nq->node = ni; nq->hash_node_id = ni->node_id; queue_data_put_with_index(bgp->nodes, &nq->ll); } diff --git a/tests/test_ipv6_sockets.c b/tests/test_ipv6_sockets.c index 05b8deaf..5e5d1eb3 100644 --- a/tests/test_ipv6_sockets.c +++ b/tests/test_ipv6_sockets.c @@ -136,119 +136,74 @@ static int is_connection_established(struct UTUN_INSTANCE* inst) { static int verify_ipv6_local_nodeinfo(const char* name, struct UTUN_INSTANCE* inst, int expect_socks, int expect_addrs, int expect_subnets) { - if (!inst || !inst->bgp || !inst->bgp->local_node) { + if (!inst || !inst->bgp || !inst->bgp->local_node || !inst->bgp->local_node->node) { printf("FAIL [%s]: no bgp/local_node\n", name); return 0; } - struct NODEINFO* ni = &inst->bgp->local_node->node; + struct NODEINFO* ni = inst->bgp->local_node->node; struct ETCP_SOCKET* es = inst->etcp_sockets; - // Check socket family int v6_sock_found = 0; - while (es) { - if (es->local_addr.ss_family == AF_INET6) { v6_sock_found = 1; break; } - es = es->next; - } + while (es) { if (es->local_addr.ss_family == AF_INET6) { v6_sock_found = 1; break; } es = es->next; } if (!v6_sock_found) { printf("FAIL [%s]: no AF_INET6 socket\n", name); return 0; } printf("PASS [%s]: AF_INET6 socket exists\n", name); - // Check nodeinfo counts - if ((int)ni->local_v6_sockets != expect_socks) { - printf("FAIL [%s]: local_v6_sockets=%d expected=%d\n", name, ni->local_v6_sockets, expect_socks); return 0; - } - printf("PASS [%s]: local_v6_sockets=%d\n", name, ni->local_v6_sockets); + int v6s = ni_list_count((struct _ni_head*)ni->v6_sock_meta); + if (v6s != expect_socks) { printf("FAIL [%s]: v6_socks=%d expected=%d\n", name, v6s, expect_socks); return 0; } + printf("PASS [%s]: v6_sockets=%d\n", name, v6s); - if ((int)ni->local_v6_addrs != expect_addrs) { - printf("FAIL [%s]: local_v6_addrs=%d expected=%d\n", name, ni->local_v6_addrs, expect_addrs); return 0; - } - printf("PASS [%s]: local_v6_addrs=%d\n", name, ni->local_v6_addrs); + int v6a = ni_list_count((struct _ni_head*)ni->v6_addrs); + if (v6a != expect_addrs) { printf("FAIL [%s]: v6_addrs=%d expected=%d\n", name, v6a, expect_addrs); return 0; } + printf("PASS [%s]: v6_addrs=%d\n", name, v6a); - if ((int)ni->local_v6_subnets != expect_subnets) { - printf("FAIL [%s]: local_v6_subnets=%d expected=%d\n", name, ni->local_v6_subnets, expect_subnets); return 0; - } - printf("PASS [%s]: local_v6_subnets=%d\n", name, ni->local_v6_subnets); - - // Verify socket meta - const struct NODEINFO_IPV6_SOCKET_META* meta; - int mc = get_node_v6_sockets_meta(inst->bgp->local_node, &meta); - if (mc != expect_socks || !meta) { printf("FAIL [%s]: v6 sockets meta retrieval failed\n", name); return 0; } - for (int i = 0; i < mc; i++) { - if (meta[i].config_type != CFG_SERVER_TYPE_PUBLIC) { - printf("FAIL [%s]: v6 socket meta[%d] config_type=%d expected=%d\n", name, i, meta[i].config_type, CFG_SERVER_TYPE_PUBLIC); return 0; - } - printf("PASS [%s]: v6 socket meta[%d] id=%d config=%d nat=%d\n", name, i, meta[i].id, meta[i].config_type, meta[i].nat_type); - } + int v6sub = inst->bgp->local_node->routes ? ni_list_count((struct _ni_head*)inst->bgp->local_node->routes->v6_subnets) : 0; + if (v6sub != expect_subnets) { printf("FAIL [%s]: v6_subnets=%d expected=%d\n", name, v6sub, expect_subnets); return 0; } + printf("PASS [%s]: v6_subnets=%d\n", name, v6sub); - // Verify IPv6 addresses - const struct NODEINFO_IPV6_ADDR* addrs; - int ac = get_node_v6_addrs(inst->bgp->local_node, &addrs); - if (ac != expect_addrs || !addrs) { printf("FAIL [%s]: v6 addrs retrieval failed\n", name); return 0; } - for (int i = 0; i < ac; i++) { - if (addrs[i].port == 0) { printf("FAIL [%s]: v6 addr port=0\n", name); return 0; } - if (addrs[i].type != ADDR_TYPE_INTERFACE) { - printf("FAIL [%s]: v6 addr[%d] type=%d expected=%d(INTERFACE)\n", name, i, addrs[i].type, ADDR_TYPE_INTERFACE); return 0; - } - if (addrs[i].type != ADDR_TYPE_INTERFACE) { - printf("FAIL [%s]: v6 addr[%d] type=%d expected=%d(INTERFACE)\n", name, i, addrs[i].type, ADDR_TYPE_INTERFACE); return 0; - } - printf("PASS [%s]: v6 addr[%d] port=%d type=%d socket_id=%d\n", name, i, addrs[i].port, addrs[i].type, addrs[i].socket_id); + { const struct NI_IPV6_SOCKET_META* m = ni->v6_sock_meta; int i = 0; + while (m) { + if (m->config_type != CFG_SERVER_TYPE_PUBLIC) { printf("FAIL [%s]: v6 socket meta[%d] config_type=%d expected=%d\n", name, i, m->config_type, CFG_SERVER_TYPE_PUBLIC); return 0; } + printf("PASS [%s]: v6 socket meta[%d] id=%d config=%d nat=%d\n", name, i, m->id, m->config_type, m->nat_type); + i++; m = m->next; + } } - - // Verify IPv6 subnets - if (expect_subnets > 0) { - const struct NODEINFO_IPV6_SUBNET* subs; - const uint8_t* dyn_start = (const uint8_t*)ni + sizeof(struct NODEINFO); - const uint8_t* p = dyn_start + ni->node_name_len; - p += ni->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET_META); - p += ni->local_v4_addrs * sizeof(struct NODEINFO_IPV4_ADDR); - p += ni->local_v6_sockets * sizeof(struct NODEINFO_IPV6_SOCKET_META); - p += ni->local_v6_addrs * sizeof(struct NODEINFO_IPV6_ADDR); - p += ni->local_v4_subnets * sizeof(struct NODEINFO_IPV4_SUBNET); - subs = (const struct NODEINFO_IPV6_SUBNET*)p; - uint8_t expected_sub[16] = {0x20,0x01,0x0d,0xb8,0x00,0x01,0,0,0,0,0,0,0,0,0,0}; - if (memcmp(subs[0].addr, expected_sub, 16) != 0) { - printf("FAIL [%s]: v6 subnet != 2001:db8:1::/48\n", name); return 0; - } - if (subs[0].prefix_length != 48) { - printf("FAIL [%s]: v6 subnet prefix=%d expected=48\n", name, subs[0].prefix_length); return 0; + { const struct NI_IPV6_ADDR* a = ni->v6_addrs; int i = 0; + while (a) { + if (a->port == 0) { printf("FAIL [%s]: v6 addr port=0\n", name); return 0; } + if (a->type != ADDR_TYPE_INTERFACE) { printf("FAIL [%s]: v6 addr[%d] type=%d expected=%d(INTERFACE)\n", name, i, a->type, ADDR_TYPE_INTERFACE); return 0; } + printf("PASS [%s]: v6 addr[%d] port=%d type=%d socket_id=%d\n", name, i, a->port, a->type, a->socket_id); + i++; a = a->next; + } + } + if (expect_subnets > 0 && inst->bgp->local_node->routes) { + const struct NI_IPV6_SUBNET* subs = inst->bgp->local_node->routes->v6_subnets; + if (subs) { + uint8_t expected_sub[16] = {0x20,0x01,0x0d,0xb8,0x00,0x01,0,0,0,0,0,0,0,0,0,0}; + if (memcmp(subs->addr, expected_sub, 16) != 0) { printf("FAIL [%s]: v6 subnet != 2001:db8:1::/48\n", name); return 0; } + if (subs->prefix_length != 48) { printf("FAIL [%s]: v6 subnet prefix=%d expected=48\n", name, subs->prefix_length); return 0; } + printf("PASS [%s]: v6 subnet 2001:db8:1::/48\n", name); } - printf("PASS [%s]: v6 subnet 2001:db8:1::/48\n", name); } - return 1; } static int verify_remote_v6_nodeinfo(const char* name, struct UTUN_INSTANCE* inst, uint64_t peer_node_id) { - if (!inst || !inst->bgp) { - printf("FAIL [%s]: no bgp\n", name); - return 0; - } + if (!inst || !inst->bgp) { printf("FAIL [%s]: no bgp\n", name); return 0; } struct NODEINFO_Q* nq = nodeinfo_find_by_id(inst->bgp, peer_node_id); - if (!nq) { - printf("FAIL [%s]: remote node %016llx not found\n", name, (unsigned long long)peer_node_id); - return 0; - } + if (!nq || !nq->node) { printf("FAIL [%s]: remote node %016llx not found\n", name, (unsigned long long)peer_node_id); return 0; } printf("PASS [%s]: remote node %016llx found\n", name, (unsigned long long)peer_node_id); - if (nq->node.local_v6_sockets == 0) { - printf("FAIL [%s]: remote node has no v6 sockets\n", name); - return 0; - } - printf("PASS [%s]: remote node v6_sockets=%d\n", name, nq->node.local_v6_sockets); + if (!nq->node->v6_sock_meta) { printf("FAIL [%s]: remote node has no v6 sockets\n", name); return 0; } + printf("PASS [%s]: remote node v6_sockets=%d\n", name, ni_list_count((struct _ni_head*)nq->node->v6_sock_meta)); - if (nq->node.local_v6_addrs == 0) { - printf("FAIL [%s]: remote node has no v6 addrs\n", name); - return 0; - } - printf("PASS [%s]: remote node v6_addrs=%d\n", name, nq->node.local_v6_addrs); + if (!nq->node->v6_addrs) { printf("FAIL [%s]: remote node has no v6 addrs\n", name); return 0; } + printf("PASS [%s]: remote node v6_addrs=%d\n", name, ni_list_count((struct _ni_head*)nq->node->v6_addrs)); - const struct NODEINFO_IPV6_ADDR* addrs; - int ac = get_node_v6_addrs(nq, &addrs); - if (ac > 0 && addrs) { + const struct NI_IPV6_ADDR* a = nq->node->v6_addrs; + if (a) { uint8_t loopback[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; - if (memcmp(addrs[0].addr, loopback, 16) != 0) - { printf("FAIL [%s]: remote v6 addr not ::1\n", name); return 0; } - printf("PASS [%s]: remote v6 addr verified ::1 port=%d\n", name, addrs[0].port); + if (memcmp(a->addr, loopback, 16) != 0) { printf("FAIL [%s]: remote v6 addr not ::1\n", name); return 0; } + printf("PASS [%s]: remote v6 addr verified ::1 port=%d\n", name, a->port); } return 1; } diff --git a/tests/test_nat_detection.c b/tests/test_nat_detection.c index a5490caf..11875f75 100644 --- a/tests/test_nat_detection.c +++ b/tests/test_nat_detection.c @@ -361,45 +361,32 @@ int main(void) { } // Verify local_node socket update on C1 (received NAT_INFO updated nodeinfo) - if (inst_c1->bgp && inst_c1->bgp->local_node) { - const struct NODEINFO_IPV4_SOCKET_META* meta = NULL; - int meta_count = get_node_v4_sockets_meta(inst_c1->bgp->local_node, &meta); + if (inst_c1->bgp && inst_c1->bgp->local_node && inst_c1->bgp->local_node->node) { int found = 0; - for (int i = 0; i < meta_count; i++) { - if (meta[i].id == sock_c1->sock_id) { - if (meta[i].nat_type != NAT_VERIFIED_EIM) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: local_node socket meta not updated on C1: nat_type=%u expected=%u", - meta[i].nat_type, NAT_VERIFIED_EIM); + for (const struct NI_IPV4_SOCKET_META* m = inst_c1->bgp->local_node->node->v4_sock_meta; m; m = m->next) { + if (m->id == sock_c1->sock_id) { + if (m->nat_type != NAT_VERIFIED_EIM) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: local_node socket meta not updated on C1: nat_type=%u expected=%u", m->nat_type, NAT_VERIFIED_EIM); goto cleanup; } - found = 1; - break; + found = 1; break; } } - if (!found) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: socket not found in local_node meta on C1"); - goto cleanup; - } + if (!found) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: socket not found in local_node meta on C1"); goto cleanup; } // Verify NAT addr in flat address list - const struct NODEINFO_IPV4_ADDR* addrs = NULL; - int addr_count = get_node_v4_addrs(inst_c1->bgp->local_node, &addrs); int nat_found = 0; - for (int i = 0; i < addr_count; i++) { - if (addrs[i].type == ADDR_TYPE_NAT && addrs[i].socket_id == sock_c1->sock_id) { - uint32_t addr_ip; memcpy(&addr_ip, addrs[i].addr, 4); - if (addr_ip != link_sc1->nat_ip || addrs[i].port != link_sc1->nat_port) { + for (const struct NI_IPV4_ADDR* a = inst_c1->bgp->local_node->node->v4_addrs; a; a = a->next) { + if (a->type == ADDR_TYPE_NAT && a->socket_id == sock_c1->sock_id) { + uint32_t addr_ip; memcpy(&addr_ip, a->addr, 4); + if (addr_ip != link_sc1->nat_ip || a->port != link_sc1->nat_port) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: NAT addr mismatch in local_node: addr=%08x nat_ip=%08x port=%u nat_port=%u", - addr_ip, link_sc1->nat_ip, addrs[i].port, link_sc1->nat_port); + addr_ip, link_sc1->nat_ip, a->port, link_sc1->nat_port); goto cleanup; } - nat_found = 1; - break; + nat_found = 1; break; } } - if (!nat_found) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: NAT addr not found in local_node flat addr list on C1"); - goto cleanup; - } + if (!nat_found) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: NAT addr not found in local_node flat addr list on C1"); goto cleanup; } DEBUG_INFO(DEBUG_CATEGORY_BGP, "local_node meta+addr check PASSED on C1"); } @@ -409,14 +396,9 @@ int main(void) { int c2_verified_nat = 0; while (!test_timed_out && bgp_wait_cycles < 500) { struct NODEINFO_Q* node_c1_on_c2 = inst_c2->bgp ? nodeinfo_find_by_id(inst_c2->bgp, NODE_ID_C1) : NULL; - if (node_c1_on_c2) { - const struct NODEINFO_IPV4_SOCKET_META* meta = NULL; - int meta_count = get_node_v4_sockets_meta(node_c1_on_c2, &meta); - for (int i = 0; i < meta_count; i++) { - if (meta[i].nat_type == NAT_VERIFIED_EIM) { - c2_verified_nat = 1; - break; - } + if (node_c1_on_c2 && node_c1_on_c2->node) { + for (const struct NI_IPV4_SOCKET_META* m = node_c1_on_c2->node->v4_sock_meta; m; m = m->next) { + if (m->nat_type == NAT_VERIFIED_EIM) { c2_verified_nat = 1; break; } } if (c2_verified_nat) break; } @@ -450,7 +432,7 @@ int main(void) { int ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, target_ip_net, link_sc1->nat_port, 3, 10, 200, 3000, nat_ping_resp_cb, NULL, - node_c1->node.public_key); + node_c1->node->public_key); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr failed: %d", ret); goto cleanup; @@ -498,7 +480,7 @@ int main(void) { ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, target_ip_net, link_sc1->nat_port, 3, 10, 200, 3000, nat_ping_resp_cb, NULL, - node_c1->node.public_key); + node_c1->node->public_key); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr (no pubkey) failed: %d", ret); goto cleanup; diff --git a/tests/test_route6_lib.c b/tests/test_route6_lib.c index 279c7058..9c2b6069 100644 --- a/tests/test_route6_lib.c +++ b/tests/test_route6_lib.c @@ -22,20 +22,36 @@ static int tests_run = 0; static struct NODEINFO_Q *make_node(uint64_t node_id, const uint8_t addrs[][16], const uint8_t *plens, int N) { - size_t dyn = N * sizeof(struct NODEINFO_IPV6_SUBNET); - struct NODEINFO_Q *nq = u_calloc(1, sizeof(*nq) + dyn); - nq->node.node_id = node_id; - nq->node.local_v6_subnets = (uint8_t)N; - struct NODEINFO_IPV6_SUBNET *subs = - (struct NODEINFO_IPV6_SUBNET *)((uint8_t *)&nq->node + sizeof(struct NODEINFO)); - for (int i = 0; i < N; i++) { - memcpy(subs[i].addr, addrs[i], 16); - subs[i].prefix_length = plens[i]; + struct NODEINFO_Q *nq = u_calloc(1, sizeof(*nq)); + struct NODEINFO *ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!nq || !ni) { u_free(nq); u_free(ni); return NULL; } + ni->ref_count = 1; ni->node_id = node_id; + nq->node = ni; nq->hash_node_id = node_id; + if (N > 0) { + struct NODEINFO_ROUTES *r = u_calloc(1, sizeof(struct NODEINFO_ROUTES)); + nq->routes = r; + struct NI_IPV6_SUBNET *head = NULL; + for (int i = N-1; i >= 0; i--) { + struct NI_IPV6_SUBNET *s = u_calloc(1, sizeof(struct NI_IPV6_SUBNET)); + memcpy(s->addr, addrs[i], 16); s->prefix_length = plens[i]; + s->next = head; head = s; + } + r->v6_subnets = head; } return nq; } -static void free_node(struct NODEINFO_Q *nq) { u_free(nq); } +static void free_node(struct NODEINFO_Q *nq) { + if (nq) { + if (nq->routes) { + struct NI_IPV6_SUBNET *s = nq->routes->v6_subnets; + while (s) { struct NI_IPV6_SUBNET *next = s->next; u_free(s); s = next; } + u_free(nq->routes); + } + if (nq->node) u_free(nq->node); + u_free(nq); + } +} static void make_key(uint8_t out[17], const uint8_t addr[16]) { out[0] = 17; memcpy(out + 1, addr, 16); @@ -317,7 +333,7 @@ static void test_stress(void) { if (rand() % 10 < 6 && n_created > 0) { // delete random active node int idx = rand() % n_created; - uint64_t nid = nodes[idx]->node.node_id; + uint64_t nid = nodes[idx]->node->node_id; route6_delete(t, nodes[idx]); // mark all routes of this node inactive for (int j = 0; j < nsr; j++) { diff --git a/tests/test_route_lib.c b/tests/test_route_lib.c index e7602354..7f77aa57 100644 --- a/tests/test_route_lib.c +++ b/tests/test_route_lib.c @@ -40,34 +40,35 @@ struct UTUN_INSTANCE { struct ROUTE_BGP* bgp; }; -/* Helper to create test NODEINFO_Q with subnet in dynamic section */ +/* Helper to create test NODEINFO_Q with subnet in linked list */ static struct NODEINFO_Q* create_test_node(uint64_t node_id, uint8_t ver, uint32_t subnet_net, uint8_t prefix) { - /* Allocate fixed + dynamic for 1 subnet (no name, no sockets) */ - size_t dyn_size = sizeof(struct NODEINFO_IPV4_SUBNET); - struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn_size); + struct NODEINFO_Q* nq = u_calloc(1, sizeof(struct NODEINFO_Q)); if (!nq) return NULL; - nq->node.node_id = htobe64(node_id); - nq->node.ver = ver; - nq->node.node_name_len = 0; - nq->node.local_v4_sockets = 0; - nq->node.local_v6_sockets = 0; - nq->node.local_v4_subnets = 1; - nq->node.local_v6_subnets = 0; - nq->node.tranzit_nodes = 0; - nq->node.hop_count = 0; + struct NODEINFO* ni = u_calloc(1, sizeof(struct NODEINFO)); + if (!ni) { u_free(nq); return NULL; } + ni->ref_count = 1; + ni->node_id = htobe64(node_id); + ni->ver = ver; + nq->node = ni; + nq->hash_node_id = ni->node_id; + nq->hop_count = 0; nq->paths = queue_new(NULL, 16, 0, 0, "test_paths"); - /* Fill subnet after fixed header (after name_len=0, sockets=0) */ - uint8_t *dyn = (uint8_t *)&nq->node + sizeof(struct NODEINFO); - struct NODEINFO_IPV4_SUBNET *sn = (struct NODEINFO_IPV4_SUBNET *)dyn; - uint32_t net = htonl(subnet_net); - memcpy(sn->addr, &net, 4); - sn->prefix_length = prefix; + struct NODEINFO_ROUTES* r = u_calloc(1, sizeof(struct NODEINFO_ROUTES)); + if (r) { + struct NI_IPV4_SUBNET* sn = u_calloc(1, sizeof(struct NI_IPV4_SUBNET)); + uint32_t net = htonl(subnet_net); + memcpy(sn->addr, &net, 4); sn->prefix_length = prefix; + r->v4_subnets = sn; + nq->routes = r; + } return nq; } static void free_test_node(struct NODEINFO_Q* nq) { if (nq) { if (nq->paths) queue_free(nq->paths); + if (nq->routes) { u_free(nq->routes->v4_subnets); u_free(nq->routes); } + if (nq->node) { u_free(nq->node->node_name); u_free(nq->node); } u_free(nq); } } diff --git a/tests/test_route_ping.c b/tests/test_route_ping.c index be34c968..3c3e6e37 100644 --- a/tests/test_route_ping.c +++ b/tests/test_route_ping.c @@ -272,12 +272,11 @@ int main(void) { uint32_t target_ip = 0; uint16_t target_port = 0; struct NODEINFO_Q* nq = inst_b->bgp ? nodeinfo_find_by_id(inst_b->bgp, NODE_ID_C) : NULL; - if (nq) { - const struct NODEINFO_IPV4_ADDR* addrs; - int sc = get_node_v4_addrs(nq, &addrs); - if (sc > 0) { - memcpy(&target_ip, addrs[0].addr, 4); /* network byte order */ - target_port = addrs[0].port; /* host byte order */ + if (nq && nq->node) { + const struct NI_IPV4_ADDR* a = nq->node->v4_addrs; + if (a) { + memcpy(&target_ip, a->addr, 4); + target_port = a->port; } } if (target_ip == 0 || target_port == 0) { @@ -294,7 +293,7 @@ int main(void) { 200, // timeout_ms 5000,// wait_timeout_ms ping_resp_cb, NULL, - nq ? nq->node.public_key : NULL); + nq ? nq->node->public_key : NULL); if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr failed: %d", ret); goto cleanup;