use libc;
use std::io;
use std::mem::size_of;
use std::os::unix::io::RawFd;
#[repr(C)]
pub struct Address {
pub family: u16,
pub _pad: u16,
pub pid: u32,
pub groups: u32,
}
macro_rules! ccall {
( $x:expr ) => {{
let value = unsafe { $x };
if value < 0 {
return Err(io::Error::last_os_error());
}
value
}};
}
pub fn get_page_size() -> usize {
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
}
pub fn netlink_socket(service: i32) -> io::Result<RawFd> {
Ok(ccall!(libc::socket(
libc::AF_NETLINK,
libc::SOCK_RAW | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC,
service
)))
}
pub fn set_socket_option<T: Sized>(
socket: RawFd,
level: i32,
name: i32,
value: T,
) -> io::Result<()> {
let value_ptr: *const T = &value;
ccall!(libc::setsockopt(
socket,
level,
name,
value_ptr as *mut libc::c_void,
size_of::<T>() as u32
));
Ok(())
}
pub fn bind(socket: RawFd, address: &Address) -> io::Result<()> {
let addr_ptr: *const Address = address;
ccall!(libc::bind(
socket,
addr_ptr as *const libc::sockaddr,
size_of::<Address>() as u32
));
Ok(())
}
pub fn get_socket_address(socket: RawFd, address: &mut Address) -> io::Result<()> {
let addr_ptr = address as *mut Address as *mut libc::sockaddr;
let mut addr_len = size_of::<Address>() as libc::socklen_t;
let addr_len_ptr: *mut libc::socklen_t = &mut addr_len;
ccall!(libc::getsockname(socket, addr_ptr, addr_len_ptr));
Ok(())
}
pub fn send_message(socket: RawFd, header: &libc::msghdr, flags: i32) -> io::Result<usize> {
Ok(ccall!(libc::sendmsg(socket, header as *const libc::msghdr, flags)) as usize)
}
pub fn receive_message(socket: RawFd, header: &mut libc::msghdr) -> io::Result<usize> {
Ok(ccall!(libc::recvmsg(socket, header as *mut libc::msghdr, 0)) as usize)
}
pub fn send(socket: RawFd, data: &[u8], flags: i32) -> io::Result<usize> {
Ok(ccall!(libc::send(
socket,
data.as_ptr() as *const libc::c_void,
data.len(),
flags
)) as usize)
}