Confusion on TUNSETIFF ioctl type

6.9k views Asked by At

I'm seeing conflicting definitions of the TUNSETIFF ioctl. If I look at linux/if_tun.h on my system, I see this line:

#define TUNSETIFF     _IOW('T', 202, int)

This indicates that the TUNSETIFF ioctl takes a pointer to an int. Also, if I print out the value of TUNSETIFF, I get 1074025674, which if I mask out the size bits indicates that this ioctl takes data with size 4 bytes.

But then when I look at the documentation around TUNSETIFF, I see instances of passing a pointer to a struct ifreq. For example in the official documentation:

#include <linux/if.h>
#include <linux/if_tun.h>

int tun_alloc(char *dev)
{
    struct ifreq ifr;
    int fd, err;

    if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
       return tun_alloc_old(dev);

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

    /* Flags: IFF_TUN   - TUN device (no Ethernet headers) 
     *        IFF_TAP   - TAP device  
     *
     *        IFF_NO_PI - Do not provide packet information  
     */ 
    ifr.ifr_flags = IFF_TUN; 
    if( *dev )
       strncpy(ifr.ifr_name, dev, IFNAMSIZ);

    if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
       close(fd);
       return err;
    }
    strcpy(dev, ifr.ifr_name);
    return fd;
}

So why is there this discrepancy? Is it just a mistake in the header file?

2

There are 2 answers

0
stark On

All ioctls take an argument whose meaning varies with the ioctl. In the case of this code it is a pointer to a user-space struct. Note that from the kernel's point of view this is just a word, not a pointer. User-space pointers are only used to copy data between the kernel and user space, and can't be dereferenced directly.

0
VOID 001 On

I got the same error when only include "if.h" & "if_tun.h"

When I include <sys/ioctl.h>it works and everything seems fine

hope this will help