use libc::*;
use std::mem;
use std::ptr::null;
use error::*;
use queue::{Queue, PacketHandler};
use message::Message;
use lock::NFQ_LOCK as LOCK;
use ffi::*;
pub enum ProtocolFamily {
INET = AF_INET as isize,
INET6 = AF_INET6 as isize
}
pub struct Handle { pub ptr: *mut nfq_handle }
impl Drop for Handle {
fn drop(&mut self) {
let ret = unsafe { nfq_close(self.ptr) };
if ret != 0 {
panic!("Failed to close NFQHandle");
}
}
}
impl Handle {
pub fn new() -> Result<Handle, NFQError> {
let _lock = LOCK.lock().unwrap();
let ptr = unsafe { nfq_open() };
if ptr.is_null() {
Err(error(ErrorReason::OpenHandle, "Failed to allocate NFQ Handle", None))
} else {
Ok(Handle{ ptr: ptr })
}
}
pub fn bind(&mut self, proto: ProtocolFamily) -> Result<(), NFQError> {
let _lock = LOCK.lock().unwrap();
let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
if res < 0 {
Err(error(ErrorReason::Bind, "Failed to bind NFQ Handle", Some(res)))
} else {
Ok(())
}
}
pub fn unbind(&mut self, proto: ProtocolFamily) -> Result<(), NFQError> {
let _lock = LOCK.lock().unwrap();
let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
if res < 0 {
Err(error(ErrorReason::Unbind, "Failed to unbind NFQ Handle", Some(res)))
} else {
Ok(())
}
}
pub fn queue<F: PacketHandler>(&mut self,
queue_number: u16,
handler: F) -> Result<Box<Queue<F>>, NFQError> {
Queue::new(self.ptr, queue_number, handler)
}
pub fn start(&mut self, length: u64) {
unsafe {
let buffer: *mut c_void = malloc(mem::size_of::<c_char>() as u64 * length as u64);
if buffer.is_null() {
panic!("Failed to allocate packet buffer");
}
let fd = nfq_fd(self.ptr);
loop {
match recv(fd, buffer, length, 0) {
rv if rv >=0 => { nfq_handle_packet(self.ptr, buffer as *mut c_char, rv as i32); },
_ => { break; }
}
}
free(buffer as *mut c_void);
}
}
}