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?
                        
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.