diff --git a/src/tun_freebsd.c b/src/tun_freebsd.c index 61babfe2..2108820e 100644 --- a/src/tun_freebsd.c +++ b/src/tun_freebsd.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -56,9 +57,43 @@ static int parse_ip_mask(const char *ip_addr, struct in_addr *ip, struct in_addr netmask->s_addr = htonl(mask); return 0; } -// Create TUN device using cloning device /dev/tun +// Create TUN device. +// Если имя оканчивается на цифру (tun4, tun0) — создаём интерфейс с этим именем +// через SIOCIFCREATE. Иначе (tun или пусто) — клонирующее устройство /dev/tun, +// ядро само выдаёт следующий свободный номер. static int create_tun_device(char *ifname, size_t ifname_len) { int fd; + size_t name_len = ifname ? strlen(ifname) : 0; + int manual = name_len > 0 && isdigit((unsigned char)ifname[name_len - 1]); + + if (manual) { + int sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create ioctl socket: %s", strerror(errno)); + return -1; + } + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; + if (ioctl(sock, SIOCIFCREATE, &ifr) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_TUN, "SIOCIFCREATE failed for %s: %s", ifname, strerror(errno)); + close(sock); + return -1; + } + close(sock); + + char dev_path[IFNAMSIZ + 6]; + snprintf(dev_path, sizeof(dev_path), "/dev/%s", ifname); + fd = open(dev_path, O_RDWR); + if (fd < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to open %s: %s", dev_path, strerror(errno)); + return -1; + } + DEBUG_INFO(DEBUG_CATEGORY_TUN, "Opened %s (fd=%d)", dev_path, fd); + return fd; + } + // Открываем cloning device /dev/tun fd = open("/dev/tun", O_RDWR); if (fd < 0) { @@ -245,7 +280,7 @@ static int tun_set_mtu(const char *ifname, int mtu) { } // Platform-specific initialization for FreeBSD int tun_platform_init(struct tun_if* tun, const char* ifname, const char* ip_str, int mtu) { - (void)ifname; // FreeBSD выделяет имя автоматически через cloning device + (void)ifname; // имя уже в tun->ifname, передаётся в create_tun_device // Create TUN device tun->fd = create_tun_device(tun->ifname, sizeof(tun->ifname)); if (tun->fd < 0) {