|
|
|
|
@ -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
|
|
|
|
|
|