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.