Hi all,
I'm pretty new to rust, I'm trying to open a an interface as promiscuos and in order to do that I'm trying to use ioctl to read and the write the flags of the interface. I'm just "traslating" some simple C code to rust
This is the C code
int setpromisc(int fd, int promisc, char* ifname, int set){
int res;
struct ifreq ifreq;
if(!promisc)
return 0;
memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifr_name, ifname, strlen(ifname));
//read flags of the interface
res = ioctl(fd, SIOCGIFFLAGS, &ifreq);
if (res==-1){
perror("Error on ioctl:SIOCGIFFLAGS");
return -1;
}
ifreq.ifr_flags = set ? ifreq.ifr_flags | IFF_PROMISC : ifreq.ifr_flags ^ IFF_PROMISC;
//set interface flags
res = ioctl(fd, SIOCSIFFLAGS, &ifreq);
if (res==-1){
perror("Error on ioctl:SIOCGIFFLAGS");
return -1;
}
return res;
}
The rust code is
//man 7 netdevice
#[repr(C)]
pub struct ifmap {
mem_start: libc::c_ulong,
mem_end: libc::c_ulong,
base_addr: libc::c_uchar,
irq: libc::c_uchar,
dma: libc::c_uchar,
port: libc::c_uchar,
}
// struct ifmap {
// unsigned long mem_start;
// unsigned long mem_end;
// unsigned short base_addr;
// unsigned char irq;
// unsigned char dma;
// unsigned char port;
// };
//man 7 netdevice
#[repr(C)]
pub struct ifreq{
pub ifr_name: [libc::c_uchar; 16],
ifr_addr: libc::sockaddr,
ifr_dstaddr: libc::sockaddr,
ifr_broadaddr: libc::sockaddr,
ifr_netmask: libc::sockaddr,
ifr_hwaddr: libc::sockaddr,
ifr_flags: libc::c_short,
ifr_ifindex: libc::c_int,
ifr_metric: libc::c_int,
ifr_mtu: libc::c_int,
ifr_map: ifmap,
ifr_slave: [libc::c_uchar; 16],
ifr_newname: [libc::c_uchar; 16],
ifr_data: *const libc::c_uchar,
}
// struct ifreq {
// char ifr_name[IFNAMSIZ]; /* Interface name */
// union {
// struct sockaddr ifr_addr;
// struct sockaddr ifr_dstaddr;
// struct sockaddr ifr_broadaddr;
// struct sockaddr ifr_netmask;
// struct sockaddr ifr_hwaddr;
// short ifr_flags;
// int ifr_ifindex;
// int ifr_metric;
// int ifr_mtu;
// struct ifmap ifr_map;
// char ifr_slave[IFNAMSIZ];
// char ifr_newname[IFNAMSIZ];
// char *ifr_data;
// };
// };
fn set_promisc(fd: &i32, ifname: &String, set: bool) -> libc::c_int {
// Enable promiscuous mode
unsafe {
let res;
let mut ifr: ifreq = mem::zeroed();
let sb = ifname.as_bytes();
//make a copy to an array of size 16
let mut arr : [u8;16] = [0;16];
let mut i = 0;
for c in sb {
arr[i] = *c;
i = i+1;
}
arr[i] = '\0' as u8;
ifr.ifr_name = arr;
//read flags of the interface
res = libc::ioctl(*fd, libc::SIOCGIFFLAGS,&ifr);
if res == -1{
return -1 as i32;
}
println!("Read FLAGS = {}", ifr.ifr_flags);
if set {
ifr.ifr_flags = ifr.ifr_flags | (libc::IFF_PROMISC as libc::c_short);
println!("Should set the flag! NEW FLAGS = {}", ifr.ifr_flags);
} else {
ifr.ifr_flags = ifr.ifr_flags ^ (libc::IFF_PROMISC as libc::c_short);
println!("Should set the remove the flag! NEW FLAGS = {}", ifr.ifr_flags);
}
return libc::ioctl(*fd, libc::SIOCSIFFLAGS, &ifr);
}
}
As you can see I have added the missing structure and I'm passing the pointer of the mutable structure to ioctl, withou getting any result
This is an example of the output
Read FLAGS = 0
Should set the flag! NEW FLAGS = 256
And with strace
I can see
....
ioctl(6, SIOCGIFFLAGS, {ifr_name="h2", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
....
ioctl(6, SIOCSIFFLAGS, {ifr_name="h2", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
...
So it is actually reading the modes, then are not stored in the strucure used for setting the flags
Any suggestion?