From f9417f06b4165664793943c270c2ab003022fe44 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sun, 9 Aug 2026 17:51:33 +0300 Subject: [PATCH] =?UTF-8?q?BSD=20route=20sockaddr=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D1=81=D0=B8=D0=BD=D0=B3:=20addr/plen/gw/dev=20=D0=B2=20INFO;?= =?UTF-8?q?=20=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D1=81=D0=BF=D0=B0=D0=BC=20?= =?UTF-8?q?v6=5Fsend/v6=5Frecv?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/transport_layer/etcp_connections.c | 15 ------ src/transport_layer/socket_monitor.c | 69 ++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/transport_layer/etcp_connections.c b/src/transport_layer/etcp_connections.c index 2fd8ae5c..9d02adc5 100644 --- a/src/transport_layer/etcp_connections.c +++ b/src/transport_layer/etcp_connections.c @@ -1208,11 +1208,6 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { struct sockaddr_storage* addr=&dgram->link->remote_addr; socklen_t addr_len = (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); - if (addr->ss_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)addr; - DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "[v6_send] fd=%d dst=%-39s scope=%u", dgram->link->conn->fd, - sockaddr_storage_to_str(addr).str, sin6->sin6_scope_id); - } ssize_t sent = etcp_udp_send(dgram->link, dgram->link->conn->fd, enc_buf, enc_buf_len + dgram->noencrypt_len, (struct sockaddr*)addr, addr_len); @@ -1811,16 +1806,6 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { socklen_t addr_len=sizeof(addr); memset(&addr, 0, sizeof(addr)); ssize_t recv_len = socket_recvfrom(sock, data, PACKET_DATA_SIZE, (struct sockaddr*)&addr, &addr_len); - if (recv_len > 0 && addr.ss_family == AF_INET6) { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&addr; - DEBUG_DEBUG(DEBUG_CATEGORY_SOCKET, "[v6_recv] sock=%s fd=%d src=[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d len=%zd scope=%u", - e_sock->name, (int)sock, - sin6->sin6_addr.s6_addr[0],sin6->sin6_addr.s6_addr[1],sin6->sin6_addr.s6_addr[2],sin6->sin6_addr.s6_addr[3], - sin6->sin6_addr.s6_addr[4],sin6->sin6_addr.s6_addr[5],sin6->sin6_addr.s6_addr[6],sin6->sin6_addr.s6_addr[7], - sin6->sin6_addr.s6_addr[8],sin6->sin6_addr.s6_addr[9],sin6->sin6_addr.s6_addr[10],sin6->sin6_addr.s6_addr[11], - sin6->sin6_addr.s6_addr[12],sin6->sin6_addr.s6_addr[13],sin6->sin6_addr.s6_addr[14],sin6->sin6_addr.s6_addr[15], - (int)ntohs(sin6->sin6_port), recv_len, sin6->sin6_scope_id); - } if (recv_len <= 0) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "recvfrom failed, error=%zd, sock_err=%d", recv_len, socket_get_error()); diff --git a/src/transport_layer/socket_monitor.c b/src/transport_layer/socket_monitor.c index c3b44b5b..1f6cc5c7 100644 --- a/src/transport_layer/socket_monitor.c +++ b/src/transport_layer/socket_monitor.c @@ -227,6 +227,59 @@ static void socket_monitor_read_cb(int fd, void* arg) { /* ===== FreeBSD: AF_ROUTE routing socket ===== */ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +static int sockaddr_to_plen(const struct sockaddr* sa) { + if (!sa || sa->sa_len == 0) return 0; + switch (sa->sa_family) { + case AF_INET: { + uint32_t m = ntohl(((const struct sockaddr_in*)sa)->sin_addr.s_addr); + int bits = 0; + while (bits < 32 && (m & 0x80000000)) { bits++; m <<= 1; } + return bits; + } + case AF_INET6: { + const uint8_t* a = ((const struct sockaddr_in6*)sa)->sin6_addr.s6_addr; + int bits = 0; + for (int i = 0; i < 16; i++) { + if (a[i] == 0xff) { bits += 8; continue; } + uint8_t b = a[i]; + while (b & 0x80) { bits++; b <<= 1; } + break; + } + return bits; + } + default: return 0; + } +} + +static void sa_to_str(const struct sockaddr* sa, char* buf, size_t bufsz) { + if (!sa || sa->sa_len == 0) { snprintf(buf, bufsz, "?"); return; } + switch (sa->sa_family) { + case AF_INET: + inet_ntop(AF_INET, &((const struct sockaddr_in*)sa)->sin_addr, buf, (socklen_t)bufsz); break; + case AF_INET6: + inet_ntop(AF_INET6, &((const struct sockaddr_in6*)sa)->sin6_addr, buf, (socklen_t)bufsz); break; + default: snprintf(buf, bufsz, "?%d", sa->sa_family); break; + } +} + +/* walk RTA sockaddrs after rtm header, extract addr, gw, plen */ +static void bsd_parse_rtm(struct rt_msghdr* rtm, int mask, char* addr, size_t as, char* gw, size_t gs, int* plen) { + struct sockaddr* sa = (struct sockaddr*)(rtm + 1); + addr[0] = gw[0] = '\0'; *plen = 0; + for (int i = 0, b = 1; i <= RTAX_MAX && mask; i++, b <<= 1) { + if (!(mask & b)) continue; + int sl = sa->sa_len ? (int)RT_ROUNDUP(sa->sa_len) : (int)sizeof(struct sockaddr); + switch (i) { + case RTAX_DST: sa_to_str(sa, addr, as); break; + case RTAX_IFA: sa_to_str(sa, addr, as); break; + case RTAX_GATEWAY: sa_to_str(sa, gw, gs); break; + case RTAX_NETMASK: *plen = sockaddr_to_plen(sa); break; + } + mask &= ~b; + sa = (struct sockaddr*)((char*)sa + sl); + } +} + static void socket_monitor_bsd_read_cb(int fd, void* arg) { struct SOCKET_MONITOR* sm = (struct SOCKET_MONITOR*)arg; char buf[8192]; @@ -267,17 +320,23 @@ static void socket_monitor_bsd_read_cb(int fd, void* arg) { case RTM_DELADDR: { sm->addr_changes++; struct ifa_msghdr* ifam = (struct ifa_msghdr*)rtm; - char ifname[IFNAMSIZ]; + char ifname[IFNAMSIZ], addr[INET6_ADDRSTRLEN]; int plen; if (!if_indextoname(ifam->ifam_index, ifname)) snprintf(ifname, sizeof(ifname), "?"); - DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "addr %s: %s (idx=%u)", - rtm->rtm_type == RTM_NEWADDR ? "NEW" : "DEL", ifname, ifam->ifam_index); + bsd_parse_rtm(rtm, ifam->ifam_addrs, addr, sizeof(addr), NULL, 0, &plen); + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "addr %s: %s/%d on %s (idx=%u)", + rtm->rtm_type == RTM_NEWADDR ? "NEW" : "DEL", addr, plen, ifname, ifam->ifam_index); struct ETCP_SOCKET* es = sm->instance->etcp_sockets; while (es) { socket_monitor_fire_one(sm, es); es = es->next; } } break; case RTM_ADD: - case RTM_DELETE: + case RTM_DELETE: { sm->route_changes++; - DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "route %s:", rtm->rtm_type == RTM_ADD ? "ADD" : "DELETE"); + char ifname[IFNAMSIZ], dst[INET6_ADDRSTRLEN], gw[INET6_ADDRSTRLEN]; int plen; + if (!if_indextoname(rtm->rtm_index, ifname)) snprintf(ifname, sizeof(ifname), "?"); + bsd_parse_rtm(rtm, rtm->rtm_addrs, dst, sizeof(dst), gw, sizeof(gw), &plen); + DEBUG_INFO(DEBUG_CATEGORY_SOCKET, "route %s: %s/%d gw=%s dev=%s (idx=%u)", + rtm->rtm_type == RTM_ADD ? "ADD" : "DELETE", + dst[0] ? dst : "default", plen, gw, ifname, rtm->rtm_index); { struct ETCP_SOCKET* es = sm->instance->etcp_sockets; while (es) {