1use core::cmp::min;
2#[cfg(feature = "async")]
3use core::task::Waker;
4
5use crate::iface::Context;
6use crate::phy::ChecksumCapabilities;
7use crate::socket::PollAt;
8#[cfg(feature = "async")]
9use crate::socket::WakerRegistration;
10use crate::storage::{PacketBuffer, PacketMetadata};
11use crate::{Error, Result};
12
13use crate::wire::{IpProtocol, IpRepr, IpVersion};
14#[cfg(feature = "proto-ipv4")]
15use crate::wire::{Ipv4Packet, Ipv4Repr};
16#[cfg(feature = "proto-ipv6")]
17use crate::wire::{Ipv6Packet, Ipv6Repr};
18
19pub type RawPacketMetadata = PacketMetadata<()>;
21
22pub type RawSocketBuffer<'a> = PacketBuffer<'a, ()>;
24
25#[derive(Debug)]
30pub struct RawSocket<'a> {
31 ip_version: IpVersion,
32 ip_protocol: IpProtocol,
33 rx_buffer: RawSocketBuffer<'a>,
34 tx_buffer: RawSocketBuffer<'a>,
35 #[cfg(feature = "async")]
36 rx_waker: WakerRegistration,
37 #[cfg(feature = "async")]
38 tx_waker: WakerRegistration,
39}
40
41impl<'a> RawSocket<'a> {
42 pub fn new(
45 ip_version: IpVersion,
46 ip_protocol: IpProtocol,
47 rx_buffer: RawSocketBuffer<'a>,
48 tx_buffer: RawSocketBuffer<'a>,
49 ) -> RawSocket<'a> {
50 RawSocket {
51 ip_version,
52 ip_protocol,
53 rx_buffer,
54 tx_buffer,
55 #[cfg(feature = "async")]
56 rx_waker: WakerRegistration::new(),
57 #[cfg(feature = "async")]
58 tx_waker: WakerRegistration::new(),
59 }
60 }
61
62 #[cfg(feature = "async")]
75 pub fn register_recv_waker(&mut self, waker: &Waker) {
76 self.rx_waker.register(waker)
77 }
78
79 #[cfg(feature = "async")]
93 pub fn register_send_waker(&mut self, waker: &Waker) {
94 self.tx_waker.register(waker)
95 }
96
97 #[inline]
99 pub fn ip_version(&self) -> IpVersion {
100 self.ip_version
101 }
102
103 #[inline]
105 pub fn ip_protocol(&self) -> IpProtocol {
106 self.ip_protocol
107 }
108
109 #[inline]
111 pub fn can_send(&self) -> bool {
112 !self.tx_buffer.is_full()
113 }
114
115 #[inline]
117 pub fn can_recv(&self) -> bool {
118 !self.rx_buffer.is_empty()
119 }
120
121 #[inline]
123 pub fn packet_recv_capacity(&self) -> usize {
124 self.rx_buffer.packet_capacity()
125 }
126
127 #[inline]
129 pub fn packet_send_capacity(&self) -> usize {
130 self.tx_buffer.packet_capacity()
131 }
132
133 #[inline]
135 pub fn payload_recv_capacity(&self) -> usize {
136 self.rx_buffer.payload_capacity()
137 }
138
139 #[inline]
141 pub fn payload_send_capacity(&self) -> usize {
142 self.tx_buffer.payload_capacity()
143 }
144
145 pub fn send(&mut self, size: usize) -> Result<&mut [u8]> {
157 let packet_buf = self.tx_buffer.enqueue(size, ())?;
158
159 net_trace!(
160 "raw:{}:{}: buffer to send {} octets",
161 self.ip_version,
162 self.ip_protocol,
163 packet_buf.len()
164 );
165 Ok(packet_buf)
166 }
167
168 pub fn send_slice(&mut self, data: &[u8]) -> Result<()> {
172 self.send(data.len())?.copy_from_slice(data);
173 Ok(())
174 }
175
176 pub fn recv(&mut self) -> Result<&[u8]> {
183 let ((), packet_buf) = self.rx_buffer.dequeue()?;
184
185 net_trace!(
186 "raw:{}:{}: receive {} buffered octets",
187 self.ip_version,
188 self.ip_protocol,
189 packet_buf.len()
190 );
191 Ok(packet_buf)
192 }
193
194 pub fn recv_slice(&mut self, data: &mut [u8]) -> Result<usize> {
198 let buffer = self.recv()?;
199 let length = min(data.len(), buffer.len());
200 data[..length].copy_from_slice(&buffer[..length]);
201 Ok(length)
202 }
203
204 pub(crate) fn accepts(&self, ip_repr: &IpRepr) -> bool {
205 if ip_repr.version() != self.ip_version {
206 return false;
207 }
208 if ip_repr.protocol() != self.ip_protocol {
209 return false;
210 }
211
212 true
213 }
214
215 pub(crate) fn process(
216 &mut self,
217 cx: &mut Context,
218 ip_repr: &IpRepr,
219 payload: &[u8],
220 ) -> Result<()> {
221 debug_assert!(self.accepts(ip_repr));
222
223 let header_len = ip_repr.buffer_len();
224 let total_len = header_len + payload.len();
225 let packet_buf = self.rx_buffer.enqueue(total_len, ())?;
226 ip_repr.emit(&mut packet_buf[..header_len], &cx.checksum_caps());
227 packet_buf[header_len..].copy_from_slice(payload);
228
229 net_trace!(
230 "raw:{}:{}: receiving {} octets",
231 self.ip_version,
232 self.ip_protocol,
233 packet_buf.len()
234 );
235
236 #[cfg(feature = "async")]
237 self.rx_waker.wake();
238
239 Ok(())
240 }
241
242 pub(crate) fn dispatch<F>(&mut self, cx: &mut Context, emit: F) -> Result<()>
243 where
244 F: FnOnce(&mut Context, (IpRepr, &[u8])) -> Result<()>,
245 {
246 fn prepare<'a>(
247 protocol: IpProtocol,
248 buffer: &'a mut [u8],
249 _checksum_caps: &ChecksumCapabilities,
250 ) -> Result<(IpRepr, &'a [u8])> {
251 match IpVersion::of_packet(buffer)? {
252 #[cfg(feature = "proto-ipv4")]
253 IpVersion::Ipv4 => {
254 let mut packet = Ipv4Packet::new_checked(buffer)?;
255 if packet.protocol() != protocol {
256 return Err(Error::Unaddressable);
257 }
258 if _checksum_caps.ipv4.tx() {
259 packet.fill_checksum();
260 } else {
261 packet.set_checksum(0);
264 }
265
266 let packet = Ipv4Packet::new_checked(&*packet.into_inner())?;
267 let ipv4_repr = Ipv4Repr::parse(&packet, _checksum_caps)?;
268 Ok((IpRepr::Ipv4(ipv4_repr), packet.payload()))
269 }
270 #[cfg(feature = "proto-ipv6")]
271 IpVersion::Ipv6 => {
272 let packet = Ipv6Packet::new_checked(buffer)?;
273 if packet.next_header() != protocol {
274 return Err(Error::Unaddressable);
275 }
276 let packet = Ipv6Packet::new_unchecked(&*packet.into_inner());
277 let ipv6_repr = Ipv6Repr::parse(&packet)?;
278 Ok((IpRepr::Ipv6(ipv6_repr), packet.payload()))
279 }
280 IpVersion::Unspecified => unreachable!(),
281 }
282 }
283
284 let ip_protocol = self.ip_protocol;
285 let ip_version = self.ip_version;
286 self.tx_buffer.dequeue_with(|&mut (), packet_buf| {
287 match prepare(ip_protocol, packet_buf, &cx.checksum_caps()) {
288 Ok((ip_repr, raw_packet)) => {
289 net_trace!(
290 "raw:{}:{}: sending {} octets",
291 ip_version,
292 ip_protocol,
293 ip_repr.buffer_len() + raw_packet.len()
294 );
295 emit(cx, (ip_repr, raw_packet))
296 }
297 Err(error) => {
298 net_debug!(
299 "raw:{}:{}: dropping outgoing packet ({})",
300 ip_version,
301 ip_protocol,
302 error
303 );
304 Ok(())
306 }
307 }
308 })?;
309
310 #[cfg(feature = "async")]
311 self.tx_waker.wake();
312
313 Ok(())
314 }
315
316 pub(crate) fn poll_at(&self, _cx: &mut Context) -> PollAt {
317 if self.tx_buffer.is_empty() {
318 PollAt::Ingress
319 } else {
320 PollAt::Now
321 }
322 }
323}
324
325#[cfg(test)]
326mod test {
327 use super::*;
328 use crate::wire::IpRepr;
329 #[cfg(feature = "proto-ipv4")]
330 use crate::wire::{Ipv4Address, Ipv4Repr};
331 #[cfg(feature = "proto-ipv6")]
332 use crate::wire::{Ipv6Address, Ipv6Repr};
333
334 fn buffer(packets: usize) -> RawSocketBuffer<'static> {
335 RawSocketBuffer::new(
336 vec![RawPacketMetadata::EMPTY; packets],
337 vec![0; 48 * packets],
338 )
339 }
340
341 #[cfg(feature = "proto-ipv4")]
342 mod ipv4_locals {
343 use super::*;
344
345 pub fn socket(
346 rx_buffer: RawSocketBuffer<'static>,
347 tx_buffer: RawSocketBuffer<'static>,
348 ) -> RawSocket<'static> {
349 RawSocket::new(
350 IpVersion::Ipv4,
351 IpProtocol::Unknown(IP_PROTO),
352 rx_buffer,
353 tx_buffer,
354 )
355 }
356
357 pub const IP_PROTO: u8 = 63;
358 pub const HEADER_REPR: IpRepr = IpRepr::Ipv4(Ipv4Repr {
359 src_addr: Ipv4Address([10, 0, 0, 1]),
360 dst_addr: Ipv4Address([10, 0, 0, 2]),
361 protocol: IpProtocol::Unknown(IP_PROTO),
362 payload_len: 4,
363 hop_limit: 64,
364 });
365 pub const PACKET_BYTES: [u8; 24] = [
366 0x45, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x00, 0x40, 0x3f, 0x00, 0x00, 0x0a, 0x00,
367 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0xaa, 0x00, 0x00, 0xff,
368 ];
369 pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
370 }
371
372 #[cfg(feature = "proto-ipv6")]
373 mod ipv6_locals {
374 use super::*;
375
376 pub fn socket(
377 rx_buffer: RawSocketBuffer<'static>,
378 tx_buffer: RawSocketBuffer<'static>,
379 ) -> RawSocket<'static> {
380 RawSocket::new(
381 IpVersion::Ipv6,
382 IpProtocol::Unknown(IP_PROTO),
383 rx_buffer,
384 tx_buffer,
385 )
386 }
387
388 pub const IP_PROTO: u8 = 63;
389 pub const HEADER_REPR: IpRepr = IpRepr::Ipv6(Ipv6Repr {
390 src_addr: Ipv6Address([
391 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x01,
393 ]),
394 dst_addr: Ipv6Address([
395 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x02,
397 ]),
398 next_header: IpProtocol::Unknown(IP_PROTO),
399 payload_len: 4,
400 hop_limit: 64,
401 });
402
403 pub const PACKET_BYTES: [u8; 44] = [
404 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0x40, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x80, 0x00, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xaa, 0x00,
407 0x00, 0xff,
408 ];
409
410 pub const PACKET_PAYLOAD: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
411 }
412
413 macro_rules! reusable_ip_specific_tests {
414 ($module:ident, $socket:path, $hdr:path, $packet:path, $payload:path) => {
415 mod $module {
416 use super::*;
417
418 #[test]
419 fn test_send_truncated() {
420 let mut socket = $socket(buffer(0), buffer(1));
421 assert_eq!(socket.send_slice(&[0; 56][..]), Err(Error::Truncated));
422 }
423
424 #[test]
425 fn test_send_dispatch() {
426 let mut socket = $socket(buffer(0), buffer(1));
427 let mut cx = Context::mock();
428
429 assert!(socket.can_send());
430 assert_eq!(
431 socket.dispatch(&mut cx, |_, _| unreachable!()),
432 Err(Error::Exhausted)
433 );
434
435 assert_eq!(socket.send_slice(&$packet[..]), Ok(()));
436 assert_eq!(socket.send_slice(b""), Err(Error::Exhausted));
437 assert!(!socket.can_send());
438
439 assert_eq!(
440 socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
441 assert_eq!(ip_repr, $hdr);
442 assert_eq!(ip_payload, &$payload);
443 Err(Error::Unaddressable)
444 }),
445 Err(Error::Unaddressable)
446 );
447 assert!(!socket.can_send());
448
449 assert_eq!(
450 socket.dispatch(&mut cx, |_, (ip_repr, ip_payload)| {
451 assert_eq!(ip_repr, $hdr);
452 assert_eq!(ip_payload, &$payload);
453 Ok(())
454 }),
455 Ok(())
456 );
457 assert!(socket.can_send());
458 }
459
460 #[test]
461 fn test_recv_truncated_slice() {
462 let mut socket = $socket(buffer(1), buffer(0));
463 let mut cx = Context::mock();
464
465 assert!(socket.accepts(&$hdr));
466 assert_eq!(socket.process(&mut cx, &$hdr, &$payload), Ok(()));
467
468 let mut slice = [0; 4];
469 assert_eq!(socket.recv_slice(&mut slice[..]), Ok(4));
470 assert_eq!(&slice, &$packet[..slice.len()]);
471 }
472
473 #[test]
474 fn test_recv_truncated_packet() {
475 let mut socket = $socket(buffer(1), buffer(0));
476 let mut cx = Context::mock();
477
478 let mut buffer = vec![0; 128];
479 buffer[..$packet.len()].copy_from_slice(&$packet[..]);
480
481 assert!(socket.accepts(&$hdr));
482 assert_eq!(
483 socket.process(&mut cx, &$hdr, &buffer),
484 Err(Error::Truncated)
485 );
486 }
487 }
488 };
489 }
490
491 #[cfg(feature = "proto-ipv4")]
492 reusable_ip_specific_tests!(
493 ipv4,
494 ipv4_locals::socket,
495 ipv4_locals::HEADER_REPR,
496 ipv4_locals::PACKET_BYTES,
497 ipv4_locals::PACKET_PAYLOAD
498 );
499
500 #[cfg(feature = "proto-ipv6")]
501 reusable_ip_specific_tests!(
502 ipv6,
503 ipv6_locals::socket,
504 ipv6_locals::HEADER_REPR,
505 ipv6_locals::PACKET_BYTES,
506 ipv6_locals::PACKET_PAYLOAD
507 );
508
509 #[test]
510 #[cfg(feature = "proto-ipv4")]
511 fn test_send_illegal() {
512 #[cfg(feature = "proto-ipv4")]
513 {
514 let mut socket = ipv4_locals::socket(buffer(0), buffer(2));
515 let mut cx = Context::mock();
516
517 let mut wrong_version = ipv4_locals::PACKET_BYTES;
518 Ipv4Packet::new_unchecked(&mut wrong_version).set_version(6);
519
520 assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
521 assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
522
523 let mut wrong_protocol = ipv4_locals::PACKET_BYTES;
524 Ipv4Packet::new_unchecked(&mut wrong_protocol).set_protocol(IpProtocol::Tcp);
525
526 assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
527 assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
528 }
529 #[cfg(feature = "proto-ipv6")]
530 {
531 let mut socket = ipv6_locals::socket(buffer(0), buffer(2));
532 let mut cx = Context::mock();
533
534 let mut wrong_version = ipv6_locals::PACKET_BYTES;
535 Ipv6Packet::new_unchecked(&mut wrong_version[..]).set_version(4);
536
537 assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
538 assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
539
540 let mut wrong_protocol = ipv6_locals::PACKET_BYTES;
541 Ipv6Packet::new_unchecked(&mut wrong_protocol[..]).set_next_header(IpProtocol::Tcp);
542
543 assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
544 assert_eq!(socket.dispatch(&mut cx, |_, _| unreachable!()), Ok(()));
545 }
546 }
547
548 #[test]
549 fn test_recv_process() {
550 #[cfg(feature = "proto-ipv4")]
551 {
552 let mut socket = ipv4_locals::socket(buffer(1), buffer(0));
553 assert!(!socket.can_recv());
554 let mut cx = Context::mock();
555
556 let mut cksumd_packet = ipv4_locals::PACKET_BYTES;
557 Ipv4Packet::new_unchecked(&mut cksumd_packet).fill_checksum();
558
559 assert_eq!(socket.recv(), Err(Error::Exhausted));
560 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
561 assert_eq!(
562 socket.process(
563 &mut cx,
564 &ipv4_locals::HEADER_REPR,
565 &ipv4_locals::PACKET_PAYLOAD
566 ),
567 Ok(())
568 );
569 assert!(socket.can_recv());
570
571 assert!(socket.accepts(&ipv4_locals::HEADER_REPR));
572 assert_eq!(
573 socket.process(
574 &mut cx,
575 &ipv4_locals::HEADER_REPR,
576 &ipv4_locals::PACKET_PAYLOAD
577 ),
578 Err(Error::Exhausted)
579 );
580 assert_eq!(socket.recv(), Ok(&cksumd_packet[..]));
581 assert!(!socket.can_recv());
582 }
583 #[cfg(feature = "proto-ipv6")]
584 {
585 let mut socket = ipv6_locals::socket(buffer(1), buffer(0));
586 assert!(!socket.can_recv());
587 let mut cx = Context::mock();
588
589 assert_eq!(socket.recv(), Err(Error::Exhausted));
590 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
591 assert_eq!(
592 socket.process(
593 &mut cx,
594 &ipv6_locals::HEADER_REPR,
595 &ipv6_locals::PACKET_PAYLOAD
596 ),
597 Ok(())
598 );
599 assert!(socket.can_recv());
600
601 assert!(socket.accepts(&ipv6_locals::HEADER_REPR));
602 assert_eq!(
603 socket.process(
604 &mut cx,
605 &ipv6_locals::HEADER_REPR,
606 &ipv6_locals::PACKET_PAYLOAD
607 ),
608 Err(Error::Exhausted)
609 );
610 assert_eq!(socket.recv(), Ok(&ipv6_locals::PACKET_BYTES[..]));
611 assert!(!socket.can_recv());
612 }
613 }
614
615 #[test]
616 fn test_doesnt_accept_wrong_proto() {
617 #[cfg(feature = "proto-ipv4")]
618 {
619 let socket = RawSocket::new(
620 IpVersion::Ipv4,
621 IpProtocol::Unknown(ipv4_locals::IP_PROTO + 1),
622 buffer(1),
623 buffer(1),
624 );
625 assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
626 #[cfg(feature = "proto-ipv6")]
627 assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
628 }
629 #[cfg(feature = "proto-ipv6")]
630 {
631 let socket = RawSocket::new(
632 IpVersion::Ipv6,
633 IpProtocol::Unknown(ipv6_locals::IP_PROTO + 1),
634 buffer(1),
635 buffer(1),
636 );
637 assert!(!socket.accepts(&ipv6_locals::HEADER_REPR));
638 #[cfg(feature = "proto-ipv4")]
639 assert!(!socket.accepts(&ipv4_locals::HEADER_REPR));
640 }
641 }
642}