1pub use nix::sys::socket::LinkAddr;
22pub type IfIndex = usize;
23
24#[derive(Debug, PartialEq, Eq, Hash)]
26pub struct EtherType(pub u16);
27impl EtherType {
28 pub const UNSPECIFIED: EtherType = EtherType(0);
29 pub const IP: EtherType = EtherType(0x0800);
30 pub const ARP: EtherType = EtherType(0x0806);
31 pub const IPV6: EtherType = EtherType(0x86DD);
32 pub const LLDP: EtherType = EtherType(0x88CC);
33}
34
35impl From<EtherType> for u16 {
36 fn from(e: EtherType) -> u16 {
37 e.0
38 }
39}
40
41impl From<u16> for EtherType {
42 fn from(e: u16) -> EtherType {
43 EtherType(e)
44 }
45}
46
47#[derive(Debug, Hash, Eq, PartialEq)]
49pub struct ArpHrd(pub u16);
50#[allow(dead_code)]
51impl ArpHrd {
52 const UNSPECIFIED: ArpHrd = ArpHrd(0);
53 const ETHERNET: ArpHrd = ArpHrd(1);
54}
55
56impl From<ArpHrd> for u16 {
57 fn from(a: ArpHrd) -> u16 {
58 a.0
59 }
60}
61
62impl From<u16> for ArpHrd {
63 fn from(u: u16) -> Self {
64 Self(u)
65 }
66}
67
68#[derive(Debug, Hash, Eq, PartialEq)]
69pub struct PacketType(pub u8);
70#[allow(dead_code)]
71impl PacketType {
72 const HOST: PacketType = PacketType(0);
73 const BROADCAST: PacketType = PacketType(1);
74 const MULTICAST: PacketType = PacketType(2);
75 const OTHER_HOST: PacketType = PacketType(3);
76 const OUTGOING: PacketType = PacketType(4);
77 const LOOPBACK: PacketType = PacketType(5);
78 const USER: PacketType = PacketType(6);
79 const KERNEL: PacketType = PacketType(7);
80 const FAST_ROUTE: PacketType = PacketType(8);
81}
82
83impl From<PacketType> for u8 {
84 fn from(p: PacketType) -> u8 {
85 p.0
86 }
87}
88
89impl From<u8> for PacketType {
90 fn from(p: u8) -> PacketType {
91 Self(p)
92 }
93}
94
95pub fn new_linkaddr(
97 protocol: EtherType,
98 ifindex: IfIndex,
99 hatype: ArpHrd,
100 pkttype: PacketType,
101 addr: &[u8],
102) -> LinkAddr {
103 let mut sll_addr = [0_u8; 8];
104 sll_addr[..addr.len()].copy_from_slice(addr);
105 let ll = nix::libc::sockaddr_ll {
107 sll_family: nix::libc::AF_PACKET as u16,
108 sll_protocol: u16::to_be(protocol.into()),
109 sll_ifindex: ifindex as i32,
110 sll_hatype: hatype.into(),
111 sll_pkttype: pkttype.into(),
112 sll_halen: addr.len() as u8,
113 sll_addr,
114 };
115 unsafe {
116 use nix::sys::socket::SockaddrLike as _;
117 LinkAddr::from_raw(
118 &ll as *const _ as *const _,
119 Some(
120 std::mem::size_of_val(&ll) as u32, ),
122 )
123 .unwrap()
124 }
125}
126
127pub fn linkaddr_for_ifindex(ifindex: IfIndex) -> LinkAddr {
128 new_linkaddr(
129 EtherType::UNSPECIFIED,
130 ifindex,
131 ArpHrd::UNSPECIFIED,
132 PacketType::HOST,
133 &[0; 8],
134 )
135}