1use std::{
2 mem,
3 net::{IpAddr, Ipv6Addr, SocketAddr},
4 ptr,
5};
6
7use bytes::{Bytes, BytesMut};
8
9#[derive(Copy, Clone)]
10#[repr(align(8))] pub struct Aligned<T>(pub T);
12
13pub struct Encoder<'a> {
18 hdr: &'a mut libc::msghdr,
19 cmsg: Option<&'a mut libc::cmsghdr>,
20 len: usize,
21}
22
23impl<'a> Encoder<'a> {
24 pub unsafe fn new(hdr: &'a mut libc::msghdr) -> Self {
29 Self {
30 cmsg: libc::CMSG_FIRSTHDR(hdr).as_mut(),
31 hdr,
32 len: 0,
33 }
34 }
35
36 #[allow(clippy::unnecessary_cast)]
42 pub fn push<T: Copy + ?Sized>(&mut self, level: libc::c_int, ty: libc::c_int, value: T) {
43 assert!(mem::align_of::<T>() <= mem::align_of::<libc::cmsghdr>());
44 let space = unsafe { libc::CMSG_SPACE(mem::size_of_val(&value) as _) as usize };
45 assert!(
46 self.hdr.msg_controllen as usize >= self.len + space,
47 "control message buffer too small. Required: {}, Available: {}",
48 self.len + space,
49 self.hdr.msg_controllen
50 );
51 let cmsg = self.cmsg.take().expect("no control buffer space remaining");
52 cmsg.cmsg_level = level;
53 cmsg.cmsg_type = ty;
54 cmsg.cmsg_len = unsafe { libc::CMSG_LEN(mem::size_of_val(&value) as _) } as _;
55 unsafe {
56 ptr::write(libc::CMSG_DATA(cmsg) as *const T as *mut T, value);
57 }
58 self.len += space;
59 self.cmsg = unsafe { libc::CMSG_NXTHDR(self.hdr, cmsg).as_mut() };
60 }
61
62 pub fn finish(self) {
64 }
66}
67
68impl<'a> Drop for Encoder<'a> {
71 fn drop(&mut self) {
72 self.hdr.msg_controllen = self.len as _;
73 }
74}
75
76#[allow(clippy::unnecessary_cast)]
80pub unsafe fn decode<T: Copy>(cmsg: &libc::cmsghdr) -> T {
81 assert!(mem::align_of::<T>() <= mem::align_of::<libc::cmsghdr>());
82 debug_assert_eq!(
83 cmsg.cmsg_len as usize,
84 libc::CMSG_LEN(mem::size_of::<T>() as _) as usize
85 );
86 ptr::read(libc::CMSG_DATA(cmsg) as *const T)
87}
88
89pub struct Iter<'a> {
90 hdr: &'a libc::msghdr,
91 cmsg: Option<&'a libc::cmsghdr>,
92}
93
94impl<'a> Iter<'a> {
95 pub unsafe fn new(hdr: &'a libc::msghdr) -> Self {
101 Self {
102 hdr,
103 cmsg: libc::CMSG_FIRSTHDR(hdr).as_ref(),
104 }
105 }
106}
107
108impl<'a> Iterator for Iter<'a> {
109 type Item = &'a libc::cmsghdr;
110 fn next(&mut self) -> Option<&'a libc::cmsghdr> {
111 let current = self.cmsg.take()?;
112 self.cmsg = unsafe { libc::CMSG_NXTHDR(self.hdr, current).as_ref() };
113 Some(current)
114 }
115}
116
117#[repr(u8)]
119#[derive(Debug, Copy, Clone, Eq, PartialEq)]
120pub enum EcnCodepoint {
121 #[doc(hidden)]
122 Ect0 = 0b10,
123 #[doc(hidden)]
124 Ect1 = 0b01,
125 #[doc(hidden)]
126 Ce = 0b11,
127}
128
129impl EcnCodepoint {
130 pub fn from_bits(x: u8) -> Option<Self> {
132 use self::EcnCodepoint::*;
133 Some(match x & 0b11 {
134 0b10 => Ect0,
135 0b01 => Ect1,
136 0b11 => Ce,
137 _ => {
138 return None;
139 }
140 })
141 }
142}
143
144#[derive(Debug)]
146pub struct Transmit<B> {
147 pub dst: SocketAddr,
149 pub ecn: Option<EcnCodepoint>,
151 pub contents: B,
153 pub segment_size: Option<usize>,
156 pub src: Option<Source>,
158}
159
160impl<B: AsPtr<u8>> Transmit<B> {
161 pub fn new(dst: SocketAddr, contents: B) -> Self {
162 Self {
163 dst,
164 contents,
165 ecn: None,
166 segment_size: None,
167 src: None,
168 }
169 }
170 pub fn src_ip(self, src_ip: Source) -> Self {
171 Transmit {
172 src: Some(src_ip),
173 ..self
174 }
175 }
176 pub fn segment_size(self, size: usize) -> Self {
177 Transmit {
178 segment_size: Some(size),
179 ..self
180 }
181 }
182 pub fn ecn(self, ecn: EcnCodepoint) -> Self {
183 Transmit {
184 ecn: Some(ecn),
185 ..self
186 }
187 }
188}
189
190#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
192pub enum Source {
193 Ip(IpAddr),
195 Interface(u32),
197 InterfaceV6(u32, Ipv6Addr),
199}
200
201pub trait AsPtr<T> {
204 fn as_ptr(&self) -> *const T;
205 fn len(&self) -> usize;
206 fn is_empty(&self) -> bool {
207 self.len() == 0
208 }
209}
210
211impl<T, const N: usize> AsPtr<T> for &[T; N] {
212 fn as_ptr(&self) -> *const T {
213 self.as_slice().as_ptr()
214 }
215
216 fn len(&self) -> usize {
217 N
218 }
219}
220
221impl<T, const N: usize> AsPtr<T> for [T; N] {
222 fn as_ptr(&self) -> *const T {
223 self.as_slice().as_ptr()
224 }
225
226 fn len(&self) -> usize {
227 N
228 }
229}
230
231impl<T> AsPtr<T> for Vec<T> {
232 fn as_ptr(&self) -> *const T {
233 <Vec<T>>::as_ptr(self)
234 }
235 fn len(&self) -> usize {
236 <Vec<T>>::len(self)
237 }
238}
239
240impl<T> AsPtr<T> for [T] {
241 fn as_ptr(&self) -> *const T {
242 <[T]>::as_ptr(self)
243 }
244 fn len(&self) -> usize {
245 <[T]>::len(self)
246 }
247}
248
249impl AsPtr<u8> for BytesMut {
250 fn as_ptr(&self) -> *const u8 {
251 <[u8]>::as_ptr(self.as_ref())
252 }
253 fn len(&self) -> usize {
254 self.len()
255 }
256}
257
258impl AsPtr<u8> for Bytes {
259 fn as_ptr(&self) -> *const u8 {
260 <[u8]>::as_ptr(self.as_ref())
261 }
262 fn len(&self) -> usize {
263 self.len()
264 }
265}