diff --git a/Cargo.toml b/Cargo.toml index 25cbc7b..ecfbf91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "netfilter_queue" -version = "0.2.1" +version = "0.2.2" authors = [ + "lilydjwg ", "Laurie Clark-Michalek ", "Zach Pomerantz " ] @@ -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" diff --git a/src/error.rs b/src/error.rs index 0f3e073..1f83644 100644 --- a/src/error.rs +++ b/src/error.rs @@ -21,13 +21,11 @@ pub enum Reason { pub struct Error { reason: Reason, description: String, - cause: Option>, } 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()) } } @@ -43,13 +41,13 @@ 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) -> 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) @@ -57,6 +55,5 @@ pub fn error(reason: Reason, msg: &str, res: Option) -> Error { Error { reason: reason, description: desc, - cause: None, } } diff --git a/src/ffi.rs b/src/ffi.rs index d166dc6..b6a9bca 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -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 { @@ -52,12 +43,12 @@ 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, @@ -65,10 +56,10 @@ extern { 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; @@ -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 diff --git a/src/handle.rs b/src/handle.rs index a9fc064..e9dbdc4 100644 --- a/src/handle.rs +++ b/src/handle.rs @@ -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, @@ -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 { @@ -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 { @@ -84,7 +86,7 @@ impl Handle { pub fn queue(&mut self, queue_number: u16, handler: F) -> Result>, Error> { - Queue::new(self.ptr, queue_number as uint16_t, handler) + Queue::new(self.ptr, queue_number, handler) } /// Start listening using any attached queues @@ -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); }, diff --git a/src/message.rs b/src/message.rs index 8f0942f..74acb53 100644 --- a/src/message.rs +++ b/src/message.rs @@ -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::*; @@ -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, @@ -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::() + self.payload::().map(|x| x.0) } /// Parse a sized `Payload` from the message @@ -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(&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(&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)) } } diff --git a/src/queue/mod.rs b/src/queue/mod.rs index 25c3809..c4f4324 100644 --- a/src/queue/mod.rs +++ b/src/queue/mod.rs @@ -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 { @@ -67,7 +67,7 @@ impl Drop for Queue { impl Queue { #[doc(hidden)] pub fn new(handle: *mut nfq_handle, - queue_number: uint16_t, + queue_number: u16, packet_handler: F) -> Result>, Error> { let _lock = LOCK.lock().unwrap(); @@ -100,11 +100,11 @@ impl Queue { 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 { diff --git a/src/queue/verdict.rs b/src/queue/verdict.rs index 3837a0c..57d36b3 100644 --- a/src/queue/verdict.rs +++ b/src/queue/verdict.rs @@ -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, } @@ -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 { - 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) }