Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[package]
name = "netfilter_queue"
version = "0.2.1"
version = "0.2.2"
authors = [
"lilydjwg <lilydjwg@gmail.com>",
"Laurie Clark-Michalek <lclarkmichalek@gmail.com>",
"Zach Pomerantz <zach@terminal.com>"
]
Expand All @@ -13,7 +14,7 @@ keywords = ["iptables", "nf", "nfq", "netfilter", "netfilter_queue"]
exclude = [".gitignore"]

[dependencies]
lazy_static = "0.1.*"
libc = "0.1"
num = "0.1.*"
errno = "0.1.*"
lazy_static = "1"
libc = "0.2"
num = "0.2"
errno = "0.2"
11 changes: 4 additions & 7 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ pub enum Reason {
pub struct Error {
reason: Reason,
description: String,
cause: Option<Box<Base>>,
}

impl fmt::Debug for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let msg = format!("{:?}: {:?} (cause: {:?})",
self.reason, self.description, self.cause);
let msg = format!("{:?}: {:?}", self.reason, self.description);
formatter.write_str(msg.as_ref())
}
}
Expand All @@ -43,20 +41,19 @@ impl Base for Error {
fn description(&self) -> &str {
self.description.as_ref()
}
fn cause(&self) -> Option<&Base> {
self.cause.as_ref().map(|c| &**c)
fn cause(&self) -> Option<&dyn Base> {
None
}
}

pub fn error(reason: Reason, msg: &str, res: Option<c_int>) -> Error {
let errno = nfq_errno;
let errno = unsafe { nfq_errno };
let desc = match res {
Some(r) => format!("{} (errno: {}, res: {})", msg, errno, r),
None => format!("{}, (errno: {})", msg, errno)
};
Error {
reason: reason,
description: desc,
cause: None,
}
}
43 changes: 17 additions & 26 deletions src/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,32 @@
#![allow(non_camel_case_types)]

use libc::*;
use num::traits::PrimInt;

pub const NF_DROP: u32 = 0;
pub const NF_ACCEPT: u32 = 1;
pub const NF_STOLEN: u32 = 2;
pub const NF_QUEUE: u32 = 3;
pub const NF_REPEAT: u32 = 4;
pub const NF_STOP: u32 = 5;

#[repr(C)]
pub struct nfq_handle;
pub struct nfq_handle(c_void);

#[repr(C)]
/// The handle into NFQueue
pub struct nfq_q_handle;
pub struct nfq_q_handle(c_void);

#[repr(C)]
pub struct nfgenmsg;
pub struct nfgenmsg(c_void);

#[repr(C)]
pub struct nfq_data;
pub struct nfq_data(c_void);

#[repr(C)]
#[packed]
#[repr(C,packed)]
/// The NFQueue specific packet data
pub struct nfqnl_msg_packet_hdr {
/// The packet id
///
/// This id is necessary to identify the packet to `set_verdict`.
/// However, it may have the wrong endianness, so `id()` should be used instead.
pub packet_id: uint32_t,
pub packet_id: u32,
/// HW protocol (network order)
pub hw_protocol: uint16_t,
pub hw_protocol: u16,
/// Netfilter hook
pub hook: uint8_t
pub hook: u8,
}

impl nfqnl_msg_packet_hdr {
Expand All @@ -52,23 +43,23 @@ extern {
// Library setup
pub fn nfq_open() -> *mut nfq_handle;
pub fn nfq_close(handle: *mut nfq_handle) -> c_int;
pub fn nfq_bind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
pub fn nfq_unbind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
pub fn nfq_bind_pf(handle: *mut nfq_handle, pf: u16) -> c_int;
pub fn nfq_unbind_pf(handle: *mut nfq_handle, pf: u16) -> c_int;

// Queue handling
pub fn nfq_create_queue(handle: *mut nfq_handle,
num: uint16_t,
num: u16,
cb: extern "C" fn(h: *mut nfq_q_handle,
nfmsg: *mut nfgenmsg,
nfad: *mut nfq_data,
data: *mut c_void) -> c_int,
data: *mut c_void) -> *mut nfq_q_handle;
pub fn nfq_destroy_queue(handle: *mut nfq_q_handle) -> c_int;
pub fn nfq_set_mode(handle: *mut nfq_q_handle,
mode: uint8_t,
range: uint32_t) -> c_int;
mode: u8,
range: u32) -> c_int;
pub fn nfq_set_queue_maxlen(handle: *mut nfq_q_handle,
queuelen: uint32_t) -> c_int;
queuelen: u32) -> c_int;

// Iterating through a queue
pub fn nfq_fd(handle: *mut nfq_handle) -> c_int;
Expand All @@ -78,9 +69,9 @@ extern {

// Deciding on a verdict
pub fn nfq_set_verdict(handle: *mut nfq_q_handle,
id: uint32_t,
verdict: uint32_t,
data_len: uint32_t,
id: u32,
verdict: u32,
data_len: u32,
buf: *const c_uchar) -> c_int;

// Parsing the message
Expand Down
12 changes: 7 additions & 5 deletions src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use ffi::*;
/// Protocol Family
///
/// NFQueue will only deal with IP, so only those families are made available.
#[derive(Clone,Copy)]
pub enum ProtocolFamily {
/// IPv4 Address Family
INET = AF_INET as isize,
Expand Down Expand Up @@ -58,7 +59,8 @@ impl Handle {
pub fn bind(&mut self, proto: ProtocolFamily) -> Result<(), Error> {
let _lock = LOCK.lock().unwrap();

let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
unsafe { nfq_unbind_pf(self.ptr, proto as u16) };
let res = unsafe { nfq_bind_pf(self.ptr, proto as u16) };
if res < 0 {
Err(error(Reason::Bind, "Failed to bind handle", Some(res)))
} else {
Expand All @@ -72,7 +74,7 @@ impl Handle {
pub fn unbind(&mut self, proto: ProtocolFamily) -> Result<(), Error> {
let _lock = LOCK.lock().unwrap();

let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
let res = unsafe { nfq_unbind_pf(self.ptr, proto as u16) };
if res < 0 {
Err(error(Reason::Unbind, "Failed to unbind handle", Some(res)))
} else {
Expand All @@ -84,7 +86,7 @@ impl Handle {
pub fn queue<F: PacketHandler>(&mut self,
queue_number: u16,
handler: F) -> Result<Box<Queue<F>>, Error> {
Queue::new(self.ptr, queue_number as uint16_t, handler)
Queue::new(self.ptr, queue_number, handler)
}

/// Start listening using any attached queues
Expand All @@ -95,14 +97,14 @@ impl Handle {
pub fn start(&mut self, length: u16) -> Result<(), Error> {
unsafe {
// TODO: Get rid of malloc
let buffer: *mut c_void = malloc(length as u64);
let buffer: *mut c_void = malloc(length as usize);
if buffer.is_null() {
panic!("Failed to allocate packet buffer");
}
let fd = nfq_fd(self.ptr);

loop {
match recv(fd, buffer, length as u64, 0) {
match recv(fd, buffer, length as usize, 0) {
rv if rv >=0 => {
nfq_handle_packet(self.ptr, buffer as *mut c_char, length as i32);
},
Expand Down
24 changes: 14 additions & 10 deletions src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

use libc::*;
use std::mem;
use std::ptr::null;
use std::ptr::null_mut;
use std::net::Ipv4Addr;
use num::traits::PrimInt;
use error::*;
use util::*;
use ffi::*;
Expand All @@ -18,6 +17,7 @@ pub trait Payload {}
#[allow(dead_code)]
#[allow(missing_docs)]
/// A `Payload` to fetch and parse an IP packet header
#[repr(C)]
pub struct IPHeader {
pub version_and_header_raw: u8,
pub dscp_raw: u8,
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<'a> Message<'a> {
/// and `handle.start_sized_to_payload` methods.
/// See `examples/get_addrs.rs`.
pub unsafe fn ip_header(&self) -> Result<&IPHeader, Error> {
self.payload::<IPHeader>()
self.payload::<IPHeader>().map(|x| x.0)
}

/// Parse a sized `Payload` from the message
Expand All @@ -105,15 +105,19 @@ impl<'a> Message<'a> {
/// The best way to do this is with the `queue_builder.set_copy_mode_sized_to_payload`
/// and `handle.start_sized_to_payload` methods.
/// See `examples/get_addrs.rs`.
pub unsafe fn payload<A: Payload>(&self) -> Result<&A, Error> {
let data: *const A = null();
let ptr: *mut *mut A = &mut (data as *mut A);
let _ = match nfq_get_payload(self.ptr, ptr as *mut *mut c_uchar) {
///
/// # Safety
///
/// ffi call to C.
pub unsafe fn payload<A: Payload>(&self) -> Result<(&A, usize), Error> {
let mut data: *mut A = null_mut();
let ptr: *mut *mut A = &mut data;
let n = match nfq_get_payload(self.ptr, ptr as *mut *mut c_uchar) {
-1 => return Err(error(Reason::GetPayload, "Failed to get payload", Some(-1))),
_ => ()
n => n
};
match as_ref(&data) {
Some(payload) => Ok(payload),
match as_mut(&data) {
Some(payload) => Ok((payload, n as usize)),
None => Err(error(Reason::GetPayload, "Failed to get payload", None))
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use lock::NFQ_LOCK as LOCK;

use ffi::*;

const NFQNL_COPY_NONE: uint8_t = 0;
const NFQNL_COPY_META: uint8_t = 1;
const NFQNL_COPY_PACKET: uint8_t = 2;
const NFQNL_COPY_NONE: u8 = 0;
const NFQNL_COPY_META: u8 = 1;
const NFQNL_COPY_PACKET: u8 = 2;

/// The amount of data to be copied to userspace for each packet queued.
pub enum CopyMode {
Expand Down Expand Up @@ -67,7 +67,7 @@ impl<F: PacketHandler> Drop for Queue<F> {
impl<F: PacketHandler> Queue<F> {
#[doc(hidden)]
pub fn new(handle: *mut nfq_handle,
queue_number: uint16_t,
queue_number: u16,
packet_handler: F) -> Result<Box<Queue<F>>, Error> {
let _lock = LOCK.lock().unwrap();

Expand Down Expand Up @@ -100,11 +100,11 @@ impl<F: PacketHandler> Queue<F> {
CopyMode::None => NFQNL_COPY_NONE,
CopyMode::Metadata => NFQNL_COPY_META,
CopyMode::Packet(_) => NFQNL_COPY_PACKET
} as uint8_t;
};
let range = match mode {
CopyMode::Packet(r) => r,
_ => 0
} as uint32_t;
} as u32;

let res = unsafe { nfq_set_mode(self.ptr, copy_mode, range) };
if res != 0 {
Expand Down
8 changes: 4 additions & 4 deletions src/queue/verdict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ pub enum Verdict {

impl Verdict {
// Encodes the enum into a u32 suitible for use by nfq_set_verdict
fn as_u32(&self) -> u32 {
fn as_i32(&self) -> i32 {
match *self {
Verdict::Drop => NF_DROP,
Verdict::Accept => NF_ACCEPT,
Verdict::Stolen => NF_STOLEN,
Verdict::Queue(t) => NF_QUEUE | (t as u32) << 16,
Verdict::Queue(t) => NF_QUEUE | (t as i32) << 16,
Verdict::Repeat => NF_REPEAT,
Verdict::Stop => NF_STOP,
}
Expand All @@ -55,9 +55,9 @@ impl Verdict {
/// The `packet_id` must be used to identify a packet, fetched from `packet.header.id()`.
/// For simpler cases, pass `data_len = 0` and `buffer = std::ptr::null()`.
pub fn set_verdict(qh: QueueHandle, packet_id: u32, verdict: Verdict, data_len: u32, buffer: *const c_uchar) -> Result<c_int, Error> {
let c_verdict = verdict.as_u32() as uint32_t;
let c_verdict = verdict.as_i32() as u32;

match unsafe { nfq_set_verdict(qh.0, packet_id as uint32_t, c_verdict as uint32_t, data_len as uint32_t, buffer) } {
match unsafe { nfq_set_verdict(qh.0, packet_id, c_verdict, data_len, buffer) } {
-1 => Err(error(Reason::SetVerdict, "Failed to set verdict", None)),
r @ _ => Ok(r)
}
Expand Down