8

I want to call ioctl from Rust. I know that I should use the nix crate, but how exactly? From the documentation it's not clear.

I have this C:

int tun_open(char *devname)
{
  struct ifreq ifr;
  int fd, err;

  if ( (fd = open("/dev/net/tun", O_RDWR)) == -1 ) {
       perror("open /dev/net/tun");exit(1);
  }
  memset(&ifr, 0, sizeof(ifr));
  ifr.ifr_flags = IFF_TUN;
  strncpy(ifr.ifr_name, devname, IFNAMSIZ);  

  /* ioctl will use if_name as the name of TUN 
   * interface to open: "tun0", etc. */
  if ( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) == -1 ) {
    perror("ioctl TUNSETIFF");close(fd);exit(1);
  }
  //..........

How would I do that same thing using the nix crate? There are no TUN* constants in the nix crate and it isn't clear how to use the ioctl macro.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
Jodooomi
  • 369
  • 5
  • 12
  • This seems like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) to me: instead of asking about specific ioctl use case you're asking how to use the `nix` crate. Still, it's worth mentioning that a similar ioctl use case seems to be covered at http://hermanradtke.com/2016/03/17/unions-rust-ffi.html. – ArtemGr Jan 05 '17 at 08:35
  • @ArtemGr The OP provided a short and simple snippet of C code and asked how to do the equivalent in Rust. How exactly is that an XY problem? – user4815162342 Jan 05 '17 at 09:25

1 Answers1

9

There is some example usage in rust-spidev. I will try to apply that to your code.

TUNSETIFF is defined as:

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

That would be this in Rust using nix:

const TUN_IOC_MAGIC: u8 = 'T' as u8;
const TUN_IOC_SET_IFF: u8 = 202;
ioctl!(write tun_set_iff with TUN_IOC_MAGIC, TUN_IOC_SET_IFF; u32);

The above macro will define the function, which you can call like this:

let err = unsafe { tun_set_iff(fd, ifr) }; // assuming ifr is an u32
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
wimh
  • 15,072
  • 6
  • 47
  • 98
  • why aren't they defined in "nix"? what does rust-spidev have to do with "nix"? – Jodooomi Jan 05 '17 at 11:15
  • 3
    @Jodooomi Here rust-spidev merely serves to demonstrate how to correctly use nix's `ioctl!` macro. Since `ioctl` is open-ended and inherently unsafe, it is impossible to provide a single definition that would work for all cases. Instead, `nix` provides the `ioctl!` macro as a *helper* to define functions that provide a safe (or at least convenient) interface to particular uses of `ioctl`. – user4815162342 Jan 05 '17 at 11:47
  • alright, but how does the author of rust-spidev know what those constants are? where can they be found? – Jodooomi Jan 07 '17 at 13:50
  • I mean, yes, the TUN.. constant is defined at "http://lxr.free-electrons.com", but what if I needed other constant, where would have to look for its definition in C? – Jodooomi Jan 07 '17 at 13:52
  • If you can find them in a C header file, it is probably the easiest. But somewhere they must be documented, you can try google to find it. (That's also how I found that definition of `TUNSETIFF`). You can also create a rust crate containing all definitions, so others can use you crate if they need something. – wimh Jan 07 '17 at 13:57
  • Would it be possible to get this example updated with the latest version of nix? it seems ioctl! doesn't exist anymore – Cecile Jan 07 '19 at 08:32
  • 1
    @Cecile It looks like `ioctl!` is split into several functions like `ioctl_read!`, `ioctl_write_ptr!`, `ioctl_write_buf!`, and so on :https://github.com/nix-rust/nix/blob/master/src/sys/ioctl/mod.rs. So depending on the usage of the ioctl, you would need a different name. It looks like this example would be `ioctl_write_int!`. But it is probably better to read the documentation in mod.rs which explains it better then I do. – wimh Jan 07 '19 at 10:19