Fix BPF header length on OpenBSD.
The actual header length may be larger than the bpf_hdr struct due to aligning:37ecb4d066/sys/net/bpf.c (L1649)
8f02f2a044/bsd/net/bpf.c (L3580)
Tests are only valid for 32 and 64 bit architectures. I did not bother guarding them with additional cfg flags.
This commit is contained in:
parent
5388ef1f1d
commit
4ac265fb46
|
@ -1,8 +1,10 @@
|
|||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
|
||||
use libc;
|
||||
|
||||
use crate::wire::ETHERNET_HEADER_LEN;
|
||||
use super::{ifreq, ifreq_for};
|
||||
|
||||
/// set interface
|
||||
|
@ -14,9 +16,19 @@ const BIOCGBLEN: libc::c_ulong = 0x40044266;
|
|||
/// set immediate/nonblocking read
|
||||
#[cfg(any(target_os = "macos", target_os = "openbsd"))]
|
||||
const BIOCIMMEDIATE: libc::c_ulong = 0x80044270;
|
||||
// TODO: check if this is same for OSes other than macos
|
||||
/// set bpf_hdr struct size
|
||||
#[cfg(target_os = "macos")]
|
||||
const SIZEOF_BPF_HDR: usize = 18;
|
||||
/// set bpf_hdr struct size
|
||||
#[cfg(target_os = "openbsd")]
|
||||
const SIZEOF_BPF_HDR: usize = 24;
|
||||
/// The actual header length may be larger than the bpf_hdr struct due to aligning
|
||||
/// see https://github.com/openbsd/src/blob/37ecb4d066e5566411cc16b362d3960c93b1d0be/sys/net/bpf.c#L1649
|
||||
/// and https://github.com/apple/darwin-xnu/blob/8f02f2a044b9bb1ad951987ef5bab20ec9486310/bsd/net/bpf.c#L3580
|
||||
#[cfg(any(target_os = "macos", target_os = "openbsd"))]
|
||||
const BPF_HDRLEN: usize = 18;
|
||||
const BPF_HDRLEN: usize = (((SIZEOF_BPF_HDR + ETHERNET_HEADER_LEN) + mem::align_of::<u32>() - 1)
|
||||
& !(mem::align_of::<u32>() - 1))
|
||||
- ETHERNET_HEADER_LEN;
|
||||
|
||||
macro_rules! try_ioctl {
|
||||
($fd:expr,$cmd:expr,$req:expr) => {
|
||||
|
@ -145,3 +157,20 @@ impl Drop for BpfDevice {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn test_aligned_bpf_hdr_len() {
|
||||
assert_eq!(18, BPF_HDRLEN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "openbsd")]
|
||||
fn test_aligned_bpf_hdr_len() {
|
||||
assert_eq!(26, BPF_HDRLEN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,9 @@ mod field {
|
|||
pub const PAYLOAD: Rest = 14..;
|
||||
}
|
||||
|
||||
/// The Ethernet header length
|
||||
pub const HEADER_LEN: usize = field::PAYLOAD.start;
|
||||
|
||||
impl<T: AsRef<[u8]>> Frame<T> {
|
||||
/// Imbue a raw octet buffer with Ethernet frame structure.
|
||||
pub fn new_unchecked(buffer: T) -> Frame<T> {
|
||||
|
@ -111,7 +114,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
|
|||
/// Returns `Err(Error::Truncated)` if the buffer is too short.
|
||||
pub fn check_len(&self) -> Result<()> {
|
||||
let len = self.buffer.as_ref().len();
|
||||
if len < field::PAYLOAD.start {
|
||||
if len < HEADER_LEN {
|
||||
Err(Error::Truncated)
|
||||
} else {
|
||||
Ok(())
|
||||
|
@ -125,13 +128,13 @@ impl<T: AsRef<[u8]>> Frame<T> {
|
|||
|
||||
/// Return the length of a frame header.
|
||||
pub fn header_len() -> usize {
|
||||
field::PAYLOAD.start
|
||||
HEADER_LEN
|
||||
}
|
||||
|
||||
/// Return the length of a buffer required to hold a packet with the payload
|
||||
/// of a given length.
|
||||
pub fn buffer_len(payload_len: usize) -> usize {
|
||||
field::PAYLOAD.start + payload_len
|
||||
HEADER_LEN + payload_len
|
||||
}
|
||||
|
||||
/// Return the destination address field.
|
||||
|
@ -262,7 +265,7 @@ impl Repr {
|
|||
|
||||
/// Return the length of a header that will be emitted from this high-level representation.
|
||||
pub fn buffer_len(&self) -> usize {
|
||||
field::PAYLOAD.start
|
||||
HEADER_LEN
|
||||
}
|
||||
|
||||
/// Emit a high-level representation into an Ethernet II frame.
|
||||
|
|
|
@ -119,6 +119,7 @@ pub use self::pretty_print::PrettyPrinter;
|
|||
pub use self::ethernet::{EtherType as EthernetProtocol,
|
||||
Address as EthernetAddress,
|
||||
Frame as EthernetFrame,
|
||||
HEADER_LEN as ETHERNET_HEADER_LEN,
|
||||
Repr as EthernetRepr};
|
||||
|
||||
#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))]
|
||||
|
|
Loading…
Reference in New Issue