2013-07-27 5 views
2

Я пишу программу C для туннелирования с помощью Linux tun device. Я создаю устройство tun, устанавливая его владельца, группу и постоянство, используя вызовы ioctl(). Однако для выполнения туннелирования мне нужно установить ip-адрес на устройство и установить связь. Я сейчас делаю это с помощьюКак установить IP-адрес устройства tun и установить ссылку UP на C-программу

# ip addr add 
# ip link set 

Я хочу, чтобы установить адрес, маску и установить связь, как up. Есть ли способ сделать это через программу без вызова команды ip?

Я пробовал использовать команду ioctl() с командой SIOCSIFADDR, но она не работает для устройства tun и работает для eth0. Я получаю ошибку ioctl() - Invalid argument.

Ниже приводится код, который работает на eth0, а не на что-то вроде tun2:

280 void setip (int fd) { 
281 
282  struct ifreq ifr; 
283  struct sockaddr_in addr; 
284  int stat; 
285  
286  memset(&ifr, 0, sizeof(ifr)); 
287  memset(&addr, 0, sizeof(addr)); 
288  strncpy(ifr.ifr_name, in.dev.device, IFNAMSIZ);  // device name: eg. tun2 
289  
290  addr.sin_family = AF_INET; 
291  stat = inet_pton(addr.sin_family, in.dev.ip_addr, &addr.sin_addr); // ip string 
292  if (stat == 0) 
293   raise_error("inet_pton() - invalid ip"); 
294  if (stat == -1) 
295   raise_error("inet_pton() - invalid family"); 
296   
297  if (stat == 1); 
298  else 
299   raise_error("inet_pton()"); 
300   
301  ifr.ifr_addr = *(struct sockaddr *) &addr; 
302  /* This is just to test if address conversion happened properly */ 
303  char buff[BUFF_SIZE]; 
304  char * foo; 
305  foo = inet_ntop(AF_INET, &addr.sin_addr, buff, BUFF_SIZE); 
306  if (foo == NULL) 
307   raise_error("inet_ntop()"); 
308  else 
309   printf("main = %s, addr = %s\n",in.dev.ip_addr, buff); 
310   
311  if (ioctl(fd, SIOCSIFADDR, (caddr_t) &ifr) == -1) 
312   raise_error("ioctl() - SIOCSIFADDR"); 
313 } 

Я искал методы, чтобы сделать это для TUN устройств, но не могли найти. Все сообщения, которые я получил, использовали ip или ifconfig или что-то в этом роде.

Есть ли способ сделать это через программу? Спасибо

+0

правильный путь для достижения этой цели является использование IOCTL. Как указано в документации http://man7.org/linux/man-pages/man7/netdevice.7.html, IOCTL позволяет настраивать любые устройства сокетов. Вы уверены, что этот код работает с eth0? Как вы создаете устройство tun0? Извините, я не смог проверить код. –

+0

Привет, спасибо за ответ. Я тестировал код для eth0, и он работал нормально. (Я сделал некоторые изменения в функции, поскольку это часть более крупной программы). Мне пришлось добавить вызов 'socket()', чтобы получить файловый дескриптор 'fd'. 'Fd' в этом коде является дескриптором дескриптора устройства. Я использую почти тот же код, что и на этой странице [Linux documentation page] (https://www.kernel.org/doc/Documentation/networking/tuntap.txt). Раздел 3.1 для создания устройства tun. – aoak

ответ

1

Я понял проблему. В случае eth0, я использую дескриптор сокета как аргумент ioctl(), в случае устройства tun, я использую дескриптор устройства устройства. Я также создал сокет в случае устройства tun и работал ioctl(). Ниже приводится код:

280 void setip (int fd) { 
281 
282  struct ifreq ifr; 
283  struct sockaddr_in addr; 
284  int stat, s; 
285 
286  memset(&ifr, 0, sizeof(ifr)); 
287  memset(&addr, 0, sizeof(addr)); 
288  strncpy(ifr.ifr_name, in.dev.device, IFNAMSIZ); 
289 
290  addr.sin_family = AF_INET; 
291  s = socket(addr.sin_family, SOCK_DGRAM, 0); 
292  stat = inet_pton(addr.sin_family, in.dev.ip_addr, &addr.sin_addr); 
293  if (stat == 0) 
294   raise_error("inet_pton() - invalid ip"); 
295  if (stat == -1) 
296   raise_error("inet_pton() - invalid family"); 
297  
298  if (stat == 1); 
299  else 
300   raise_error("inet_pton()"); 
301  
302  ifr.ifr_addr = *(struct sockaddr *) &addr; 
303  /* This is just to test if address conversion happened properly */ 
304  char buff[BUFF_SIZE]; 
305  char * foo; 
306  foo = inet_ntop(AF_INET, &addr.sin_addr, buff, BUFF_SIZE); 
307  if (foo == NULL) 
308   raise_error("inet_ntop()"); 
309  else 
310   printf("main = %s, addr = %s\n",in.dev.ip_addr, buff); 
311 
312  //if (ioctl(fd, SIOCSIFADDR, (caddr_t) &ifr) == -1) 
313  if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) == -1) 
314   raise_error("ioctl() - SIOCSIFADDR"); 
315 } 

Спасибо Giuseppe Pes за ответ :)

+0

Эта программа использует тот же метод с вами: http: //linuxgazette.net/149/misc/melinte/udptun.c – xjdrew