-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpacket_socket.rs
76 lines (63 loc) · 2.03 KB
/
packet_socket.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#![allow(unsafe_code)]
use std::io;
use std::time::Duration;
use rustix::fd::OwnedFd;
use rustix::net::{
eth, recv, send, socket_with, AddressFamily, RecvFlags, SendFlags, SocketFlags, SocketType,
};
use super::{sys, Event};
use super::{HardwareType, NetDev};
/// A socket of the AF_PACKET family. [Read more][packet]
///
/// [packet]: https://man7.org/linux/man-pages/man7/packet.7.html
#[derive(Debug)]
pub struct PacketSocket {
fd: OwnedFd,
mtu: usize,
hw_type: HardwareType,
}
impl PacketSocket {
/// Creates a socket with family `AF_PACKET` and binds it to the interface called `name`.
///
/// Requires superuser privileges or the `CAP_NET_RAW` capability.
pub fn bind(name: &str, hw_type: HardwareType) -> io::Result<Self> {
let (type_, protocol) = match hw_type {
HardwareType::Opaque => (SocketType::DGRAM, eth::ALL),
HardwareType::EthernetII => (SocketType::RAW, eth::ALL),
HardwareType::Ieee802154 => (SocketType::RAW, eth::IEEE802154),
};
let fd = socket_with(
AddressFamily::PACKET,
type_,
SocketFlags::NONBLOCK,
Some(protocol),
)?;
let ifreq_name = sys::ifreq_name(name);
sys::bind_interface(&fd, protocol, ifreq_name)?;
let mtu = sys::ioctl_siocgifmtu(&fd, ifreq_name)?;
Ok(PacketSocket { fd, mtu, hw_type })
}
}
impl NetDev for PacketSocket {
type Error = io::Error;
#[inline]
fn send(&self, buf: &[u8]) -> io::Result<usize> {
send(&self.fd, buf, SendFlags::empty()).map_err(io::Error::from)
}
#[inline]
fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
recv(&self.fd, buf, RecvFlags::empty()).map_err(io::Error::from)
}
#[inline]
fn poll(&self, interest: Event, timeout: Option<Duration>) -> io::Result<Event> {
sys::poll(&self.fd, interest, timeout)
}
#[inline]
fn mtu(&self) -> usize {
self.mtu
}
#[inline]
fn hw_type(&self) -> HardwareType {
self.hw_type
}
}