extern crate libc;
use hwaddr::*;
use std;
type NflogData = *const libc::c_void;
pub struct Message {
nfad : NflogData,
}
#[derive(Debug)]
pub enum NflogError {
NoSuchAttribute,
}
pub enum XMLFormatFlags {
XmlPrefix,
XmlHw,
XmlMark,
XmlDev,
XmlPhysDev,
XmlPayload,
XmlTime,
XmlAll,
}
#[link(name = "netfilter_log")]
extern {
fn nflog_get_msg_packet_hdr(nfad: NflogData) -> *const libc::c_void;
fn nflog_get_hwtype (nfad: NflogData) -> u16;
fn nflog_get_msg_packet_hwhdrlen (nfad: NflogData) -> u16;
fn nflog_get_msg_packet_hwhdr (nfad: NflogData) -> *const libc::c_char;
fn nflog_get_nfmark (nfad: NflogData) -> u32;
fn nflog_get_timestamp (nfad: NflogData, tv: *mut libc::timeval) -> u32;
fn nflog_get_indev (nfad: NflogData) -> u32;
fn nflog_get_physindev (nfad: NflogData) -> u32;
fn nflog_get_outdev (nfad: NflogData) -> u32;
fn nflog_get_physoutdev (nfad: NflogData) -> u32;
fn nflog_get_packet_hw (nfad: NflogData) -> *const NfMsgPacketHw;
fn nflog_get_payload (nfad: NflogData, data: &*mut libc::c_void) -> libc::c_int;
fn nflog_get_prefix (nfad: NflogData) -> *const libc::c_char;
fn nflog_get_uid (nfad: NflogData, uid: *mut u32) -> libc::c_int;
fn nflog_get_gid (nfad: NflogData, uid: *mut u32) -> libc::c_int;
fn nflog_get_seq (nfad: NflogData, uid: *mut u32) -> libc::c_int;
fn nflog_get_seq_global (nfad: NflogData, uid: *mut u32) -> libc::c_int;
fn nflog_snprintf_xml (buf: *mut u8, rem: libc::size_t, tb: NflogData, flags: libc::c_uint) -> libc::c_int;
}
const NFLOG_XML_PREFIX : u32 = (1 << 0);
const NFLOG_XML_HW : u32 = (1 << 1);
const NFLOG_XML_MARK : u32 = (1 << 2);
const NFLOG_XML_DEV : u32 = (1 << 3);
const NFLOG_XML_PHYSDEV : u32 = (1 << 4);
const NFLOG_XML_PAYLOAD : u32 = (1 << 5);
const NFLOG_XML_TIME : u32 = (1 << 6);
const NFLOG_XML_ALL : u32 = (!0u32);
#[repr(C)]
struct NfMsgPacketHw {
pub hw_addrlen : u16,
pub _pad : u16,
pub hw_addr : [u8;8],
}
#[repr(C)]
pub struct NfMsgPacketHdr {
pub hw_protocol : u16,
pub hook : u8,
pub pad : u8,
}
impl Message {
#[doc(hidden)]
pub fn new(nfad: *const libc::c_void) -> Message {
Message {
nfad: nfad,
}
}
pub fn get_msg_packet_hdr(&self) -> NfMsgPacketHdr {
let ptr = unsafe { nflog_get_msg_packet_hdr(self.nfad) };
let c_hdr = ptr as *const NfMsgPacketHdr;
let hdr = unsafe {
NfMsgPacketHdr {
hw_protocol: (*c_hdr).hw_protocol,
hook: (*c_hdr).hook,
pad: (*c_hdr).pad,
}
};
return hdr;
}
pub fn get_hwtype(&self) -> u16 {
return unsafe { nflog_get_hwtype(self.nfad) };
}
pub fn get_packet_hwhdr<'a>(&'a self) -> &'a [u8] {
let c_len = unsafe { nflog_get_msg_packet_hwhdrlen(self.nfad) };
let c_ptr = unsafe { nflog_get_msg_packet_hwhdr(self.nfad) };
let data : &[u8] = unsafe { std::slice::from_raw_parts(c_ptr as *mut u8, c_len as usize) };
return data;
}
pub fn get_nfmark(&self) -> u32 {
return unsafe { nflog_get_nfmark(self.nfad) };
}
pub fn get_timestamp(&self) -> Result<libc::timeval,NflogError> {
let mut tv = libc::timeval {
tv_sec: 0,
tv_usec: 0,
};
let rc = unsafe { nflog_get_timestamp(self.nfad,&mut tv) };
match rc {
0 => Ok(tv),
_ => Err(NflogError::NoSuchAttribute),
}
}
pub fn get_indev(&self) -> u32 {
return unsafe { nflog_get_indev(self.nfad) };
}
pub fn get_physindev(&self) -> u32 {
return unsafe { nflog_get_physindev(self.nfad) };
}
pub fn get_outdev(&self) -> u32 {
return unsafe { nflog_get_outdev(self.nfad) };
}
pub fn get_physoutdev(&self) -> u32 {
return unsafe { nflog_get_physoutdev(self.nfad) };
}
pub fn get_packet_hw<'a>(&'a self) -> Result<HwAddr<'a>,NflogError> {
let c_hw = unsafe { nflog_get_packet_hw(self.nfad) };
if c_hw == std::ptr::null() {
return Err(NflogError::NoSuchAttribute);
}
let c_len = u16::from_be(unsafe{(*c_hw).hw_addrlen}) as usize;
match c_len {
0 => Err(NflogError::NoSuchAttribute),
_ => Ok( HwAddr::new(unsafe{&((*c_hw).hw_addr)[1..c_len]})),
}
}
pub fn get_payload<'a>(&'a self) -> &'a [u8] {
let c_ptr = std::ptr::null_mut();
let payload_len = unsafe { nflog_get_payload(self.nfad, &c_ptr) };
let payload : &[u8] = unsafe { std::slice::from_raw_parts(c_ptr as *mut u8, payload_len as usize) };
return payload;
}
pub fn get_prefix(&self) -> Result<String,std::str::Utf8Error> {
let c_buf: *const libc::c_char = unsafe { nflog_get_prefix(self.nfad) };
let c_str = unsafe { std::ffi::CStr::from_ptr(c_buf) };
match c_str.to_str() {
Err(e) => Err(e),
Ok(v) => Ok(v.to_string()),
}
}
pub fn get_uid(&self) -> Result<u32,&str> {
let mut uid =0;
let rc = unsafe { nflog_get_uid(self.nfad,&mut uid) };
match rc {
0 => Ok(uid),
_ => Err("nflog_get_uid"),
}
}
pub fn get_gid(&self) -> Result<u32,NflogError> {
let mut gid =0;
let rc = unsafe { nflog_get_gid(self.nfad,&mut gid) };
match rc {
0 => Ok(gid),
_ => Err(NflogError::NoSuchAttribute),
}
}
pub fn get_seq(&self) -> Result<u32,NflogError> {
let mut uid =0;
let rc = unsafe { nflog_get_seq(self.nfad,&mut uid) };
match rc {
0 => Ok(uid),
_ => Err(NflogError::NoSuchAttribute),
}
}
pub fn get_seq_global(&self) -> Result<u32,NflogError> {
let mut uid =0;
let rc = unsafe { nflog_get_seq_global(self.nfad,&mut uid) };
match rc {
0 => Ok(uid),
_ => Err(NflogError::NoSuchAttribute),
}
}
pub fn as_xml_str(&self, flags: &[XMLFormatFlags]) -> Result<String,std::str::Utf8Error> {
let mut buf : [u8;65536] = [0;65536];
let buf_ptr = buf.as_mut_ptr() as *mut libc::c_uchar;
let buf_len = buf.len() as libc::size_t;
let xml_flags = flags.iter().map(|flag| {
match *flag {
XMLFormatFlags::XmlPrefix => NFLOG_XML_PREFIX,
XMLFormatFlags::XmlHw => NFLOG_XML_HW,
XMLFormatFlags::XmlMark => NFLOG_XML_MARK,
XMLFormatFlags::XmlDev => NFLOG_XML_DEV,
XMLFormatFlags::XmlPhysDev => NFLOG_XML_PHYSDEV,
XMLFormatFlags::XmlPayload => NFLOG_XML_PAYLOAD,
XMLFormatFlags::XmlTime => NFLOG_XML_TIME,
XMLFormatFlags::XmlAll => NFLOG_XML_ALL,
}
}).fold(0u32, |acc, i| acc | i);
let rc = unsafe { nflog_snprintf_xml(buf_ptr, buf_len, self.nfad, xml_flags) };
if rc < 0 { panic!("nflog_snprintf_xml"); }
match std::str::from_utf8(&buf) {
Ok(v) => Ok(v.to_string()),
Err(e) => Err(e),
}
}
}
use std::fmt;
use std::fmt::Write;
impl fmt::Display for Message {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
let payload_data = self.get_payload();
let mut s = String::new();
for &byte in payload_data {
write!(&mut s, "{:X} ", byte).unwrap();
}
write!(out, "{}", s)
}
}