Как взаимодействовать с драйвером Tun Linux
Вопрос
Мне трудно разобраться в этой проблеме — я пытаюсь написать программу, которая будет взаимодействовать с драйвером туннеля Linux.На самом базовом уровне я просто хочу создать приложение, способное передавать данные через сетевой туннель.Однако я совершенно не понимаю, как правильно настроить драйвер туннеля, чтобы добиться этого.
Я занимаюсь разработкой на Ubuntu 9.04, и у меня загружен модуль ядра драйвера туннеля.
Существует устройство /dev/net/tun
, однако нет /dev/tunX
устройства.Я не могу создать эти устройства, используя ifconfig
- всякий раз, когда я бегаю /sbin/ifconfig tun0 up
, например, я получаю следующую ошибку:
тун0:ОШИБКА при получении флагов интерфейса:Нет такого устройства.
Если я попытаюсь посмотреть на /dev/net/tun
устройстве появляется следующая ошибка:
кот:/dev/net/tun:Дескриптор файла в плохом состоянии.
Попытка открыть /dev/tunX
через небольшую программу, по сути, простую
tun_fd = open( "/dev/tun0", O_RDWR )
возвращает -1:приложение работает от имени пользователя root и по-прежнему не может открыть это туннельное устройство.Есть возможность открыть /dev/net/tun
, однако это, похоже, не приводит к созданию нового /dev/tunX
устройство, которое будет использоваться вместо этого.
Итак, вкратце: как написать приложение, которое будет использовать драйвер туннеля Linux?Любая информация будет принята с благодарностью.
Спасибо;~ Роберт
Решение
Читать /usr/src/linux/Documentation/networking/tuntap.txt
.
Вы должны open
тот /dev/net/tun
устройство.Последующий ioctl
на открытом диске создаст tun0
(или как вы его назовете) сетевой интерфейс.Сетевые интерфейсы Linux не соответствуют ни одному /dev/*
устройство.
Другие советы
Нет /dev/tunX
файлы устройства.Вместо этого вы открываете /dev/net/tun
и настроить его через ioctl()
указать на tun0
.Чтобы показать основную процедуру, я создам интерфейс TUN с помощью инструмента командной строки. ip tun tap
а затем покажите код C для чтения с этого устройства TUN.Итак, чтобы создать интерфейс Tun через командную строку:
sudo ip tuntap add mode tun dev tun0
ip addr add 10.0.0.0/24 dev tun0 # give it an ip
ip link set dev tun0 up # bring the if up
ip route get 10.0.0.2 # check that packets to 10.0.0.x are going through tun0
ping 10.0.0.2 # leave this running in another shell to be able to see the effect of the next example
Теперь у нас есть tun0
созданный.Для чтения/записи пакетов на этот интерфейс из пользовательской программы необходимо взаимодействовать с /dev/net/tun
файл устройства с помощью ioctl()
.Вот пример, который будет читать пакеты, поступающие на tun0
интерфейс и распечатайте размер:
#include <fcntl.h> /* O_RDWR */
#include <string.h> /* memset(), memcpy() */
#include <stdio.h> /* perror(), printf(), fprintf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <sys/ioctl.h> /* ioctl() */
/* includes for struct ifreq, etc */
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_tun.h>
int tun_open(char *devname)
{
struct ifreq ifr;
int fd, err;
if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
perror("open /dev/net/tun");exit(1);
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN;
strncpy(ifr.ifr_name, devname, IFNAMSIZ); // devname = "tun0" or "tun1", etc
/* ioctl will use ifr.if_name as the name of TUN
* interface to open: "tun0", etc. */
if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
perror("ioctl TUNSETIFF");close(fd);exit(1);
}
/* After the ioctl call the fd is "connected" to tun device specified
* by devname ("tun0", "tun1", etc)*/
return fd;
}
int main(int argc, char *argv[])
{
int fd, nbytes;
char buf[1600];
fd = tun_open("tun0"); /* devname = ifr.if_name = "tun0" */
printf("Device tun0 opened\n");
while(1) {
nbytes = read(fd, buf, sizeof(buf));
printf("Read %d bytes from tun0\n", nbytes);
}
return 0;
}
Я наткнулся на хороший вводный урок по этому поводу
http://backreference.org/2010/03/26/tuntap-interface-tutorial/
Он поставляется с исходным архивом.
Это было в том же наборе результатов Google, что и этот вопрос.:-)