lx 0.4.0

A no_std crate to use Linux system calls
Documentation
use super::{
    SockAddr,
    AF_NETLINK,
};

// Link layer types.
pub const ARPHRD_ETHER: u16 = 1;
pub const ARPHRD_NONE: u16 = 0xFFFE;

// Interface attributes.
pub const IFA_ADDRESS: u16 = 1;
pub const IFA_LOCAL: u16 = 2;
pub const IFA_BROADCAST: u16 = 4;

// Interface flags.
pub const IFF_UP: u32 = 0x1;

// Interface link attributes.
pub const IFLA_UNSPEC: u16 = 0;
pub const IFLA_ADDRESS: u16 = 1;
pub const IFLA_BROADCAST: u16 = 2;
pub const IFLA_IFNAME: u16 = 3;
pub const IFLA_MTU: u16 = 4;
pub const IFLA_LINK: u16 = 5;
pub const IFLA_QDISC: u16 = 6;
pub const IFLA_STATS: u16 = 7;
pub const IFLA_COST: u16 = 8;
pub const IFLA_PRIORITY: u16 = 9;
pub const IFLA_MASTER: u16 = 10;
pub const IFLA_WIRELESS: u16 = 11;
pub const IFLA_PROTINFO: u16 = 12;
pub const IFLA_TXQLEN: u16 = 13;
pub const IFLA_MAP: u16 = 14;
pub const IFLA_WEIGHT: u16 = 15;
pub const IFLA_OPERSTATE: u16 = 16;
pub const IFLA_LINKMODE: u16 = 17;
pub const IFLA_LINKINFO: u16 = 18;
pub const IFLA_NET_NS_PID: u16 = 19;
pub const IFLA_IFALIAS: u16 = 20;
pub const IFLA_NUM_VF: u16 = 21;
pub const IFLA_VFINFO_LIST: u16 = 22;
pub const IFLA_STATS64: u16 = 23;
pub const IFLA_VF_PORTS: u16 = 24;
pub const IFLA_PORT_SELF: u16 = 25;
pub const IFLA_AF_SPEC: u16 = 26;
pub const IFLA_GROUP: u16 = 27;
pub const IFLA_NET_NS_FD: u16 = 28;
pub const IFLA_EXT_MASK: u16 = 29;
pub const IFLA_PROMISCUITY: u16 = 30;
pub const IFLA_NUM_TX_QUEUES: u16 = 31;
pub const IFLA_NUM_RX_QUEUES: u16 = 32;
pub const IFLA_CARRIER: u16 = 33;
pub const IFLA_PHYS_PORT_ID: u16 = 34;
pub const IFLA_CARRIER_CHANGES: u16 = 35;
pub const IFLA_PHYS_SWITCH_ID: u16 = 36;
pub const IFLA_LINK_NETNSID: u16 = 37;
pub const IFLA_PHYS_PORT_NAME: u16 = 38;
pub const IFLA_PROTO_DOWN: u16 = 39;
pub const IFLA_GSO_MAX_SEGS: u16 = 40;
pub const IFLA_GSO_MAX_SIZE: u16 = 41;
pub const IFLA_PAD: u16 = 42;
pub const IFLA_XDP: u16 = 43;
pub const IFLA_EVENT: u16 = 44;
pub const IFLA_NEW_NETNSID: u16 = 45;
pub const IFLA_TARGET_NETNSID: u16 = 46;
pub const IFLA_CARRIER_UP_COUNT: u16 = 47;
pub const IFLA_CARRIER_DOWN_COUNT: u16 = 48;
pub const IFLA_NEW_IFINDEX: u16 = 49;
pub const IFLA_MIN_MTU: u16 = 50;
pub const IFLA_MAX_MTU: u16 = 51;
pub const IFLA_PROP_LIST: u16 = 52;
pub const IFLA_ALT_IFNAME: u16 = 53;
pub const IFLA_PERM_ADDRESS: u16 = 54;
pub const IFLA_PROTO_DOWN_REASON: u16 = 55;
pub const IFLA_PARENT_DEV_NAME: u16 = 56;
pub const IFLA_PARENT_DEV_BUS_NAME: u16 = 57;

// IFLA_LINKINFO subattributes.
pub const IFLA_INFO_UNSPEC: u16 = 0;
pub const IFLA_INFO_KIND: u16 = 1;
pub const IFLA_INFO_DATA: u16 = 2;
pub const IFLA_INFO_XSTATS: u16 = 3;
pub const IFLA_INFO_SLAVE_KIND: u16 = 4;
pub const IFLA_INFO_SLAVE_DATA: u16 = 5;

// Netlink protocols.
pub const NETLINK_ROUTE: i32 = 0;
pub const NETLINK_UNUSED: i32 = 1;
pub const NETLINK_USERSOCK: i32 = 2;
pub const NETLINK_FIREWALL: i32 = 3;
pub const NETLINK_SOCK_DIAG: i32 = 4;
pub const NETLINK_NFLOG: i32 = 5;
pub const NETLINK_XFRM: i32 = 6;
pub const NETLINK_SELINUX: i32 = 7;
pub const NETLINK_ISCSI: i32 = 8;
pub const NETLINK_AUDIT: i32 = 9;
pub const NETLINK_FIB_LOOKUP: i32 = 10;
pub const NETLINK_CONNECTOR: i32 = 11;
pub const NETLINK_NETFILTER: i32 = 12;
pub const NETLINK_IP6_FW: i32 = 13;
pub const NETLINK_DNRTMSG: i32 = 14;
pub const NETLINK_KOBJECT_UEVENT: i32 = 15;
pub const NETLINK_GENERIC: i32 = 16;
pub const NETLINK_SCSITRANSPORT: i32 = 18;
pub const NETLINK_ECRYPTFS: i32 = 19;
pub const NETLINK_RDMA: i32 = 20;
pub const NETLINK_CRYPTO: i32 = 21;
pub const NETLINK_SMC: i32 = 22;

