Browse Source

freebsd: уникальный dst-адрес per-interface (tunN -> 192.0.2.(N+1))

proxy
evgeny 1 week ago
parent
commit
4353daf913
  1. 29
      src/tun_freebsd.c

29
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

Loading…
Cancel
Save