use std::{env, mem, process, vec::Vec}; extern crate libc; extern crate errno; use errno::Errno; extern crate rsmnl as mnl; use mnl::{AttrTbl, CbResult, CbStatus, MsgVec, Msghdr, Socket}; extern crate rsmnl_linux as linux; use linux::netfilter::{ nfnetlink as nfnl, nfnetlink::Nfgenmsg, nfnetlink_log as nful, nfnetlink_log::{ NfulnlAttrConfig, NfulnlAttrTypeTbl, NfulnlMsgConfigCmd, NfulnlMsgConfigCmds, NfulnlMsgConfigMode, NfulnlMsgPacketHdr, NfulnlMsgTypes, }, }; fn log_cb(nlh: &Msghdr) -> CbResult { let mut ph = &NfulnlMsgPacketHdr { hw_protocol: 0, hook: 0, _pad: 0, }; let mut prefix = ""; let mut mark: u32 = 0; let tb = NfulnlAttrTypeTbl::from_nlmsg(mem::size_of::(), nlh)?; tb.packet_hdr()?.map(|x| ph = x); tb.prefix()?.map(|x| prefix = x); tb.mark()?.map(|x| mark = *x); println!( "log received (prefix=\"{}\", hw=0x{:x}, hook={}, mark={})", prefix, ph.hw_protocol, ph.hook, mark ); Ok(CbStatus::Ok) } fn nflog_build_cfg_pf_request(nlv: &mut MsgVec, command: u8) -> Result<(), Errno> { let mut nlh = nlv.put_header(); nlh.nlmsg_type = (nfnl::NFNL_SUBSYS_ULOG << 8) | NfulnlMsgTypes::Config as u16; nlh.nlmsg_flags = libc::NLM_F_REQUEST as u16; let nfg = nlv.put_extra_header::()?; nfg.nfgen_family = libc::AF_INET as u8; nfg.version = libc::NFNETLINK_V0 as u8; let cmd = NfulnlMsgConfigCmd { command: command }; // nlv.put(NfulnlAttrConfig::Cmd, &cmd)?; NfulnlAttrConfig::put_cmd(nlv, &cmd)?; Ok(()) } fn nflog_build_cfg_request(nlv: &mut MsgVec, command: u8, qnum: u16) -> Result<(), Errno> { let mut nlh = nlv.put_header(); nlh.nlmsg_type = (nfnl::NFNL_SUBSYS_ULOG << 8) | NfulnlMsgTypes::Config as u16; nlh.nlmsg_flags = libc::NLM_F_REQUEST as u16; let nfg = nlv.put_extra_header::()?; nfg.nfgen_family = libc::AF_INET as u8; nfg.version = libc::NFNETLINK_V0 as u8; nfg.res_id = qnum.to_be(); let cmd = nful::NfulnlMsgConfigCmd { command: command }; // nlv.put(NfulnlAttrConfig::Cmd, &cmd)?; NfulnlAttrConfig::put_cmd(nlv, &cmd)?; Ok(()) } fn nflog_build_cfg_params(nlv: &mut MsgVec, mode: u8, range: u32, qnum: u16) -> Result<(), Errno> { let mut nlh = nlv.put_header(); nlh.nlmsg_type = (nfnl::NFNL_SUBSYS_ULOG << 8) | NfulnlMsgTypes::Config as u16; nlh.nlmsg_flags = libc::NLM_F_REQUEST as u16; let nfg = nlv.put_extra_header::()?; nfg.nfgen_family = libc::AF_UNSPEC as u8; nfg.version = nfnl::NFNETLINK_V0; nfg.res_id = qnum.to_be(); let params = NfulnlMsgConfigMode { copy_range: range.to_be(), copy_mode: mode, _pad: 0, }; // nlv.put(NfulnlAttrConfig::Mode, ¶ms)?; NfulnlAttrConfig::put_mode(nlv, ¶ms)?; Ok(()) } fn main() -> Result<(), String> { let args: Vec<_> = env::args().collect(); if args.len() != 2 { println!("Usage: {} [queue_num]", args[0]); process::exit(libc::EXIT_FAILURE); } let qnum: u16 = args[1].trim().parse().expect("queue number required"); let mut nl = Socket::open(libc::NETLINK_NETFILTER, 0) .map_err(|errno| format!("mnl_socket_open: {}", errno))?; nl.bind(0, mnl::SOCKET_AUTOPID) .map_err(|errno| format!("mnl_socket_bind: {}", errno))?; let portid = nl.portid(); let mut nlv = MsgVec::new(); nflog_build_cfg_pf_request(&mut nlv, NfulnlMsgConfigCmds::PfUnbind as u8) .map_err(|errno| format!("nflog_build_cfg_pf_request: {}", errno))?; nl.sendto(&nlv) .map_err(|errno| format!("mnl_socket_sendto: {}", errno))?; nlv.reset(); nflog_build_cfg_pf_request(&mut nlv, NfulnlMsgConfigCmds::PfBind as u8) .map_err(|errno| format!("nflog_build_cfg_pf_request: {}", errno))?; nl.sendto(&nlv) .map_err(|errno| format!("mnl_socket_sendto: {}", errno))?; nlv.reset(); nflog_build_cfg_request(&mut nlv, NfulnlMsgConfigCmds::Bind as u8, qnum) .map_err(|errno| format!("nflog_build_cfg_request: {}", errno))?; nl.sendto(&nlv) .map_err(|errno| format!("mnl_socket_sendto: {}", errno))?; nlv.reset(); nflog_build_cfg_params(&mut nlv, nful::NFULNL_COPY_PACKET, 0xffff, qnum) .map_err(|errno| format!("nflog_build_cfg_params: {}", errno))?; nl.sendto(&nlv) .map_err(|errno| format!("mnl_socket_sendto: {}", errno))?; let mut buf = mnl::default_buffer(); loop { let nrecv = nl .recvfrom(&mut buf) .map_err(|errno| format!("mnl_socket_recvfrom: {}", errno))?; mnl::cb_run(&buf[..nrecv], 0, portid, Some(log_cb)) .map_err(|errno| format!("mnl_cb_run: {}", errno))?; } }