I am writing a C program for tunnelling using Linux tun device. I am creating a tun device, setting its owner, group and persistence using ioctl()
calls. However, for doing the tunnelling, I need to set ip address to the device and set the link up. I am currently doing this using
# ip addr add
# ip link set
I want to set the address, mask and set the link as up
. Is there any way to do it through the program without invoking ip
command?
I tried using ioctl()
with SIOCSIFADDR
command, but it doesn't work for tun device, and works for eth0
. I get the error ioctl() - Invalid argument
.
Following is the code which works on eth0
but not on something like 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 }
I searched for methods to do this for tun devices but could not find any. All the posts I got to use ip
or ifconfig
or something of the sort.
Is there any way to do this through the program? Thanks
I figured out the problem. In case of eth0
, I am using a socket descriptor as the argument to ioctl()
, in case of tun device, I am using tun device descriptor. I created a socket in case of tun device too and the ioctl()
worked. Following is the code:
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 }
Thanks Giuseppe Pes for your reply :)