2

I'm trying to convert a system() call I have in C that calls ip tuntap add ... to C code that doesn't rely on the system() call.

Basically, it's a problem that the tunnel adapter that I use the system("ip tuntap add ...") call to bring up is left there when my application is forcibly terminated.

I've been told I can use rtnetlink to achieve my goal. I'd like to convert the following line into C code that doesn't rely on the system() call. I believe if I use rtnetlink that the tunnel adapter I bring up will be destroyed by the kernel when my application is terminated, which is the main reason I want to do this.

This is my current line in C:

system("ip tuntap add dev tun1 mode tun");

If rtnetlink isn't how I would go about doing this, is there another method that would destroy the tunnel when my application is forcibly terminated?

Nathan F.
  • 3,250
  • 3
  • 35
  • 69
  • 1
    Right. What you're looking for is a non-persistent TUN adapter, which is the default when you're using the system calls. – Jonathon Reinhart Apr 01 '18 at 23:05
  • @JonathonReinhart but afaik that requires restarting the network service in order to purge it, correct? Which I can't do since everything needs to be done within the C code.. :3 – Nathan F. Apr 01 '18 at 23:06
  • No, you don't have to restart. Try out this example: http://www.cis.syr.edu/~wedu/seed/Labs/VPN/files/simpletun.c – Jonathon Reinhart Apr 01 '18 at 23:08
  • @JonathonReinhart I don't see `system()` being called anywhere in there? I see a `tun_alloc` function, but afaik that only gets the file descriptor for an active tunnel interface – Nathan F. Apr 01 '18 at 23:24
  • It can create a new tun device. Compile the code and play with it. – Jonathon Reinhart Apr 01 '18 at 23:35
  • Never mind, i was running that same function but after i created the tunnel :facepalm:. Thanks so much for the help, if you'd like you can submit this as an answer and I'll accept it :) – Nathan F. Apr 01 '18 at 23:35

1 Answers1

3

@Jonathon Reinhart answered this in the comments:

What you're looking for is a non-persistent TUN adapter. Instead of using

system("ip tuntap add dev tun1 mode tun");

The Function

Originally taken from simpletun.c, code added to answer to avoid potential issues with dead links in the future.

# Not certain that these are all of the imports you'll need,
# but i'm pretty sure it covers everything.

#include <net/if.h>
#include <linux/if_tun.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdio.h>

int tun_alloc(char *dev, int flags) {
  struct ifreq ifr;
  int fd, err;
  char *clonedev = "/dev/net/tun";

  if( (fd = open(clonedev , O_RDWR)) < 0 ) {
    perror("Opening /dev/net/tun");
    return fd;
  }

  memset(&ifr, 0, sizeof(ifr));

  ifr.ifr_flags = flags;

  if (*dev) {
    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
  }

  if( (err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0 ) {
    perror("ioctl(TUNSETIFF)");
    close(fd);
    return err;
  }

  strcpy(dev, ifr.ifr_name);

  return fd;
}

Calling It

int tun_fd = tun_alloc("tun1", IFF_TUN | IFF_NO_PI);

What's happening?

When it is called, this function will create the new tunnel if it doesn't exist and return the file descriptor for the tunnel. If it already exists, it will simply return the file descriptor for the tunnel.

When it creates the tunnel, if your process dies it will actively destroy the tunnel and any associated routes.

Nathan F.
  • 3,250
  • 3
  • 35
  • 69