#include #include #include #include "../lib/ll_queue.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #include "utun_instance.h" #include "etcp.h" #include "config_parser.h" #include "route_node.h" #include "route_bgp.h" #include "etcp_debug.h" static const uint8_t* node_dyn_start(const struct NODEINFO* info) { return (const uint8_t*)info + sizeof(struct NODEINFO); } static const uint8_t* skip_name(const uint8_t* p, uint8_t name_len) { return p + name_len; } 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 const uint8_t* skip_v4_addrs(const uint8_t* p, uint8_t count) { return p + count * sizeof(struct NODEINFO_IPV4_ADDR); } 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 const uint8_t* skip_v6_addrs(const uint8_t* p, uint8_t count) { return p + count * sizeof(struct NODEINFO_IPV6_ADDR); } static const uint8_t* skip_v4_subnets(const uint8_t* p, uint8_t count) { return p + count * sizeof(struct NODEINFO_IPV4_SUBNET); } 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; } 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; } 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; } 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 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; } 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; } 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; } size_t name_len = 0; 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; struct ETCP_SOCKET* e_sock = instance->etcp_sockets; while (e_sock) { if (e_sock->local_addr.ss_family == AF_INET) { sock_count++; addr_count++; // INTERFACE 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 (e_sock->nat_type == NAT_VERIFIED_DIRECT || (e_sock->type == CFG_SERVER_TYPE_PUBLIC && 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) } e_sock = e_sock->next; } 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 (changed) { if (bgp->local_node) u_free(bgp->local_node); bgp->local_node = u_calloc(1, sizeof(struct NODEINFO_Q) + dyn); 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); 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->local_addr.ss_family == AF_INET) { meta[midx].id = e_sock->sock_id; meta[midx].type = e_sock->nat_type; midx++; } e_sock = e_sock->next; } dp += sock_count * sizeof(struct NODEINFO_IPV4_SOCKET_META); // 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->local_addr.ss_family == AF_INET) { 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; 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; aidx++; } } if (e_sock->nat_type == NAT_VERIFIED_DIRECT || (e_sock->type == CFG_SERVER_TYPE_PUBLIC && 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; aidx++; } } e_sock = e_sock->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->local_addr.ss_family == AF_INET6) { meta6[m6idx].id = e_sock->sock_id; meta6[m6idx].type = e_sock->nat_type; m6idx++; } e_sock = e_sock->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->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; a6idx++; } e_sock = e_sock->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; } 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); } else { bgp->local_node->last_ver = bgp->local_node->node.ver; } return vc; }