From 4353daf9135f7d57858bf26a799f6ae8f94e20b8 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 25 Sep 2026 20:16:39 +0300 Subject: [PATCH] =?UTF-8?q?freebsd:=20=D1=83=D0=BD=D0=B8=D0=BA=D0=B0=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D0=B9=20dst-=D0=B0=D0=B4=D1=80=D0=B5=D1=81?= =?UTF-8?q?=20per-interface=20(tunN=20->=20192.0.2.(N+1))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tun_freebsd.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/tun_freebsd.c b/src/tun_freebsd.c index c456eb32..6c0a526d 100644 --- a/src/tun_freebsd.c +++ b/src/tun_freebsd.c @@ -149,6 +149,16 @@ static int tun_set_head(int fd, const char *ifname) { DEBUG_INFO(DEBUG_CATEGORY_TUN, "Set TUNSIFHEAD on %s", ifname); return 0; } +// Сформировать dst-адрес point-to-point по номеру интерфейса: tunN -> 192.0.2.(N+1) +static void tun_dst_addr(const char *ifname, char *dst, size_t dst_len) { + const char *p = ifname + strlen(ifname); + while (p > ifname && isdigit((unsigned char)p[-1])) p--; + unsigned long n = strtoul(p, NULL, 10); + if (p == ifname + strlen(ifname) || n > 253) { + n = 253; // нет цифр в имени (не должно быть на FreeBSD) или переполнение диапазона + } + snprintf(dst, dst_len, "192.0.2.%lu", n + 1); +} // Set IP address on TUN interface using ifconfig // FreeBSD требует отдельно IP и netmask для TUN // For point-to-point, require destination address, set to same as local for /32 @@ -157,6 +167,9 @@ static int tun_set_ip(const char *ifname, const char *ip_addr) { errno = EINVAL; return -1; } + // Уникальный dst-адрес на каждый интерфейс: tunN -> 192.0.2.(N+1) + char dst_str[INET_ADDRSTRLEN]; + tun_dst_addr(ifname, dst_str, sizeof(dst_str)); // Парсим IP и CIDR char ip_str[INET_ADDRSTRLEN] = {0}; int cidr = -1; @@ -193,13 +206,13 @@ static int tun_set_ip(const char *ifname, const char *ip_addr) { } // Формируем команду ifconfig с destination address (same as local for /32) char cmd[512]; - snprintf(cmd, sizeof(cmd), "ifconfig %s inet %s 192.0.2.1 netmask %s up", - ifname, ip_str, mask_str); + snprintf(cmd, sizeof(cmd), "ifconfig %s inet %s %s netmask %s up", + ifname, ip_str, dst_str, mask_str); DEBUG_INFO(DEBUG_CATEGORY_TUN, "Executing: %s", cmd); int ret = system(cmd); if (ret != 0) { - DEBUG_ERROR(DEBUG_CATEGORY_TUN, "ifconfig failed for %s with IP %s netmask %s", - ifname, ip_str, mask_str); + DEBUG_ERROR(DEBUG_CATEGORY_TUN, "ifconfig failed for %s with IP %s dst %s netmask %s", + ifname, ip_str, dst_str, mask_str); // Fallback: пробуем через ioctl напрямую DEBUG_INFO(DEBUG_CATEGORY_TUN, "Trying ioctl fallback..."); int sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -223,12 +236,12 @@ static int tun_set_ip(const char *ifname, const char *ip_addr) { close(sock); return -1; } - // Устанавливаем destination address (same as local) + // Устанавливаем destination address (уникальный на каждый интерфейс) memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); struct sockaddr_in *sin_dst = (struct sockaddr_in *)&ifr.ifr_dstaddr; sin_dst->sin_family = AF_INET; - inet_pton(AF_INET, "192.0.2.1", &sin_dst->sin_addr); + inet_pton(AF_INET, dst_str, &sin_dst->sin_addr); if (ioctl(sock, SIOCSIFDSTADDR, &ifr) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_TUN, "SIOCSIFDSTADDR failed: %s", strerror(errno)); close(sock); @@ -260,10 +273,10 @@ static int tun_set_ip(const char *ifname, const char *ip_addr) { return -1; } close(sock); - DEBUG_INFO(DEBUG_CATEGORY_TUN, "Successfully configured %s via ioctl", ifname); + DEBUG_INFO(DEBUG_CATEGORY_TUN, "Successfully configured %s (ip=%s dst=%s) via ioctl", ifname, ip_str, dst_str); return 0; } - DEBUG_INFO(DEBUG_CATEGORY_TUN, "Set IP %s/%d on %s", ip_str, cidr, ifname); + DEBUG_INFO(DEBUG_CATEGORY_TUN, "Set IP %s/%d dst %s on %s", ip_str, cidr, dst_str, ifname); return 0; } // Set MTU on TUN interface