diff --git a/src/bindings/winpcap.rs b/src/bindings/winpcap.rs
index d29ecbb..e29cb29 100644
@@ -347,7 +347,8 @@ extern "system" {
-> libc::DWORD;
}
-#[link(name = ":Packet.dll")]
+#[link(name = "Packet")]
+#[allow(improper_ctypes)]
extern {
// from Packet32.h
pub fn PacketSendPacket(AdapterObject: LPADAPTER, pPacket: LPPACKET, Sync: win::BOOLEAN)
diff --git a/src/datalink/winpcap.rs b/src/datalink/winpcap.rs
index d1bb14c..0084db1 100644
@@ -9,11 +9,11 @@
extern crate libc;
use std::cmp;
-use std::collections::RingBuf;
+use std::collections::VecDeque;
use std::ffi::CString;
-use std::old_io::{IoResult, IoError};
+use std::io;
use std::mem;
-use std::raw::Slice;
+use std::slice;
use std::sync::Arc;
use bindings::{bpf, winpcap};
@@ -50,8 +50,8 @@ impl Drop for WinPcapPacket {
pub fn datalink_channel(network_interface: &NetworkInterface,
read_buffer_size: usize,
write_buffer_size: usize,
- channel_type: DataLinkChannelType)
- -> IoResult<(Box<DataLinkSenderImpl>, Box<DataLinkReceiverImpl>)> {
+ _channel_type: DataLinkChannelType)
+ -> io::Result<(Box<DataLinkSender>, Box<DataLinkReceiver>)> {
let mut read_buffer = Vec::new();
read_buffer.resize(read_buffer_size, 0u8);
@@ -59,18 +59,18 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
write_buffer.resize(write_buffer_size, 0u8);
let adapter = unsafe {
- let net_if_str = CString::from_slice(network_interface.name.as_bytes());
+ let net_if_str = CString::new(network_interface.name.as_bytes()).unwrap();
winpcap::PacketOpenAdapter(net_if_str.as_ptr() as *mut libc::c_char)
};
if adapter.is_null() {
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
let ret = unsafe {
winpcap::PacketSetHwFilter(adapter, winpcap::NDIS_PACKET_TYPE_PROMISCUOUS)
};
if ret == 0 {
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
// Set kernel buffer size
@@ -78,7 +78,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
winpcap::PacketSetBuff(adapter, read_buffer_size as libc::c_int)
};
if ret == 0 {
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
// FIXME [windows] causes "os error 31: a device atteched to the system is not functioning"
@@ -88,7 +88,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
winpcap::PacketSetReadTimeout(adapter, 5000)
};
if ret == 0 {
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
// Immediate mode
@@ -96,7 +96,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
winpcap::PacketSetMinToCopy(adapter, 1)
};
if ret == 0 {
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
let read_packet = unsafe { winpcap::PacketAllocatePacket() };
@@ -104,7 +104,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
unsafe {
winpcap::PacketCloseAdapter(adapter);
}
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
unsafe {
@@ -119,7 +119,7 @@ pub fn datalink_channel(network_interface: &NetworkInterface,
winpcap::PacketFreePacket(read_packet);
winpcap::PacketCloseAdapter(adapter);
}
- return Err(IoError::last_error());
+ return Err(io::Error::last_os_error());
}
unsafe {
@@ -151,25 +151,19 @@ pub struct DataLinkSenderImpl {
impl DataLinkSender for DataLinkSenderImpl {
#[inline]
fn build_and_send(&mut self, num_packets: usize, packet_size: usize,
- func: &mut FnMut(MutableEthernetPacket)) -> Option<IoResult<()>>
+ func: &mut FnMut(MutableEthernetPacket)) -> Option<io::Result<()>>
{
- use std::raw::Slice;
let len = num_packets * packet_size;
if len >= unsafe { (*self.packet.packet).Length } as usize {
None
} else {
let min = unsafe { cmp::min((*self.packet.packet).Length as usize, len) };
let slice: &mut [u8] = unsafe {
- mem::transmute(
- Slice {
- data: (*self.packet.packet).Buffer as *const (),
- len: min
- }
- )
+ slice::from_raw_parts_mut((*self.packet.packet).Buffer as *mut u8, min)
};
for chunk in slice.chunks_mut(packet_size) {
{
- let eh = MutableEthernetPacket::new(chunk);
+ let eh = MutableEthernetPacket::new(chunk).unwrap();
func(eh);
}
@@ -181,9 +175,8 @@ impl DataLinkSender for DataLinkSenderImpl {
unsafe { (*self.packet.packet).Length = old_len; }
- match ret {
- 0 => return Some(Err(IoError::last_error())),
- _ => ()
+ if ret == 0 {
+ return Some(Err(io::Error::last_os_error()))
}
}
Some(Ok(()))
@@ -192,8 +185,8 @@ impl DataLinkSender for DataLinkSenderImpl {
#[inline]
fn send_to(&mut self, packet: &EthernetPacket, _dst: Option<NetworkInterface>)
- -> Option<IoResult<()>> {
- use old_packet::MutablePacket;
+ -> Option<io::Result<()>> {
+ use packet::MutablePacket;
self.build_and_send(1, packet.packet().len(), &mut |mut eh| {
eh.clone_from(packet);
})
@@ -210,12 +203,14 @@ pub struct DataLinkReceiverImpl {
}
impl DataLinkReceiver for DataLinkReceiverImpl {
+ // FIXME See https://github.com/Manishearth/rust-clippy/issues/417
+ #[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
fn iter<'a>(&'a mut self) -> Box<DataLinkChannelIterator + 'a> {
let buflen = unsafe { (*self.packet.packet).Length } as usize;
Box::new(DataLinkChannelIteratorImpl {
pc: self,
// Enough room for minimally sized packets without reallocating
- packets: RingBuf::with_capacity(buflen / 64)
+ packets: VecDeque::with_capacity(buflen / 64)
})
}
}
@@ -225,18 +220,18 @@ unsafe impl Sync for DataLinkReceiverImpl {}
pub struct DataLinkChannelIteratorImpl<'a> {
pc: &'a mut DataLinkReceiverImpl,
- packets: RingBuf<(usize, usize)>,
+ packets: VecDeque<(usize, usize)>,
}
impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> {
- fn next<'c>(&'c mut self) -> IoResult<EthernetPacket<'c>> {
+ fn next(&mut self) -> io::Result<EthernetPacket> {
// NOTE Most of the logic here is identical to FreeBSD/OS X
if self.packets.is_empty() {
let ret = unsafe {
winpcap::PacketReceivePacket(self.pc.adapter.adapter, self.pc.packet.packet, 0)
};
let buflen = match ret {
- 0 => return Err(IoError::last_error()),
+ 0 => return Err(io::Error::last_os_error()),
_ => unsafe { (*self.pc.packet.packet).ulBytesReceived },
};
let mut ptr = unsafe { (*self.pc.packet.packet).Buffer };
@@ -256,9 +251,9 @@ impl<'a> DataLinkChannelIterator<'a> for DataLinkChannelIteratorImpl<'a> {
let (start, len) = self.packets.pop_front().unwrap();
let slice = unsafe {
let data = (*self.pc.packet.packet).Buffer as usize + start;
- mem::transmute(Slice { data: data as *const u8, len: len } )
+ slice::from_raw_parts(data as *const u8, len)
};
- Ok(EthernetPacket::new(slice))
+ Ok(EthernetPacket::new(slice).unwrap())
}
}
diff --git a/src/lib.rs b/src/lib.rs
index e804c87..707d5a9 100644
@@ -103,7 +103,7 @@
// FIXME Remove this once the std lib has stabilised
#![feature(custom_attribute, ip_addr, libc, plugin, slice_bytes,
- slice_patterns, vec_push_all)]
+ slice_patterns, vec_push_all, lookup_host)]
#![plugin(pnet_macros)]
#![cfg_attr(test, feature(str_char))]
#![cfg_attr(any(target_os = "freebsd", target_os = "macos"), feature(clone_from_slice))]
diff --git a/src/test.rs b/src/test.rs
index 7d0a50c..926f7ed 100644
@@ -267,11 +267,31 @@ fn layer2() {
const MIN_PACKET_SIZE: usize = 64;
const ETHERNET_HEADER_LEN: usize = 14;
+ #[cfg(windows)]
fn get_test_interface() -> util::NetworkInterface {
use std::clone::Clone;
use std::env;
+ let interfaces = util::get_network_interfaces();
- (*(&util::get_network_interfaces()[..]).iter()
+ interfaces.iter()
+ .filter(|x| {
+ match env::var("PNET_TEST_IFACE") {
+ Ok(name) => x.name == name,
+ Err(_) => true
+ }
+ })
+ .next()
+ .unwrap()
+ .clone()
+ }
+
+ #[cfg(not(windows))]
+ fn get_test_interface() -> util::NetworkInterface {
+ use std::clone::Clone;
+ use std::env;
+ let interfaces = util::get_network_interfaces();
+
+ interfaces.iter()
.filter(|x| {
match env::var("PNET_TEST_IFACE") {
Ok(name) => x.name == name,
@@ -279,7 +299,7 @@ fn layer2() {
}
})
.next()
- .unwrap())
+ .unwrap()
.clone()
}
@@ -353,7 +373,7 @@ fn check_test_environment() {
test_iface();
- #[cfg(not(target_os = "linux"))]
+ #[cfg(all(not(windows), not(target_os = "linux")))]
fn test_iface() {
let iface = env::var("PNET_TEST_IFACE");
if !iface.is_ok() {
@@ -361,6 +381,6 @@ fn check_test_environment() {
}
}
- #[cfg(target_os = "linux")]
+ #[cfg(any(windows, target_os = "linux"))]
fn test_iface() {}
}
diff --git a/src/transport.rs b/src/transport.rs
index 408e70c..b3e56f6 100644
@@ -68,6 +68,12 @@ pub struct TransportReceiver {
channel_type: TransportChannelType
}
+#[cfg(windows)]
+const INVALID_SOCKET: libc::SOCKET = libc::INVALID_SOCKET;
+
+#[cfg(not(windows))]
+const INVALID_SOCKET: libc::c_int = -1;
+
/// Create a new (TransportSender, TransportReceiver) pair
///
/// This allows for sending and receiving packets at the transport layer. The buffer size should be
@@ -80,6 +86,10 @@ pub struct TransportReceiver {
/// header when sending.
pub fn transport_channel(buffer_size: usize, channel_type: TransportChannelType)
-> io::Result<(TransportSender, TransportReceiver)> {
+ use std::net;
+ // This hack makes sure that winsock is initialised
+ let _ = net::lookup_host("\0");
+
let socket = unsafe {
match channel_type {
Layer4(Ipv4(IpNextHeaderProtocol(proto))) | Layer3(IpNextHeaderProtocol(proto))
@@ -88,7 +98,7 @@ pub fn transport_channel(buffer_size: usize, channel_type: TransportChannelType)
=> libc::socket(libc::AF_INET6, libc::SOCK_RAW, proto as libc::c_int),
}
};
- if socket != -1 {
+ if socket != INVALID_SOCKET {
if match channel_type { Layer3(_) | Layer4(Ipv4(_)) => true, _ => false } {
let hincl: libc::c_int = match channel_type { Layer4(..) => 0, _ => 1 };
let res = unsafe {
diff --git a/src/util.rs b/src/util.rs
index c35a89b..9901de9 100644
@@ -12,12 +12,14 @@ extern crate libc;
use packet::PrimitiveValues;
+use std::ffi::{CStr};
use std::fmt;
-use std::str::FromStr;
+use std::str::{from_utf8_unchecked, FromStr};
use std::mem;
use std::u8;
use std::net::IpAddr;
+
#[cfg(not(windows))] use internal;
/// A MAC address
@@ -194,8 +196,7 @@ pub fn get_network_interfaces() -> Vec<NetworkInterface> {
#[cfg(not(windows))]
fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
- use std::ffi::{CStr, CString};
- use std::str::from_utf8_unchecked;
+ use std::ffi::CString;
let mut ifaces: Vec<NetworkInterface> = Vec::new();
unsafe {
@@ -255,9 +256,6 @@ fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
#[cfg(windows)]
fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
- use std::ffi::c_str_to_bytes;
- use std::str::from_utf8;
-
use bindings::winpcap;
let mut adapters_size = 0u32;
@@ -271,7 +269,6 @@ fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
);
}
-
let vec_size = adapters_size / mem::size_of::<winpcap::IP_ADAPTER_INFO>() as u32;
let mut adapters = Vec::with_capacity(vec_size as usize);
@@ -296,17 +293,21 @@ fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
let mut ip_cursor = unsafe { &mut (*cursor).IpAddressList as winpcap::PIP_ADDR_STRING};
let mut ips: Vec<IpAddr> = Vec::new();
while !ip_cursor.is_null() {
- let ref ip_str_ptr = unsafe { &(*ip_cursor) }.IpAddress.String.as_ptr() as *const i8;
- let ip_str = from_utf8(unsafe { c_str_to_bytes(ip_str_ptr) }).unwrap();
+ let ip_str_ptr = unsafe { &(*ip_cursor) }.IpAddress.String.as_ptr() as *const i8;
+ let bytes = unsafe { CStr::from_ptr(ip_str_ptr).to_bytes() };
+ let ip_str = unsafe { from_utf8_unchecked(bytes).to_owned() };
ips.push(ip_str.parse().unwrap());
ip_cursor = unsafe { (*ip_cursor).Next };
}
unsafe {
- let ref name_str_ptr =(*cursor).AdapterName.as_ptr() as *const i8;
+ let name_str_ptr = (*cursor).AdapterName.as_ptr() as *const i8;
+
+ let bytes = CStr::from_ptr(name_str_ptr).to_bytes();
+ let name_str = from_utf8_unchecked(bytes).to_owned();
all_ifaces.push(NetworkInterface {
- name: String::from_utf8_unchecked(c_str_to_bytes(name_str_ptr).to_owned()),
+ name: name_str,
index: (*cursor).Index,
mac: Some(mac),
ips: Some(ips),
@@ -329,17 +330,17 @@ fn get_network_interfaces_impl() -> Vec<NetworkInterface> {
panic!("FIXME [windows] unable to get interface list");
}
- let buf_str = from_utf8(&buf).unwrap();
- let iface_names = buf_str.split_str("\0\0").next();
+ let buf_str = unsafe { from_utf8_unchecked(&buf) };
+ let iface_names = buf_str.split("\0\0").next();
let mut vec = Vec::new();
// Return only supported adapters
match iface_names {
Some(iface_names) => {
for iface in iface_names.split('\0') {
- let name = iface.to_string();
+ let name = iface.to_owned();
let next = all_ifaces.iter()
- .filter(|x| name.as_slice().ends_with(x.name.as_slice()))
+ .filter(|x| name[..].ends_with(&x.name[..]))
.next();
if next.is_some() {
let mut iface = next.unwrap().clone();