nell 0.0.2

Linux netlink API access
Documentation
// Copyright (C) 2018 - Will Glozer. All rights reserved.

use std::mem::size_of;
use std::os::raw::c_int;
use ffi::*;
use ffi::netlink_family::*;
use sys::*;

pub fn set_link_fd(index: u32, fd: Option<u32>, flags: u32) -> Result<(), Error> {
    let sock = Socket::new(NETLINK_ROUTE)?;

    #[repr(C)]
    #[derive(Default, Debug)]
    struct Request {
        hdr: nlmsghdr,
        req: ifinfomsg,
        nla: nlattr,
        nlb: nlattr,
        fd:  c_int,
        nlc: nlattr,
        flg: u32,
    }

    let mut req = Request::default();
    req.hdr.nlmsg_type  = RTM_SETLINK;
    req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.req.ifi_family  = AF_UNSPEC;
    req.req.ifi_index   = index as i32;
    req.nla.nla_type    = IFLA_XDP | NLA_F_NESTED;
    req.nlb.nla_type    = IFLA_XDP_FD;
    req.fd              = fd.map(|fd| fd as i32).unwrap_or(-1);
    req.nlc.nla_type    = IFLA_XDP_FLAGS;
    req.flg             = flags;

    // FIXME: rename to netlink_align?
    req.hdr.nlmsg_len += nlmsg_align(size_of::<nlmsghdr>() as u32);
    req.hdr.nlmsg_len += nlmsg_align(size_of::<ifinfomsg>() as u32);
    req.nla.nla_len   += nlmsg_align(size_of::<nlattr>() as u32) as u16;
    req.nlb.nla_len   += nlmsg_align(size_of::<nlattr>() as u32) as u16;
    req.nlb.nla_len   += nlmsg_align(size_of::<c_int>() as u32)  as u16;
    req.nlc.nla_len   += nlmsg_align(size_of::<nlattr>() as u32) as u16;
    req.nlc.nla_len   += nlmsg_align(size_of::<u32>() as u32)    as u16;
    req.nla.nla_len   += req.nlb.nla_len;
    req.nla.nla_len   += req.nlc.nla_len;
    req.hdr.nlmsg_len += nlmsg_align(req.nla.nla_len as u32);

    sock.send(&mut [as_iovec(&mut req)]).unwrap();
    match sock.recv(skip) {
        Err(Error::Ack) => Ok(()),
        Err(err)        => Err(err),
        Ok(..)          => unreachable!(),
    }
}

fn skip(_: &(), _: Attrs) -> Result<(), Error> {
    Ok(())
}