1extern crate libc;
2
3use hwaddr::*;
4use std;
5
6type NfqueueData = *const libc::c_void;
7
8pub struct Message {
10 qqh : *const libc::c_void,
11 nfad : NfqueueData,
12 id : u32,
13}
14
15#[derive(Debug)]
16pub enum NfqueueError {
17 NoSuchAttribute,
18}
19
20#[derive(Clone)]
22pub enum Verdict {
23 Drop,
25 Accept,
27 Stolen,
29 Queue,
31 Repeat,
33 Stop,
35}
36
37const NF_DROP : u32 = 0x0000;
38const NF_ACCEPT : u32 = 0x0001;
39const NF_STOLEN : u32 = 0x0002;
40const NF_QUEUE : u32 = 0x0003;
41const NF_REPEAT : u32 = 0x0004;
42const NF_STOP : u32 = 0x0005;
43
44fn u32_of_verdict(v: Verdict) -> u32 {
45 match v {
46 Verdict::Drop => NF_DROP,
47 Verdict::Accept => NF_ACCEPT,
48 Verdict::Stolen => NF_STOLEN,
49 Verdict::Queue => NF_QUEUE,
50 Verdict::Repeat => NF_REPEAT,
51 Verdict::Stop => NF_STOP,
52 }
53}
54
55pub enum XMLFormatFlags {
57 XmlHw,
58 XmlMark,
59 XmlDev,
60 XmlPhysDev,
61 XmlPayload,
62 XmlTime,
63 XmlAll,
64}
65
66const NFQ_XML_HW : u32 = (1 << 0);
67const NFQ_XML_MARK : u32 = (1 << 1);
68const NFQ_XML_DEV : u32 = (1 << 2);
69const NFQ_XML_PHYSDEV : u32 = (1 << 3);
70const NFQ_XML_PAYLOAD : u32 = (1 << 4);
71const NFQ_XML_TIME : u32 = (1 << 5);
72const NFQ_XML_ALL : u32 = (!0u32);
73
74#[repr(C)]
76struct NfMsgPacketHw {
77 pub hw_addrlen : u16,
79 pub _pad : u16,
81 pub hw_addr : [u8;8],
83}
84
85#[repr(C)]
87pub struct NfMsgPacketHdr {
88 pub packet_id : u32,
90 pub hw_protocol : u16,
92 pub hook : u8,
94}
95
96#[link(name = "netfilter_queue")]
97extern {
98 fn nfq_set_verdict2(qqh: *const libc::c_void, id: u32, verdict: u32, mark: u32, data_len: u32, data: *const libc::c_uchar);
102
103 fn nfq_get_msg_packet_hdr(nfad: NfqueueData) -> *const libc::c_void;
105 fn nfq_get_nfmark (nfad: NfqueueData) -> u32;
106 fn nfq_get_timestamp (nfad: NfqueueData, tv: *mut libc::timeval) -> u32;
107 fn nfq_get_indev (nfad: NfqueueData) -> u32;
108 fn nfq_get_physindev (nfad: NfqueueData) -> u32;
109 fn nfq_get_outdev (nfad: NfqueueData) -> u32;
110 fn nfq_get_physoutdev (nfad: NfqueueData) -> u32;
111
112 fn nfq_get_packet_hw (nfad: NfqueueData) -> *const NfMsgPacketHw;
113 fn nfq_get_payload (nfad: NfqueueData, data: &*mut libc::c_void) -> libc::c_int;
114
115 fn nfq_snprintf_xml (buf: *mut u8, rem: libc::size_t, tb: NfqueueData, flags: libc::c_uint) -> libc::c_int;
117}
118
119impl Message {
120 #[doc(hidden)]
124 pub fn new(qqh: *const libc::c_void, nfad: *const libc::c_void) -> Message {
125 let msg_hdr = unsafe { nfq_get_msg_packet_hdr(nfad) as *const NfMsgPacketHdr };
126 assert!(!msg_hdr.is_null());
127 let id = u32::from_be( unsafe{(*msg_hdr).packet_id} );
128 Message {
129 qqh : qqh,
130 nfad: nfad,
131 id : id,
132 }
133 }
134
135 pub fn get_id(&self) -> u32 {
137 self.id
138 }
139
140 pub fn get_nfmark(&self) -> u32 {
142 return unsafe { nfq_get_nfmark(self.nfad) };
143 }
144
145 pub fn get_timestamp(&self) -> Result<libc::timeval,NfqueueError> {
147 let mut tv = libc::timeval {
148 tv_sec: 0,
149 tv_usec: 0,
150 };
151 let rc = unsafe { nfq_get_timestamp(self.nfad,&mut tv) };
152 match rc {
153 0 => Ok(tv),
154 _ => Err(NfqueueError::NoSuchAttribute),
155 }
156 }
157
158 pub fn get_indev(&self) -> u32 {
164 return unsafe { nfq_get_indev(self.nfad) };
165 }
166
167 pub fn get_physindev(&self) -> u32 {
173 return unsafe { nfq_get_physindev(self.nfad) };
174 }
175
176 pub fn get_outdev(&self) -> u32 {
182 return unsafe { nfq_get_outdev(self.nfad) };
183 }
184
185 pub fn get_physoutdev(&self) -> u32 {
191 return unsafe { nfq_get_physoutdev(self.nfad) };
192 }
193
194
195
196
197
198 pub fn get_packet_hw<'a>(&'a self) -> Result<HwAddr<'a>,NfqueueError> {
209 let c_hw = unsafe { nfq_get_packet_hw(self.nfad) };
210
211 if c_hw == std::ptr::null() {
212 return Err(NfqueueError::NoSuchAttribute);
213 }
214
215 let c_len = u16::from_be(unsafe{(*c_hw).hw_addrlen}) as usize;
216 match c_len {
217 0 => Err(NfqueueError::NoSuchAttribute),
218 _ => Ok( HwAddr::new(unsafe{&((*c_hw).hw_addr)[0..c_len]})),
219 }
220 }
221
222
223
224 pub fn set_verdict(&self, verdict: Verdict) {
237 assert!(!self.qqh.is_null());
238 let c_verdict = u32_of_verdict(verdict);
239 unsafe { nfq_set_verdict2(self.qqh, self.id, c_verdict, 0, 0, std::ptr::null_mut()) };
241 }
242
243 pub fn set_verdict_mark(&self, verdict: Verdict, mark: u32) {
257 assert!(!self.qqh.is_null());
258 let c_verdict = u32_of_verdict(verdict);
259 unsafe { nfq_set_verdict2(self.qqh, self.id, c_verdict, mark, 0, std::ptr::null_mut()) };
261 }
262
263 pub fn set_verdict_full(&self, verdict: Verdict, mark: u32, data: &[u8]) {
279 assert!(!self.qqh.is_null());
280 let c_verdict = u32_of_verdict(verdict);
281 let data_ptr = data.as_ptr() as *const libc::c_uchar;
282 let data_len = data.len() as u32;
283 unsafe { nfq_set_verdict2(self.qqh, self.id, c_verdict, mark, data_len, data_ptr) };
285 }
286
287 pub fn get_payload<'a>(&'a self) -> &'a [u8] {
293 let c_ptr = std::ptr::null_mut();
294 let payload_len = unsafe { nfq_get_payload(self.nfad, &c_ptr) };
295 let payload : &[u8] = unsafe { std::slice::from_raw_parts(c_ptr as *mut u8, payload_len as usize) };
296
297 return payload;
298 }
299
300 pub fn as_xml_str(&self, flags: &[XMLFormatFlags]) -> Result<String,std::str::Utf8Error> {
302 let mut buf : [u8;65536] = [0;65536];
304 let buf_ptr = buf.as_mut_ptr() as *mut libc::c_uchar;
305 let buf_len = buf.len() as libc::size_t;
306
307 let xml_flags = flags.iter().map(|flag| {
308 match *flag {
309 XMLFormatFlags::XmlHw => NFQ_XML_HW,
310 XMLFormatFlags::XmlMark => NFQ_XML_MARK,
311 XMLFormatFlags::XmlDev => NFQ_XML_DEV,
312 XMLFormatFlags::XmlPhysDev => NFQ_XML_PHYSDEV,
313 XMLFormatFlags::XmlPayload => NFQ_XML_PAYLOAD,
314 XMLFormatFlags::XmlTime => NFQ_XML_TIME,
315 XMLFormatFlags::XmlAll => NFQ_XML_ALL,
316 }
317 }).fold(0u32, |acc, i| acc | i);
318
319 let rc = unsafe { nfq_snprintf_xml(buf_ptr, buf_len, self.nfad, xml_flags) };
320 if rc < 0 { panic!("nfq_snprintf_xml"); } match std::str::from_utf8(&buf) {
323 Ok(v) => Ok(v.to_string()),
324 Err(e) => Err(e),
325 }
326 }
327}
328
329use std::fmt;
330use std::fmt::Write;
331
332impl fmt::Display for Message {
333 fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
334 let payload_data = self.get_payload();
335 let mut s = String::new();
336 for &byte in payload_data {
337 write!(&mut s, "{:X} ", byte).unwrap();
338 }
339 write!(out, "{}", s)
340 }
341}
342