// Netfilter special message types.
pub const NFNL_MSG_BATCH_BEGIN: u16 = 0x10;
pub const NFNL_MSG_BATCH_END: u16 = 0x11;

// Netfilter subsystems.
pub const NFNL_SUBSYS_NFTABLES: u8 = 0xA;

// Netfilter table chain attributes.
pub const NFTA_CHAIN_UNSPEC: u16 = 0;
pub const NFTA_CHAIN_TABLE: u16 = 1;
pub const NFTA_CHAIN_NAME: u16 = 3;
pub const NFTA_CHAIN_HOOK: u16 = 4;
pub const NFTA_CHAIN_TYPE: u16 = 7;

// Netfilter rule expression attributes.
pub const NFTA_EXPR_UNSPEC: u16 = 0;
pub const NFTA_EXPR_NAME: u16 = 1;
pub const NFTA_EXPR_DATA: u16 = 2;

// Netfilter hook attributes.
pub const NFTA_HOOK_UNSPEC: u16 = 0;
pub const NFTA_HOOK_HOOKNUM: u16 = 1;
pub const NFTA_HOOK_PRIORITY: u16 = 2;

// Netfilter list attributes.
pub const NFTA_LIST_UNSPEC: u16 = 0;
pub const NFTA_LIST_ELEM: u16 = 1;

// Netfilter rule attributes.
pub const NFTA_RULE_UNSPEC: u16 = 0;
pub const NFTA_RULE_TABLE: u16 = 1;
pub const NFTA_RULE_CHAIN: u16 = 2;
pub const NFTA_RULE_EXPRESSIONS: u16 = 4;

// Netfilter table attributes.
pub const NFTA_TABLE_NAME: u16 = 1;
pub const NFTA_TABLE_FLAGS: u16 = 2;

// Netfilter table message types.
pub const NFT_MSG_NEWTABLE: u8 = 0;
pub const NFT_MSG_NEWCHAIN: u8 = 3;
pub const NFT_MSG_NEWRULE: u8 = 6;

// Netfilter hooks.
pub const NF_INET_POST_ROUTING: u32 = 4;

// Netlink attribute flags.
pub const NLA_F_NESTED: u16 = 0x8000;

// Netlink message types.
pub const NLMSG_ERROR: i32 = 0x2;

// Netlink message flags.
pub const NLM_F_REQUEST: u16 = 1;
pub const NLM_F_ACK: u16 = 4;
pub const NLM_F_EXCL: u16 = 0x200;
pub const NLM_F_CREATE: u16 = 0x400;
pub const NLM_F_APPEND: u16 = 0x800;

// Route attributes.
pub const RTA_OIF: u16 = 4;
pub const RTA_GATEWAY: u16 = 5;

// Route message types.
pub const RTM_NEWLINK: u16 = 16;
pub const RTM_SETLINK: u16 = 19;
pub const RTM_NEWADDR: u16 = 20;
pub const RTM_NEWROUTE: u16 = 24;

pub const RTN_UNICAST: u8 = 1;

pub const RTPROT_BOOT: u8 = 3;

pub const RT_SCOPE_UNIVERSE: u8 = 0;

pub const RT_TABLE_MAIN: u8 = 254;

// veth attributes.
pub const VETH_INFO_UNSPEC: u16 = 0;
pub const VETH_INFO_PEER: u16 = 1;
/// rtnetlink Network interface address description.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ifaddrmsg {
    pub ifa_family: u8,
    pub ifa_prefixlen: u8,
    pub ifa_flags: u8,
    pub ifa_scope: u8,
    pub ifa_index: u32,
}

/// rtnetlink Network interface description.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ifinfomsg {
    pub ifi_family: u8,
    pub ifi_type: u16,
    pub ifi_index: i32,
    pub ifi_flags: u32,
    pub ifi_change: u32,
}

// Netfilter general message header.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct nfgenmsg {
    pub nfgen_family: u8,
    pub version: u8,
    pub res_id: u16,
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct nlmsgerr {
    pub error: i32,
    pub msg: nlmsghdr,
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct nlmsghdr {
    pub nlmsg_len: u32,
    pub nlmsg_type: u16,
    pub nlmsg_flags: u16,
    pub nlmsg_seq: u32,
    pub nlmsg_pid: u32,
}

/// rtnetlink Network interface route description.
#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct rtmsg {
    pub rtm_family: u8,
    pub rtm_dst_len: u8,
    pub rtm_src_len: u8,
    pub rtm_tos: u8,
    pub rtm_table: u8,
    pub rtm_protocol: u8,
    pub rtm_scope: u8,
    pub rtm_type: u8,
    pub rtm_flags: u32,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct SockAddrNl {
    family: u16,
    pub pid: u32,
    pub groups: u32,
}

impl SockAddrNl {
    pub fn new(pid: u32, groups: u32) -> Self {
        Self {
            family: AF_NETLINK.into(),
            pid,
            groups,
        }
    }
}

unsafe impl SockAddr for SockAddrNl {
    fn family() -> u8 {
        AF_NETLINK
    }
}

/// Creates a Netfilter message type from the subsystem and a subsystem specific message type.
///
/// See the `NFNL_SUBSYS_*` constants.
// TODO: Make `const fn` when possible.
pub fn nfnl_msg(subsys: u8, msg: u8) -> u16 {
    (u16::from(subsys) << 8) | u16::from(msg)
}