1 #[cfg(feature = "proto-igmp")]
2 use std::vec::Vec;
3 
4 use super::*;
5 
6 use crate::iface::Interface;
7 use crate::phy::{ChecksumCapabilities, Loopback};
8 #[cfg(feature = "proto-igmp")]
9 use crate::time::Instant;
10 
11 #[allow(unused)]
fill_slice(s: &mut [u8], val: u8)12 fn fill_slice(s: &mut [u8], val: u8) {
13     for x in s.iter_mut() {
14         *x = val
15     }
16 }
17 
18 #[cfg(feature = "medium-ethernet")]
19 const MEDIUM: Medium = Medium::Ethernet;
20 #[cfg(all(not(feature = "medium-ethernet"), feature = "medium-ip"))]
21 const MEDIUM: Medium = Medium::Ip;
22 #[cfg(all(not(feature = "medium-ethernet"), feature = "medium-ieee802154"))]
23 const MEDIUM: Medium = Medium::Ieee802154;
24 
create<'a>(medium: Medium) -> (Interface, SocketSet<'a>, Loopback)25 fn create<'a>(medium: Medium) -> (Interface, SocketSet<'a>, Loopback) {
26     match medium {
27         #[cfg(feature = "medium-ethernet")]
28         Medium::Ethernet => create_ethernet(),
29         #[cfg(feature = "medium-ip")]
30         Medium::Ip => create_ip(),
31         #[cfg(feature = "medium-ieee802154")]
32         Medium::Ieee802154 => create_ieee802154(),
33     }
34 }
35 
36 #[cfg(feature = "medium-ip")]
37 #[allow(unused)]
create_ip<'a>() -> (Interface, SocketSet<'a>, Loopback)38 fn create_ip<'a>() -> (Interface, SocketSet<'a>, Loopback) {
39     // Create a basic device
40     let mut device = Loopback::new(Medium::Ip);
41 
42     let mut config = Config::new();
43     let mut iface = Interface::new(config, &mut device);
44     iface.update_ip_addrs(|ip_addrs| {
45         #[cfg(feature = "proto-ipv4")]
46         ip_addrs
47             .push(IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8))
48             .unwrap();
49         #[cfg(feature = "proto-ipv6")]
50         ip_addrs
51             .push(IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128))
52             .unwrap();
53         #[cfg(feature = "proto-ipv6")]
54         ip_addrs
55             .push(IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64))
56             .unwrap();
57     });
58 
59     (iface, SocketSet::new(vec![]), device)
60 }
61 
62 #[cfg(feature = "medium-ethernet")]
create_ethernet<'a>() -> (Interface, SocketSet<'a>, Loopback)63 fn create_ethernet<'a>() -> (Interface, SocketSet<'a>, Loopback) {
64     // Create a basic device
65     let mut device = Loopback::new(Medium::Ethernet);
66 
67     let mut config = Config::new();
68     config.hardware_addr = Some(EthernetAddress::default().into());
69     let mut iface = Interface::new(config, &mut device);
70     iface.update_ip_addrs(|ip_addrs| {
71         #[cfg(feature = "proto-ipv4")]
72         ip_addrs
73             .push(IpCidr::new(IpAddress::v4(127, 0, 0, 1), 8))
74             .unwrap();
75         #[cfg(feature = "proto-ipv6")]
76         ip_addrs
77             .push(IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128))
78             .unwrap();
79         #[cfg(feature = "proto-ipv6")]
80         ip_addrs
81             .push(IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64))
82             .unwrap();
83     });
84 
85     (iface, SocketSet::new(vec![]), device)
86 }
87 
88 #[cfg(feature = "medium-ieee802154")]
create_ieee802154<'a>() -> (Interface, SocketSet<'a>, Loopback)89 fn create_ieee802154<'a>() -> (Interface, SocketSet<'a>, Loopback) {
90     // Create a basic device
91     let mut device = Loopback::new(Medium::Ieee802154);
92 
93     let mut config = Config::new();
94     config.hardware_addr = Some(Ieee802154Address::default().into());
95     let mut iface = Interface::new(config, &mut device);
96     iface.update_ip_addrs(|ip_addrs| {
97         #[cfg(feature = "proto-ipv6")]
98         ip_addrs
99             .push(IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 128))
100             .unwrap();
101         #[cfg(feature = "proto-ipv6")]
102         ip_addrs
103             .push(IpCidr::new(IpAddress::v6(0xfdbe, 0, 0, 0, 0, 0, 0, 1), 64))
104             .unwrap();
105     });
106 
107     (iface, SocketSet::new(vec![]), device)
108 }
109 
110 #[cfg(feature = "proto-igmp")]
recv_all(device: &mut Loopback, timestamp: Instant) -> Vec<Vec<u8>>111 fn recv_all(device: &mut Loopback, timestamp: Instant) -> Vec<Vec<u8>> {
112     let mut pkts = Vec::new();
113     while let Some((rx, _tx)) = device.receive(timestamp) {
114         rx.consume(|pkt| {
115             pkts.push(pkt.to_vec());
116         });
117     }
118     pkts
119 }
120 
121 #[derive(Debug, PartialEq)]
122 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
123 struct MockTxToken;
124 
125 impl TxToken for MockTxToken {
consume<R, F>(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R,126     fn consume<R, F>(self, len: usize, f: F) -> R
127     where
128         F: FnOnce(&mut [u8]) -> R,
129     {
130         let mut junk = [0; 1536];
131         f(&mut junk[..len])
132     }
133 }
134 
135 #[test]
136 #[should_panic(expected = "hardware_addr required option was not set")]
137 #[cfg(all(feature = "medium-ethernet"))]
test_new_panic()138 fn test_new_panic() {
139     let mut device = Loopback::new(Medium::Ethernet);
140     let config = Config::new();
141     Interface::new(config, &mut device);
142 }
143 
144 #[test]
145 #[cfg(feature = "proto-ipv4")]
test_no_icmp_no_unicast_ipv4()146 fn test_no_icmp_no_unicast_ipv4() {
147     let (mut iface, mut sockets, _device) = create(MEDIUM);
148 
149     // Unknown Ipv4 Protocol
150     //
151     // Because the destination is the broadcast address
152     // this should not trigger and Destination Unreachable
153     // response. See RFC 1122 § 3.2.2.
154     let repr = IpRepr::Ipv4(Ipv4Repr {
155         src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
156         dst_addr: Ipv4Address::BROADCAST,
157         next_header: IpProtocol::Unknown(0x0c),
158         payload_len: 0,
159         hop_limit: 0x40,
160     });
161 
162     let mut bytes = vec![0u8; 54];
163     repr.emit(&mut bytes, &ChecksumCapabilities::default());
164     let frame = Ipv4Packet::new_unchecked(&bytes);
165 
166     // Ensure that the unknown protocol frame does not trigger an
167     // ICMP error response when the destination address is a
168     // broadcast address
169 
170     assert_eq!(
171         iface
172             .inner
173             .process_ipv4(&mut sockets, &frame, &mut iface.fragments),
174         None
175     );
176 }
177 
178 #[test]
179 #[cfg(feature = "proto-ipv6")]
test_no_icmp_no_unicast_ipv6()180 fn test_no_icmp_no_unicast_ipv6() {
181     let (mut iface, mut sockets, _device) = create(MEDIUM);
182 
183     // Unknown Ipv6 Protocol
184     //
185     // Because the destination is the broadcast address
186     // this should not trigger and Destination Unreachable
187     // response. See RFC 1122 § 3.2.2.
188     let repr = IpRepr::Ipv6(Ipv6Repr {
189         src_addr: Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1),
190         dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
191         next_header: IpProtocol::Unknown(0x0c),
192         payload_len: 0,
193         hop_limit: 0x40,
194     });
195 
196     let mut bytes = vec![0u8; 54];
197     repr.emit(&mut bytes, &ChecksumCapabilities::default());
198     let frame = Ipv6Packet::new_unchecked(&bytes);
199 
200     // Ensure that the unknown protocol frame does not trigger an
201     // ICMP error response when the destination address is a
202     // broadcast address
203     assert_eq!(iface.inner.process_ipv6(&mut sockets, &frame), None);
204 }
205 
206 #[test]
207 #[cfg(feature = "proto-ipv4")]
test_icmp_error_no_payload()208 fn test_icmp_error_no_payload() {
209     static NO_BYTES: [u8; 0] = [];
210     let (mut iface, mut sockets, _device) = create(MEDIUM);
211 
212     // Unknown Ipv4 Protocol with no payload
213     let repr = IpRepr::Ipv4(Ipv4Repr {
214         src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
215         dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
216         next_header: IpProtocol::Unknown(0x0c),
217         payload_len: 0,
218         hop_limit: 0x40,
219     });
220 
221     let mut bytes = vec![0u8; 34];
222     repr.emit(&mut bytes, &ChecksumCapabilities::default());
223     let frame = Ipv4Packet::new_unchecked(&bytes);
224 
225     // The expected Destination Unreachable response due to the
226     // unknown protocol
227     let icmp_repr = Icmpv4Repr::DstUnreachable {
228         reason: Icmpv4DstUnreachable::ProtoUnreachable,
229         header: Ipv4Repr {
230             src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
231             dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
232             next_header: IpProtocol::Unknown(12),
233             payload_len: 0,
234             hop_limit: 64,
235         },
236         data: &NO_BYTES,
237     };
238 
239     let expected_repr = IpPacket::Icmpv4((
240         Ipv4Repr {
241             src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
242             dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
243             next_header: IpProtocol::Icmp,
244             payload_len: icmp_repr.buffer_len(),
245             hop_limit: 64,
246         },
247         icmp_repr,
248     ));
249 
250     // Ensure that the unknown protocol triggers an error response.
251     // And we correctly handle no payload.
252 
253     assert_eq!(
254         iface
255             .inner
256             .process_ipv4(&mut sockets, &frame, &mut iface.fragments),
257         Some(expected_repr)
258     );
259 }
260 
261 #[test]
262 #[cfg(feature = "proto-ipv4")]
test_local_subnet_broadcasts()263 fn test_local_subnet_broadcasts() {
264     let (mut iface, _, _device) = create(MEDIUM);
265     iface.update_ip_addrs(|addrs| {
266         addrs.iter_mut().next().map(|addr| {
267             *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 1, 23]), 24));
268         });
269     });
270 
271     assert!(iface
272         .inner
273         .is_subnet_broadcast(Ipv4Address([192, 168, 1, 255])),);
274     assert!(!iface
275         .inner
276         .is_subnet_broadcast(Ipv4Address([192, 168, 1, 254])),);
277 
278     iface.update_ip_addrs(|addrs| {
279         addrs.iter_mut().next().map(|addr| {
280             *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 16));
281         });
282     });
283     assert!(!iface
284         .inner
285         .is_subnet_broadcast(Ipv4Address([192, 168, 23, 255])),);
286     assert!(!iface
287         .inner
288         .is_subnet_broadcast(Ipv4Address([192, 168, 23, 254])),);
289     assert!(!iface
290         .inner
291         .is_subnet_broadcast(Ipv4Address([192, 168, 255, 254])),);
292     assert!(iface
293         .inner
294         .is_subnet_broadcast(Ipv4Address([192, 168, 255, 255])),);
295 
296     iface.update_ip_addrs(|addrs| {
297         addrs.iter_mut().next().map(|addr| {
298             *addr = IpCidr::Ipv4(Ipv4Cidr::new(Ipv4Address([192, 168, 23, 24]), 8));
299         });
300     });
301     assert!(!iface
302         .inner
303         .is_subnet_broadcast(Ipv4Address([192, 23, 1, 255])),);
304     assert!(!iface
305         .inner
306         .is_subnet_broadcast(Ipv4Address([192, 23, 1, 254])),);
307     assert!(!iface
308         .inner
309         .is_subnet_broadcast(Ipv4Address([192, 255, 255, 254])),);
310     assert!(iface
311         .inner
312         .is_subnet_broadcast(Ipv4Address([192, 255, 255, 255])),);
313 }
314 
315 #[test]
316 #[cfg(all(feature = "socket-udp", feature = "proto-ipv4"))]
test_icmp_error_port_unreachable()317 fn test_icmp_error_port_unreachable() {
318     static UDP_PAYLOAD: [u8; 12] = [
319         0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x6c, 0x64, 0x21,
320     ];
321     let (mut iface, mut sockets, _device) = create(MEDIUM);
322 
323     let mut udp_bytes_unicast = vec![0u8; 20];
324     let mut udp_bytes_broadcast = vec![0u8; 20];
325     let mut packet_unicast = UdpPacket::new_unchecked(&mut udp_bytes_unicast);
326     let mut packet_broadcast = UdpPacket::new_unchecked(&mut udp_bytes_broadcast);
327 
328     let udp_repr = UdpRepr {
329         src_port: 67,
330         dst_port: 68,
331     };
332 
333     let ip_repr = IpRepr::Ipv4(Ipv4Repr {
334         src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
335         dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
336         next_header: IpProtocol::Udp,
337         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
338         hop_limit: 64,
339     });
340 
341     // Emit the representations to a packet
342     udp_repr.emit(
343         &mut packet_unicast,
344         &ip_repr.src_addr(),
345         &ip_repr.dst_addr(),
346         UDP_PAYLOAD.len(),
347         |buf| buf.copy_from_slice(&UDP_PAYLOAD),
348         &ChecksumCapabilities::default(),
349     );
350 
351     let data = packet_unicast.into_inner();
352 
353     // The expected Destination Unreachable ICMPv4 error response due
354     // to no sockets listening on the destination port.
355     let icmp_repr = Icmpv4Repr::DstUnreachable {
356         reason: Icmpv4DstUnreachable::PortUnreachable,
357         header: Ipv4Repr {
358             src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
359             dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
360             next_header: IpProtocol::Udp,
361             payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
362             hop_limit: 64,
363         },
364         data,
365     };
366     let expected_repr = IpPacket::Icmpv4((
367         Ipv4Repr {
368             src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
369             dst_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
370             next_header: IpProtocol::Icmp,
371             payload_len: icmp_repr.buffer_len(),
372             hop_limit: 64,
373         },
374         icmp_repr,
375     ));
376 
377     // Ensure that the unknown protocol triggers an error response.
378     // And we correctly handle no payload.
379     assert_eq!(
380         iface
381             .inner
382             .process_udp(&mut sockets, ip_repr, udp_repr, false, &UDP_PAYLOAD, data),
383         Some(expected_repr)
384     );
385 
386     let ip_repr = IpRepr::Ipv4(Ipv4Repr {
387         src_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x02]),
388         dst_addr: Ipv4Address::BROADCAST,
389         next_header: IpProtocol::Udp,
390         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
391         hop_limit: 64,
392     });
393 
394     // Emit the representations to a packet
395     udp_repr.emit(
396         &mut packet_broadcast,
397         &ip_repr.src_addr(),
398         &IpAddress::Ipv4(Ipv4Address::BROADCAST),
399         UDP_PAYLOAD.len(),
400         |buf| buf.copy_from_slice(&UDP_PAYLOAD),
401         &ChecksumCapabilities::default(),
402     );
403 
404     // Ensure that the port unreachable error does not trigger an
405     // ICMP error response when the destination address is a
406     // broadcast address and no socket is bound to the port.
407     assert_eq!(
408         iface.inner.process_udp(
409             &mut sockets,
410             ip_repr,
411             udp_repr,
412             false,
413             &UDP_PAYLOAD,
414             packet_broadcast.into_inner(),
415         ),
416         None
417     );
418 }
419 
420 #[test]
421 #[cfg(feature = "socket-udp")]
test_handle_udp_broadcast()422 fn test_handle_udp_broadcast() {
423     use crate::wire::IpEndpoint;
424 
425     static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
426 
427     let (mut iface, mut sockets, _device) = create(MEDIUM);
428 
429     let rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
430     let tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
431 
432     let udp_socket = udp::Socket::new(rx_buffer, tx_buffer);
433 
434     let mut udp_bytes = vec![0u8; 13];
435     let mut packet = UdpPacket::new_unchecked(&mut udp_bytes);
436 
437     let socket_handle = sockets.add(udp_socket);
438 
439     #[cfg(feature = "proto-ipv6")]
440     let src_ip = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
441     #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
442     let src_ip = Ipv4Address::new(0x7f, 0x00, 0x00, 0x02);
443 
444     let udp_repr = UdpRepr {
445         src_port: 67,
446         dst_port: 68,
447     };
448 
449     #[cfg(feature = "proto-ipv6")]
450     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
451         src_addr: src_ip,
452         dst_addr: Ipv6Address::LINK_LOCAL_ALL_NODES,
453         next_header: IpProtocol::Udp,
454         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
455         hop_limit: 0x40,
456     });
457     #[cfg(all(not(feature = "proto-ipv6"), feature = "proto-ipv4"))]
458     let ip_repr = IpRepr::Ipv4(Ipv4Repr {
459         src_addr: src_ip,
460         dst_addr: Ipv4Address::BROADCAST,
461         next_header: IpProtocol::Udp,
462         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
463         hop_limit: 0x40,
464     });
465 
466     // Bind the socket to port 68
467     let socket = sockets.get_mut::<udp::Socket>(socket_handle);
468     assert_eq!(socket.bind(68), Ok(()));
469     assert!(!socket.can_recv());
470     assert!(socket.can_send());
471 
472     udp_repr.emit(
473         &mut packet,
474         &ip_repr.src_addr(),
475         &ip_repr.dst_addr(),
476         UDP_PAYLOAD.len(),
477         |buf| buf.copy_from_slice(&UDP_PAYLOAD),
478         &ChecksumCapabilities::default(),
479     );
480 
481     // Packet should be handled by bound UDP socket
482     assert_eq!(
483         iface.inner.process_udp(
484             &mut sockets,
485             ip_repr,
486             udp_repr,
487             false,
488             &UDP_PAYLOAD,
489             packet.into_inner(),
490         ),
491         None
492     );
493 
494     // Make sure the payload to the UDP packet processed by process_udp is
495     // appended to the bound sockets rx_buffer
496     let socket = sockets.get_mut::<udp::Socket>(socket_handle);
497     assert!(socket.can_recv());
498     assert_eq!(
499         socket.recv(),
500         Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_ip.into(), 67)))
501     );
502 }
503 
504 #[test]
505 #[cfg(feature = "proto-ipv4")]
test_handle_ipv4_broadcast()506 fn test_handle_ipv4_broadcast() {
507     use crate::wire::{Icmpv4Packet, Icmpv4Repr, Ipv4Packet};
508 
509     let (mut iface, mut sockets, _device) = create(MEDIUM);
510 
511     let our_ipv4_addr = iface.ipv4_addr().unwrap();
512     let src_ipv4_addr = Ipv4Address([127, 0, 0, 2]);
513 
514     // ICMPv4 echo request
515     let icmpv4_data: [u8; 4] = [0xaa, 0x00, 0x00, 0xff];
516     let icmpv4_repr = Icmpv4Repr::EchoRequest {
517         ident: 0x1234,
518         seq_no: 0xabcd,
519         data: &icmpv4_data,
520     };
521 
522     // Send to IPv4 broadcast address
523     let ipv4_repr = Ipv4Repr {
524         src_addr: src_ipv4_addr,
525         dst_addr: Ipv4Address::BROADCAST,
526         next_header: IpProtocol::Icmp,
527         hop_limit: 64,
528         payload_len: icmpv4_repr.buffer_len(),
529     };
530 
531     // Emit to ip frame
532     let mut bytes = vec![0u8; ipv4_repr.buffer_len() + icmpv4_repr.buffer_len()];
533     let frame = {
534         ipv4_repr.emit(
535             &mut Ipv4Packet::new_unchecked(&mut bytes),
536             &ChecksumCapabilities::default(),
537         );
538         icmpv4_repr.emit(
539             &mut Icmpv4Packet::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
540             &ChecksumCapabilities::default(),
541         );
542         Ipv4Packet::new_unchecked(&bytes)
543     };
544 
545     // Expected ICMPv4 echo reply
546     let expected_icmpv4_repr = Icmpv4Repr::EchoReply {
547         ident: 0x1234,
548         seq_no: 0xabcd,
549         data: &icmpv4_data,
550     };
551     let expected_ipv4_repr = Ipv4Repr {
552         src_addr: our_ipv4_addr,
553         dst_addr: src_ipv4_addr,
554         next_header: IpProtocol::Icmp,
555         hop_limit: 64,
556         payload_len: expected_icmpv4_repr.buffer_len(),
557     };
558     let expected_packet = IpPacket::Icmpv4((expected_ipv4_repr, expected_icmpv4_repr));
559 
560     assert_eq!(
561         iface
562             .inner
563             .process_ipv4(&mut sockets, &frame, &mut iface.fragments),
564         Some(expected_packet)
565     );
566 }
567 
568 #[test]
569 #[cfg(feature = "socket-udp")]
test_icmp_reply_size()570 fn test_icmp_reply_size() {
571     #[cfg(feature = "proto-ipv6")]
572     use crate::wire::Icmpv6DstUnreachable;
573     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
574     use crate::wire::IPV4_MIN_MTU as MIN_MTU;
575     #[cfg(feature = "proto-ipv6")]
576     use crate::wire::IPV6_MIN_MTU as MIN_MTU;
577 
578     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
579     const MAX_PAYLOAD_LEN: usize = 528;
580     #[cfg(feature = "proto-ipv6")]
581     const MAX_PAYLOAD_LEN: usize = 1192;
582 
583     let (mut iface, mut sockets, _device) = create(MEDIUM);
584 
585     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
586     let src_addr = Ipv4Address([192, 168, 1, 1]);
587     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
588     let dst_addr = Ipv4Address([192, 168, 1, 2]);
589     #[cfg(feature = "proto-ipv6")]
590     let src_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
591     #[cfg(feature = "proto-ipv6")]
592     let dst_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 2);
593 
594     // UDP packet that if not tructated will cause a icmp port unreachable reply
595     // to exeed the minimum mtu bytes in length.
596     let udp_repr = UdpRepr {
597         src_port: 67,
598         dst_port: 68,
599     };
600     let mut bytes = vec![0xff; udp_repr.header_len() + MAX_PAYLOAD_LEN];
601     let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
602     udp_repr.emit(
603         &mut packet,
604         &src_addr.into(),
605         &dst_addr.into(),
606         MAX_PAYLOAD_LEN,
607         |buf| fill_slice(buf, 0x2a),
608         &ChecksumCapabilities::default(),
609     );
610     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
611     let ip_repr = Ipv4Repr {
612         src_addr,
613         dst_addr,
614         next_header: IpProtocol::Udp,
615         hop_limit: 64,
616         payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
617     };
618     #[cfg(feature = "proto-ipv6")]
619     let ip_repr = Ipv6Repr {
620         src_addr,
621         dst_addr,
622         next_header: IpProtocol::Udp,
623         hop_limit: 64,
624         payload_len: udp_repr.header_len() + MAX_PAYLOAD_LEN,
625     };
626     let payload = packet.into_inner();
627 
628     // Expected packets
629     #[cfg(feature = "proto-ipv6")]
630     let expected_icmp_repr = Icmpv6Repr::DstUnreachable {
631         reason: Icmpv6DstUnreachable::PortUnreachable,
632         header: ip_repr,
633         data: &payload[..MAX_PAYLOAD_LEN],
634     };
635     #[cfg(feature = "proto-ipv6")]
636     let expected_ip_repr = Ipv6Repr {
637         src_addr: dst_addr,
638         dst_addr: src_addr,
639         next_header: IpProtocol::Icmpv6,
640         hop_limit: 64,
641         payload_len: expected_icmp_repr.buffer_len(),
642     };
643     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
644     let expected_icmp_repr = Icmpv4Repr::DstUnreachable {
645         reason: Icmpv4DstUnreachable::PortUnreachable,
646         header: ip_repr,
647         data: &payload[..MAX_PAYLOAD_LEN],
648     };
649     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
650     let expected_ip_repr = Ipv4Repr {
651         src_addr: dst_addr,
652         dst_addr: src_addr,
653         next_header: IpProtocol::Icmp,
654         hop_limit: 64,
655         payload_len: expected_icmp_repr.buffer_len(),
656     };
657 
658     // The expected packet does not exceed the IPV4_MIN_MTU
659     #[cfg(feature = "proto-ipv6")]
660     assert_eq!(
661         expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
662         MIN_MTU
663     );
664     // The expected packet does not exceed the IPV4_MIN_MTU
665     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
666     assert_eq!(
667         expected_ip_repr.buffer_len() + expected_icmp_repr.buffer_len(),
668         MIN_MTU
669     );
670     // The expected packet and the generated packet are equal
671     #[cfg(all(feature = "proto-ipv4", not(feature = "proto-ipv6")))]
672     assert_eq!(
673         iface.inner.process_udp(
674             &mut sockets,
675             ip_repr.into(),
676             udp_repr,
677             false,
678             &vec![0x2a; MAX_PAYLOAD_LEN],
679             payload,
680         ),
681         Some(IpPacket::Icmpv4((expected_ip_repr, expected_icmp_repr)))
682     );
683     #[cfg(feature = "proto-ipv6")]
684     assert_eq!(
685         iface.inner.process_udp(
686             &mut sockets,
687             ip_repr.into(),
688             udp_repr,
689             false,
690             &vec![0x2a; MAX_PAYLOAD_LEN],
691             payload,
692         ),
693         Some(IpPacket::Icmpv6((expected_ip_repr, expected_icmp_repr)))
694     );
695 }
696 
697 #[test]
698 #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
test_handle_valid_arp_request()699 fn test_handle_valid_arp_request() {
700     let (mut iface, mut sockets, _device) = create_ethernet();
701 
702     let mut eth_bytes = vec![0u8; 42];
703 
704     let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
705     let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
706     let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
707     let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
708 
709     let repr = ArpRepr::EthernetIpv4 {
710         operation: ArpOperation::Request,
711         source_hardware_addr: remote_hw_addr,
712         source_protocol_addr: remote_ip_addr,
713         target_hardware_addr: EthernetAddress::default(),
714         target_protocol_addr: local_ip_addr,
715     };
716 
717     let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
718     frame.set_dst_addr(EthernetAddress::BROADCAST);
719     frame.set_src_addr(remote_hw_addr);
720     frame.set_ethertype(EthernetProtocol::Arp);
721     let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
722     repr.emit(&mut packet);
723 
724     // Ensure an ARP Request for us triggers an ARP Reply
725     assert_eq!(
726         iface
727             .inner
728             .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
729         Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
730             operation: ArpOperation::Reply,
731             source_hardware_addr: local_hw_addr,
732             source_protocol_addr: local_ip_addr,
733             target_hardware_addr: remote_hw_addr,
734             target_protocol_addr: remote_ip_addr
735         }))
736     );
737 
738     // Ensure the address of the requestor was entered in the cache
739     assert_eq!(
740         iface.inner.lookup_hardware_addr(
741             MockTxToken,
742             &IpAddress::Ipv4(local_ip_addr),
743             &IpAddress::Ipv4(remote_ip_addr),
744             &mut iface.fragmenter,
745         ),
746         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
747     );
748 }
749 
750 #[test]
751 #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))]
test_handle_valid_ndisc_request()752 fn test_handle_valid_ndisc_request() {
753     let (mut iface, mut sockets, _device) = create_ethernet();
754 
755     let mut eth_bytes = vec![0u8; 86];
756 
757     let local_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 1);
758     let remote_ip_addr = Ipv6Address::new(0xfdbe, 0, 0, 0, 0, 0, 0, 2);
759     let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
760     let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
761 
762     let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
763         target_addr: local_ip_addr,
764         lladdr: Some(remote_hw_addr.into()),
765     });
766     let ip_repr = IpRepr::Ipv6(Ipv6Repr {
767         src_addr: remote_ip_addr,
768         dst_addr: local_ip_addr.solicited_node(),
769         next_header: IpProtocol::Icmpv6,
770         hop_limit: 0xff,
771         payload_len: solicit.buffer_len(),
772     });
773 
774     let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
775     frame.set_dst_addr(EthernetAddress([0x33, 0x33, 0x00, 0x00, 0x00, 0x00]));
776     frame.set_src_addr(remote_hw_addr);
777     frame.set_ethertype(EthernetProtocol::Ipv6);
778     ip_repr.emit(frame.payload_mut(), &ChecksumCapabilities::default());
779     solicit.emit(
780         &remote_ip_addr.into(),
781         &local_ip_addr.solicited_node().into(),
782         &mut Icmpv6Packet::new_unchecked(&mut frame.payload_mut()[ip_repr.header_len()..]),
783         &ChecksumCapabilities::default(),
784     );
785 
786     let icmpv6_expected = Icmpv6Repr::Ndisc(NdiscRepr::NeighborAdvert {
787         flags: NdiscNeighborFlags::SOLICITED,
788         target_addr: local_ip_addr,
789         lladdr: Some(local_hw_addr.into()),
790     });
791 
792     let ipv6_expected = Ipv6Repr {
793         src_addr: local_ip_addr,
794         dst_addr: remote_ip_addr,
795         next_header: IpProtocol::Icmpv6,
796         hop_limit: 0xff,
797         payload_len: icmpv6_expected.buffer_len(),
798     };
799 
800     // Ensure an Neighbor Solicitation triggers a Neighbor Advertisement
801     assert_eq!(
802         iface
803             .inner
804             .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
805         Some(EthernetPacket::Ip(IpPacket::Icmpv6((
806             ipv6_expected,
807             icmpv6_expected
808         ))))
809     );
810 
811     // Ensure the address of the requestor was entered in the cache
812     assert_eq!(
813         iface.inner.lookup_hardware_addr(
814             MockTxToken,
815             &IpAddress::Ipv6(local_ip_addr),
816             &IpAddress::Ipv6(remote_ip_addr),
817             &mut iface.fragmenter,
818         ),
819         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
820     );
821 }
822 
823 #[test]
824 #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
test_handle_other_arp_request()825 fn test_handle_other_arp_request() {
826     let (mut iface, mut sockets, _device) = create_ethernet();
827 
828     let mut eth_bytes = vec![0u8; 42];
829 
830     let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
831     let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
832 
833     let repr = ArpRepr::EthernetIpv4 {
834         operation: ArpOperation::Request,
835         source_hardware_addr: remote_hw_addr,
836         source_protocol_addr: remote_ip_addr,
837         target_hardware_addr: EthernetAddress::default(),
838         target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x03]),
839     };
840 
841     let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
842     frame.set_dst_addr(EthernetAddress::BROADCAST);
843     frame.set_src_addr(remote_hw_addr);
844     frame.set_ethertype(EthernetProtocol::Arp);
845     let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
846     repr.emit(&mut packet);
847 
848     // Ensure an ARP Request for someone else does not trigger an ARP Reply
849     assert_eq!(
850         iface
851             .inner
852             .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
853         None
854     );
855 
856     // Ensure the address of the requestor was NOT entered in the cache
857     assert_eq!(
858         iface.inner.lookup_hardware_addr(
859             MockTxToken,
860             &IpAddress::Ipv4(Ipv4Address([0x7f, 0x00, 0x00, 0x01])),
861             &IpAddress::Ipv4(remote_ip_addr),
862             &mut iface.fragmenter,
863         ),
864         Err(DispatchError::NeighborPending)
865     );
866 }
867 
868 #[test]
869 #[cfg(all(
870     feature = "medium-ethernet",
871     feature = "proto-ipv4",
872     not(feature = "medium-ieee802154")
873 ))]
test_arp_flush_after_update_ip()874 fn test_arp_flush_after_update_ip() {
875     let (mut iface, mut sockets, _device) = create_ethernet();
876 
877     let mut eth_bytes = vec![0u8; 42];
878 
879     let local_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
880     let remote_ip_addr = Ipv4Address([0x7f, 0x00, 0x00, 0x02]);
881     let local_hw_addr = EthernetAddress([0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
882     let remote_hw_addr = EthernetAddress([0x52, 0x54, 0x00, 0x00, 0x00, 0x00]);
883 
884     let repr = ArpRepr::EthernetIpv4 {
885         operation: ArpOperation::Request,
886         source_hardware_addr: remote_hw_addr,
887         source_protocol_addr: remote_ip_addr,
888         target_hardware_addr: EthernetAddress::default(),
889         target_protocol_addr: Ipv4Address([0x7f, 0x00, 0x00, 0x01]),
890     };
891 
892     let mut frame = EthernetFrame::new_unchecked(&mut eth_bytes);
893     frame.set_dst_addr(EthernetAddress::BROADCAST);
894     frame.set_src_addr(remote_hw_addr);
895     frame.set_ethertype(EthernetProtocol::Arp);
896     {
897         let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
898         repr.emit(&mut packet);
899     }
900 
901     // Ensure an ARP Request for us triggers an ARP Reply
902     assert_eq!(
903         iface
904             .inner
905             .process_ethernet(&mut sockets, frame.into_inner(), &mut iface.fragments),
906         Some(EthernetPacket::Arp(ArpRepr::EthernetIpv4 {
907             operation: ArpOperation::Reply,
908             source_hardware_addr: local_hw_addr,
909             source_protocol_addr: local_ip_addr,
910             target_hardware_addr: remote_hw_addr,
911             target_protocol_addr: remote_ip_addr
912         }))
913     );
914 
915     // Ensure the address of the requestor was entered in the cache
916     assert_eq!(
917         iface.inner.lookup_hardware_addr(
918             MockTxToken,
919             &IpAddress::Ipv4(local_ip_addr),
920             &IpAddress::Ipv4(remote_ip_addr),
921             &mut iface.fragmenter,
922         ),
923         Ok((HardwareAddress::Ethernet(remote_hw_addr), MockTxToken))
924     );
925 
926     // Update IP addrs to trigger ARP cache flush
927     let local_ip_addr_new = Ipv4Address([0x7f, 0x00, 0x00, 0x01]);
928     iface.update_ip_addrs(|addrs| {
929         addrs.iter_mut().next().map(|addr| {
930             *addr = IpCidr::Ipv4(Ipv4Cidr::new(local_ip_addr_new, 24));
931         });
932     });
933 
934     // ARP cache flush after address change
935     assert!(!iface.inner.has_neighbor(&IpAddress::Ipv4(remote_ip_addr)));
936 }
937 
938 #[test]
939 #[cfg(all(feature = "socket-icmp", feature = "proto-ipv4"))]
test_icmpv4_socket()940 fn test_icmpv4_socket() {
941     use crate::wire::Icmpv4Packet;
942 
943     let (mut iface, mut sockets, _device) = create(MEDIUM);
944 
945     let rx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
946     let tx_buffer = icmp::PacketBuffer::new(vec![icmp::PacketMetadata::EMPTY], vec![0; 24]);
947 
948     let icmpv4_socket = icmp::Socket::new(rx_buffer, tx_buffer);
949 
950     let socket_handle = sockets.add(icmpv4_socket);
951 
952     let ident = 0x1234;
953     let seq_no = 0x5432;
954     let echo_data = &[0xff; 16];
955 
956     let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
957     // Bind to the ID 0x1234
958     assert_eq!(socket.bind(icmp::Endpoint::Ident(ident)), Ok(()));
959 
960     // Ensure the ident we bound to and the ident of the packet are the same.
961     let mut bytes = [0xff; 24];
962     let mut packet = Icmpv4Packet::new_unchecked(&mut bytes[..]);
963     let echo_repr = Icmpv4Repr::EchoRequest {
964         ident,
965         seq_no,
966         data: echo_data,
967     };
968     echo_repr.emit(&mut packet, &ChecksumCapabilities::default());
969     let icmp_data = &*packet.into_inner();
970 
971     let ipv4_repr = Ipv4Repr {
972         src_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x02),
973         dst_addr: Ipv4Address::new(0x7f, 0x00, 0x00, 0x01),
974         next_header: IpProtocol::Icmp,
975         payload_len: 24,
976         hop_limit: 64,
977     };
978     let ip_repr = IpRepr::Ipv4(ipv4_repr);
979 
980     // Open a socket and ensure the packet is handled due to the listening
981     // socket.
982     assert!(!sockets.get_mut::<icmp::Socket>(socket_handle).can_recv());
983 
984     // Confirm we still get EchoReply from `smoltcp` even with the ICMP socket listening
985     let echo_reply = Icmpv4Repr::EchoReply {
986         ident,
987         seq_no,
988         data: echo_data,
989     };
990     let ipv4_reply = Ipv4Repr {
991         src_addr: ipv4_repr.dst_addr,
992         dst_addr: ipv4_repr.src_addr,
993         ..ipv4_repr
994     };
995     assert_eq!(
996         iface.inner.process_icmpv4(&mut sockets, ip_repr, icmp_data),
997         Some(IpPacket::Icmpv4((ipv4_reply, echo_reply)))
998     );
999 
1000     let socket = sockets.get_mut::<icmp::Socket>(socket_handle);
1001     assert!(socket.can_recv());
1002     assert_eq!(
1003         socket.recv(),
1004         Ok((
1005             icmp_data,
1006             IpAddress::Ipv4(Ipv4Address::new(0x7f, 0x00, 0x00, 0x02))
1007         ))
1008     );
1009 }
1010 
1011 #[test]
1012 #[cfg(feature = "proto-ipv6")]
test_solicited_node_addrs()1013 fn test_solicited_node_addrs() {
1014     let (mut iface, _, _device) = create(MEDIUM);
1015     let mut new_addrs = heapless::Vec::<IpCidr, IFACE_MAX_ADDR_COUNT>::new();
1016     new_addrs
1017         .push(IpCidr::new(IpAddress::v6(0xfe80, 0, 0, 0, 1, 2, 0, 2), 64))
1018         .unwrap();
1019     new_addrs
1020         .push(IpCidr::new(
1021             IpAddress::v6(0xfe80, 0, 0, 0, 3, 4, 0, 0xffff),
1022             64,
1023         ))
1024         .unwrap();
1025     iface.update_ip_addrs(|addrs| {
1026         new_addrs.extend(addrs.to_vec());
1027         *addrs = new_addrs;
1028     });
1029     assert!(iface
1030         .inner
1031         .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0002)));
1032     assert!(iface
1033         .inner
1034         .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0xffff)));
1035     assert!(!iface
1036         .inner
1037         .has_solicited_node(Ipv6Address::new(0xff02, 0, 0, 0, 0, 1, 0xff00, 0x0003)));
1038 }
1039 
1040 #[test]
1041 #[cfg(feature = "proto-ipv6")]
test_icmpv6_nxthdr_unknown()1042 fn test_icmpv6_nxthdr_unknown() {
1043     let (mut iface, mut sockets, _device) = create(MEDIUM);
1044 
1045     let remote_ip_addr = Ipv6Address::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
1046 
1047     let payload = [0x12, 0x34, 0x56, 0x78];
1048 
1049     let ipv6_repr = Ipv6Repr {
1050         src_addr: remote_ip_addr,
1051         dst_addr: Ipv6Address::LOOPBACK,
1052         next_header: IpProtocol::HopByHop,
1053         payload_len: 12,
1054         hop_limit: 0x40,
1055     };
1056 
1057     let mut bytes = vec![0; 52];
1058     let frame = {
1059         let ip_repr = IpRepr::Ipv6(ipv6_repr);
1060         ip_repr.emit(&mut bytes, &ChecksumCapabilities::default());
1061         let mut offset = ipv6_repr.buffer_len();
1062         {
1063             let mut hbh_pkt = Ipv6HopByHopHeader::new_unchecked(&mut bytes[offset..]);
1064             hbh_pkt.set_next_header(IpProtocol::Unknown(0x0c));
1065             hbh_pkt.set_header_len(0);
1066             offset += 8;
1067             {
1068                 let mut pad_pkt = Ipv6Option::new_unchecked(&mut *hbh_pkt.options_mut());
1069                 Ipv6OptionRepr::PadN(3).emit(&mut pad_pkt);
1070             }
1071             {
1072                 let mut pad_pkt = Ipv6Option::new_unchecked(&mut hbh_pkt.options_mut()[5..]);
1073                 Ipv6OptionRepr::Pad1.emit(&mut pad_pkt);
1074             }
1075         }
1076         bytes[offset..].copy_from_slice(&payload);
1077         Ipv6Packet::new_unchecked(&bytes)
1078     };
1079 
1080     let reply_icmp_repr = Icmpv6Repr::ParamProblem {
1081         reason: Icmpv6ParamProblem::UnrecognizedNxtHdr,
1082         pointer: 40,
1083         header: ipv6_repr,
1084         data: &payload[..],
1085     };
1086 
1087     let reply_ipv6_repr = Ipv6Repr {
1088         src_addr: Ipv6Address::LOOPBACK,
1089         dst_addr: remote_ip_addr,
1090         next_header: IpProtocol::Icmpv6,
1091         payload_len: reply_icmp_repr.buffer_len(),
1092         hop_limit: 0x40,
1093     };
1094 
1095     // Ensure the unknown next header causes a ICMPv6 Parameter Problem
1096     // error message to be sent to the sender.
1097     assert_eq!(
1098         iface.inner.process_ipv6(&mut sockets, &frame),
1099         Some(IpPacket::Icmpv6((reply_ipv6_repr, reply_icmp_repr)))
1100     );
1101 }
1102 
1103 #[test]
1104 #[cfg(feature = "proto-igmp")]
test_handle_igmp()1105 fn test_handle_igmp() {
1106     fn recv_igmp(device: &mut Loopback, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> {
1107         let caps = device.capabilities();
1108         let checksum_caps = &caps.checksum;
1109         recv_all(device, timestamp)
1110             .iter()
1111             .filter_map(|frame| {
1112                 let ipv4_packet = match caps.medium {
1113                     #[cfg(feature = "medium-ethernet")]
1114                     Medium::Ethernet => {
1115                         let eth_frame = EthernetFrame::new_checked(frame).ok()?;
1116                         Ipv4Packet::new_checked(eth_frame.payload()).ok()?
1117                     }
1118                     #[cfg(feature = "medium-ip")]
1119                     Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()?,
1120                     #[cfg(feature = "medium-ieee802154")]
1121                     Medium::Ieee802154 => todo!(),
1122                 };
1123                 let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, checksum_caps).ok()?;
1124                 let ip_payload = ipv4_packet.payload();
1125                 let igmp_packet = IgmpPacket::new_checked(ip_payload).ok()?;
1126                 let igmp_repr = IgmpRepr::parse(&igmp_packet).ok()?;
1127                 Some((ipv4_repr, igmp_repr))
1128             })
1129             .collect::<Vec<_>>()
1130     }
1131 
1132     let groups = [
1133         Ipv4Address::new(224, 0, 0, 22),
1134         Ipv4Address::new(224, 0, 0, 56),
1135     ];
1136 
1137     let (mut iface, mut sockets, mut device) = create(MEDIUM);
1138 
1139     // Join multicast groups
1140     let timestamp = Instant::now();
1141     for group in &groups {
1142         iface
1143             .join_multicast_group(&mut device, *group, timestamp)
1144             .unwrap();
1145     }
1146 
1147     let reports = recv_igmp(&mut device, timestamp);
1148     assert_eq!(reports.len(), 2);
1149     for (i, group_addr) in groups.iter().enumerate() {
1150         assert_eq!(reports[i].0.next_header, IpProtocol::Igmp);
1151         assert_eq!(reports[i].0.dst_addr, *group_addr);
1152         assert_eq!(
1153             reports[i].1,
1154             IgmpRepr::MembershipReport {
1155                 group_addr: *group_addr,
1156                 version: IgmpVersion::Version2,
1157             }
1158         );
1159     }
1160 
1161     // General query
1162     let timestamp = Instant::now();
1163     const GENERAL_QUERY_BYTES: &[u8] = &[
1164         0x46, 0xc0, 0x00, 0x24, 0xed, 0xb4, 0x00, 0x00, 0x01, 0x02, 0x47, 0x43, 0xac, 0x16, 0x63,
1165         0x04, 0xe0, 0x00, 0x00, 0x01, 0x94, 0x04, 0x00, 0x00, 0x11, 0x64, 0xec, 0x8f, 0x00, 0x00,
1166         0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1167         0x00,
1168     ];
1169     {
1170         // Transmit GENERAL_QUERY_BYTES into loopback
1171         let tx_token = device.transmit(timestamp).unwrap();
1172         tx_token.consume(GENERAL_QUERY_BYTES.len(), |buffer| {
1173             buffer.copy_from_slice(GENERAL_QUERY_BYTES);
1174         });
1175     }
1176     // Trigger processing until all packets received through the
1177     // loopback have been processed, including responses to
1178     // GENERAL_QUERY_BYTES. Therefore `recv_all()` would return 0
1179     // pkts that could be checked.
1180     iface.socket_ingress(&mut device, &mut sockets);
1181 
1182     // Leave multicast groups
1183     let timestamp = Instant::now();
1184     for group in &groups {
1185         iface
1186             .leave_multicast_group(&mut device, *group, timestamp)
1187             .unwrap();
1188     }
1189 
1190     let leaves = recv_igmp(&mut device, timestamp);
1191     assert_eq!(leaves.len(), 2);
1192     for (i, group_addr) in groups.iter().cloned().enumerate() {
1193         assert_eq!(leaves[i].0.next_header, IpProtocol::Igmp);
1194         assert_eq!(leaves[i].0.dst_addr, Ipv4Address::MULTICAST_ALL_ROUTERS);
1195         assert_eq!(leaves[i].1, IgmpRepr::LeaveGroup { group_addr });
1196     }
1197 }
1198 
1199 #[test]
1200 #[cfg(all(feature = "proto-ipv4", feature = "socket-raw"))]
test_raw_socket_no_reply()1201 fn test_raw_socket_no_reply() {
1202     use crate::wire::{IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
1203 
1204     let (mut iface, mut sockets, _device) = create(MEDIUM);
1205 
1206     let packets = 1;
1207     let rx_buffer =
1208         raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
1209     let tx_buffer = raw::PacketBuffer::new(
1210         vec![raw::PacketMetadata::EMPTY; packets],
1211         vec![0; 48 * packets],
1212     );
1213     let raw_socket = raw::Socket::new(IpVersion::Ipv4, IpProtocol::Udp, rx_buffer, tx_buffer);
1214     sockets.add(raw_socket);
1215 
1216     let src_addr = Ipv4Address([127, 0, 0, 2]);
1217     let dst_addr = Ipv4Address([127, 0, 0, 1]);
1218 
1219     const PAYLOAD_LEN: usize = 10;
1220 
1221     let udp_repr = UdpRepr {
1222         src_port: 67,
1223         dst_port: 68,
1224     };
1225     let mut bytes = vec![0xff; udp_repr.header_len() + PAYLOAD_LEN];
1226     let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
1227     udp_repr.emit(
1228         &mut packet,
1229         &src_addr.into(),
1230         &dst_addr.into(),
1231         PAYLOAD_LEN,
1232         |buf| fill_slice(buf, 0x2a),
1233         &ChecksumCapabilities::default(),
1234     );
1235     let ipv4_repr = Ipv4Repr {
1236         src_addr,
1237         dst_addr,
1238         next_header: IpProtocol::Udp,
1239         hop_limit: 64,
1240         payload_len: udp_repr.header_len() + PAYLOAD_LEN,
1241     };
1242 
1243     // Emit to frame
1244     let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + PAYLOAD_LEN];
1245     let frame = {
1246         ipv4_repr.emit(
1247             &mut Ipv4Packet::new_unchecked(&mut bytes),
1248             &ChecksumCapabilities::default(),
1249         );
1250         udp_repr.emit(
1251             &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
1252             &src_addr.into(),
1253             &dst_addr.into(),
1254             PAYLOAD_LEN,
1255             |buf| fill_slice(buf, 0x2a),
1256             &ChecksumCapabilities::default(),
1257         );
1258         Ipv4Packet::new_unchecked(&bytes)
1259     };
1260 
1261     assert_eq!(
1262         iface
1263             .inner
1264             .process_ipv4(&mut sockets, &frame, &mut iface.fragments),
1265         None
1266     );
1267 }
1268 
1269 #[test]
1270 #[cfg(all(feature = "proto-ipv4", feature = "socket-raw", feature = "socket-udp"))]
test_raw_socket_with_udp_socket()1271 fn test_raw_socket_with_udp_socket() {
1272     use crate::wire::{IpEndpoint, IpVersion, Ipv4Packet, UdpPacket, UdpRepr};
1273 
1274     static UDP_PAYLOAD: [u8; 5] = [0x48, 0x65, 0x6c, 0x6c, 0x6f];
1275 
1276     let (mut iface, mut sockets, _device) = create(MEDIUM);
1277 
1278     let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
1279     let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 15]);
1280     let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
1281     let udp_socket_handle = sockets.add(udp_socket);
1282 
1283     // Bind the socket to port 68
1284     let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
1285     assert_eq!(socket.bind(68), Ok(()));
1286     assert!(!socket.can_recv());
1287     assert!(socket.can_send());
1288 
1289     let packets = 1;
1290     let raw_rx_buffer =
1291         raw::PacketBuffer::new(vec![raw::PacketMetadata::EMPTY; packets], vec![0; 48 * 1]);
1292     let raw_tx_buffer = raw::PacketBuffer::new(
1293         vec![raw::PacketMetadata::EMPTY; packets],
1294         vec![0; 48 * packets],
1295     );
1296     let raw_socket = raw::Socket::new(
1297         IpVersion::Ipv4,
1298         IpProtocol::Udp,
1299         raw_rx_buffer,
1300         raw_tx_buffer,
1301     );
1302     sockets.add(raw_socket);
1303 
1304     let src_addr = Ipv4Address([127, 0, 0, 2]);
1305     let dst_addr = Ipv4Address([127, 0, 0, 1]);
1306 
1307     let udp_repr = UdpRepr {
1308         src_port: 67,
1309         dst_port: 68,
1310     };
1311     let mut bytes = vec![0xff; udp_repr.header_len() + UDP_PAYLOAD.len()];
1312     let mut packet = UdpPacket::new_unchecked(&mut bytes[..]);
1313     udp_repr.emit(
1314         &mut packet,
1315         &src_addr.into(),
1316         &dst_addr.into(),
1317         UDP_PAYLOAD.len(),
1318         |buf| buf.copy_from_slice(&UDP_PAYLOAD),
1319         &ChecksumCapabilities::default(),
1320     );
1321     let ipv4_repr = Ipv4Repr {
1322         src_addr,
1323         dst_addr,
1324         next_header: IpProtocol::Udp,
1325         hop_limit: 64,
1326         payload_len: udp_repr.header_len() + UDP_PAYLOAD.len(),
1327     };
1328 
1329     // Emit to frame
1330     let mut bytes = vec![0u8; ipv4_repr.buffer_len() + udp_repr.header_len() + UDP_PAYLOAD.len()];
1331     let frame = {
1332         ipv4_repr.emit(
1333             &mut Ipv4Packet::new_unchecked(&mut bytes),
1334             &ChecksumCapabilities::default(),
1335         );
1336         udp_repr.emit(
1337             &mut UdpPacket::new_unchecked(&mut bytes[ipv4_repr.buffer_len()..]),
1338             &src_addr.into(),
1339             &dst_addr.into(),
1340             UDP_PAYLOAD.len(),
1341             |buf| buf.copy_from_slice(&UDP_PAYLOAD),
1342             &ChecksumCapabilities::default(),
1343         );
1344         Ipv4Packet::new_unchecked(&bytes)
1345     };
1346 
1347     assert_eq!(
1348         iface
1349             .inner
1350             .process_ipv4(&mut sockets, &frame, &mut iface.fragments),
1351         None
1352     );
1353 
1354     // Make sure the UDP socket can still receive in presence of a Raw socket that handles UDP
1355     let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
1356     assert!(socket.can_recv());
1357     assert_eq!(
1358         socket.recv(),
1359         Ok((&UDP_PAYLOAD[..], IpEndpoint::new(src_addr.into(), 67)))
1360     );
1361 }
1362 
1363 #[cfg(all(
1364     not(feature = "medium-ethernet"),
1365     feature = "proto-sixlowpan",
1366     feature = "proto-sixlowpan-fragmentation"
1367 ))]
1368 #[test]
test_echo_request_sixlowpan_128_bytes()1369 fn test_echo_request_sixlowpan_128_bytes() {
1370     use crate::phy::Checksum;
1371 
1372     let (mut iface, mut sockets, mut device) = create(Medium::Ieee802154);
1373     // TODO: modify the example, such that we can also test if the checksum is correctly
1374     // computed.
1375     iface.inner.caps.checksum.icmpv6 = Checksum::None;
1376 
1377     assert_eq!(iface.inner.caps.medium, Medium::Ieee802154);
1378     let now = iface.inner.now();
1379 
1380     iface.inner.neighbor_cache.as_mut().unwrap().fill(
1381         Ipv6Address([0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0]).into(),
1382         HardwareAddress::Ieee802154(Ieee802154Address::default()),
1383         now,
1384     );
1385 
1386     let mut ieee802154_repr = Ieee802154Repr {
1387         frame_type: Ieee802154FrameType::Data,
1388         security_enabled: false,
1389         frame_pending: false,
1390         ack_request: false,
1391         sequence_number: Some(5),
1392         pan_id_compression: true,
1393         frame_version: Ieee802154FrameVersion::Ieee802154_2003,
1394         dst_pan_id: Some(Ieee802154Pan(0xbeef)),
1395         dst_addr: Some(Ieee802154Address::Extended([
1396             0x90, 0xfc, 0x48, 0xc2, 0xa4, 0x41, 0xfc, 0x76,
1397         ])),
1398         src_pan_id: Some(Ieee802154Pan(0xbeef)),
1399         src_addr: Some(Ieee802154Address::Extended([
1400             0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0b, 0x1a,
1401         ])),
1402     };
1403 
1404     // NOTE: this data is retrieved from tests with Contiki-NG
1405 
1406     let request_first_part_packet = SixlowpanFragPacket::new_checked(&[
1407         0xc0, 0xb0, 0x00, 0x8e, 0x6a, 0x33, 0x05, 0x25, 0x2c, 0x3a, 0x80, 0x00, 0xe0, 0x71, 0x00,
1408         0x27, 0x00, 0x02, 0xa2, 0xc2, 0x2d, 0x63, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x5e, 0x0c, 0x00,
1409         0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
1410         0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
1411         0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
1412         0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
1413         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
1414     ])
1415     .unwrap();
1416 
1417     let request_first_part_iphc_packet =
1418         SixlowpanIphcPacket::new_checked(request_first_part_packet.payload()).unwrap();
1419 
1420     let request_first_part_iphc_repr = SixlowpanIphcRepr::parse(
1421         &request_first_part_iphc_packet,
1422         ieee802154_repr.src_addr,
1423         ieee802154_repr.dst_addr,
1424         &iface.inner.sixlowpan_address_context,
1425     )
1426     .unwrap();
1427 
1428     assert_eq!(
1429         request_first_part_iphc_repr.src_addr,
1430         Ipv6Address([
1431             0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb,
1432             0x1a,
1433         ]),
1434     );
1435     assert_eq!(
1436         request_first_part_iphc_repr.dst_addr,
1437         Ipv6Address([
1438             0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41, 0xfc,
1439             0x76,
1440         ]),
1441     );
1442 
1443     let request_second_part = [
1444         0xe0, 0xb0, 0x00, 0x8e, 0x10, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
1445         0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
1446         0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
1447         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1448     ];
1449 
1450     assert_eq!(
1451         iface.inner.process_sixlowpan(
1452             &mut sockets,
1453             &ieee802154_repr,
1454             &request_first_part_packet.into_inner(),
1455             &mut iface.fragments
1456         ),
1457         None
1458     );
1459 
1460     ieee802154_repr.sequence_number = Some(6);
1461 
1462     // data that was generated when using `ping -s 128`
1463     let data = &[
1464         0xa2, 0xc2, 0x2d, 0x63, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x5e, 0x0c, 0x00, 0x00, 0x00, 0x00,
1465         0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
1466         0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c,
1467         0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
1468         0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
1469         0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
1470         0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
1471         0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
1472         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1473     ];
1474 
1475     let result = iface.inner.process_sixlowpan(
1476         &mut sockets,
1477         &ieee802154_repr,
1478         &request_second_part,
1479         &mut iface.fragments,
1480     );
1481 
1482     assert_eq!(
1483         result,
1484         Some(IpPacket::Icmpv6((
1485             Ipv6Repr {
1486                 src_addr: Ipv6Address([
1487                     0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x92, 0xfc, 0x48, 0xc2, 0xa4, 0x41,
1488                     0xfc, 0x76,
1489                 ]),
1490                 dst_addr: Ipv6Address([
1491                     0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42,
1492                     0xb, 0x1a,
1493                 ]),
1494                 next_header: IpProtocol::Icmpv6,
1495                 payload_len: 136,
1496                 hop_limit: 64,
1497             },
1498             Icmpv6Repr::EchoReply {
1499                 ident: 39,
1500                 seq_no: 2,
1501                 data,
1502             }
1503         )))
1504     );
1505 
1506     iface.inner.neighbor_cache.as_mut().unwrap().fill(
1507         IpAddress::Ipv6(Ipv6Address([
1508             0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, 0x1a,
1509         ])),
1510         HardwareAddress::Ieee802154(Ieee802154Address::default()),
1511         Instant::now(),
1512     );
1513 
1514     let tx_token = device.transmit(Instant::now()).unwrap();
1515     iface.inner.dispatch_ieee802154(
1516         Ieee802154Address::default(),
1517         tx_token,
1518         result.unwrap(),
1519         &mut iface.fragmenter,
1520     );
1521 
1522     assert_eq!(
1523         device.queue[0],
1524         &[
1525             0x41, 0xcc, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1526             0x0, 0x0, 0x0, 0x0, 0xc0, 0xb0, 0x5, 0x4e, 0x7a, 0x11, 0x3a, 0x92, 0xfc, 0x48, 0xc2,
1527             0xa4, 0x41, 0xfc, 0x76, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42, 0xb, 0x1a, 0x81, 0x0, 0x0,
1528             0x0, 0x0, 0x27, 0x0, 0x2, 0xa2, 0xc2, 0x2d, 0x63, 0x0, 0x0, 0x0, 0x0, 0xd9, 0x5e, 0xc,
1529             0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
1530             0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
1531             0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
1532             0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
1533             0x44, 0x45, 0x46, 0x47,
1534         ]
1535     );
1536 
1537     iface.poll(Instant::now(), &mut device, &mut sockets);
1538 
1539     assert_eq!(
1540         device.queue[1],
1541         &[
1542             0x41, 0xcc, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1543             0x0, 0x0, 0x0, 0x0, 0xe0, 0xb0, 0x5, 0x4e, 0xf, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
1544             0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b,
1545             0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
1546             0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
1547             0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
1548         ]
1549     );
1550 }
1551 
1552 #[cfg(all(
1553     not(feature = "medium-ethernet"),
1554     feature = "proto-sixlowpan",
1555     feature = "proto-sixlowpan-fragmentation"
1556 ))]
1557 #[test]
test_sixlowpan_udp_with_fragmentation()1558 fn test_sixlowpan_udp_with_fragmentation() {
1559     use crate::phy::Checksum;
1560 
1561     let mut ieee802154_repr = Ieee802154Repr {
1562         frame_type: Ieee802154FrameType::Data,
1563         security_enabled: false,
1564         frame_pending: false,
1565         ack_request: false,
1566         sequence_number: Some(5),
1567         pan_id_compression: true,
1568         frame_version: Ieee802154FrameVersion::Ieee802154_2003,
1569         dst_pan_id: Some(Ieee802154Pan(0xbeef)),
1570         dst_addr: Some(Ieee802154Address::Extended([
1571             0x90, 0xfc, 0x48, 0xc2, 0xa4, 0x41, 0xfc, 0x76,
1572         ])),
1573         src_pan_id: Some(Ieee802154Pan(0xbeef)),
1574         src_addr: Some(Ieee802154Address::Extended([
1575             0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x0b, 0x1a,
1576         ])),
1577     };
1578 
1579     let (mut iface, mut sockets, mut device) = create(Medium::Ieee802154);
1580     iface.inner.caps.checksum.udp = Checksum::None;
1581 
1582     let udp_rx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 1024 * 4]);
1583     let udp_tx_buffer = udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY], vec![0; 1024 * 4]);
1584     let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
1585     let udp_socket_handle = sockets.add(udp_socket);
1586 
1587     {
1588         let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
1589         assert_eq!(socket.bind(6969), Ok(()));
1590         assert!(!socket.can_recv());
1591         assert!(socket.can_send());
1592     }
1593 
1594     let udp_first_part = &[
1595         0xc0, 0xbc, 0x00, 0x92, 0x6e, 0x33, 0x07, 0xe7, 0xdc, 0xf0, 0xd3, 0xc9, 0x1b, 0x39, 0xbf,
1596         0xa0, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64, 0x6f,
1597         0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2c, 0x20, 0x63,
1598         0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70,
1599         0x69, 0x73, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x69, 0x74, 0x2e, 0x20, 0x49, 0x6e,
1600         0x20, 0x61, 0x74, 0x20, 0x72, 0x68, 0x6f, 0x6e, 0x63, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x72,
1601         0x74, 0x6f, 0x72, 0x2e, 0x20, 0x43, 0x72, 0x61, 0x73, 0x20, 0x62, 0x6c, 0x61, 0x6e,
1602     ];
1603 
1604     assert_eq!(
1605         iface.inner.process_sixlowpan(
1606             &mut sockets,
1607             &ieee802154_repr,
1608             udp_first_part,
1609             &mut iface.fragments
1610         ),
1611         None
1612     );
1613 
1614     ieee802154_repr.sequence_number = Some(6);
1615 
1616     let udp_second_part = &[
1617         0xe0, 0xbc, 0x00, 0x92, 0x11, 0x64, 0x69, 0x74, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x75, 0x73,
1618         0x20, 0x64, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x76, 0x61, 0x72, 0x69, 0x75, 0x73, 0x20, 0x76,
1619         0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6c, 0x75, 0x6d, 0x20, 0x6e, 0x69, 0x62, 0x68, 0x20,
1620         0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x6f, 0x20, 0x6e, 0x65, 0x63, 0x2e,
1621     ];
1622 
1623     assert_eq!(
1624         iface.inner.process_sixlowpan(
1625             &mut sockets,
1626             &ieee802154_repr,
1627             udp_second_part,
1628             &mut iface.fragments
1629         ),
1630         None
1631     );
1632 
1633     let socket = sockets.get_mut::<udp::Socket>(udp_socket_handle);
1634 
1635     let udp_data = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
1636                          In at rhoncus tortor. Cras blandit tellus diam, varius vestibulum nibh commodo nec.";
1637     assert_eq!(
1638         socket.recv(),
1639         Ok((
1640             &udp_data[..],
1641             IpEndpoint {
1642                 addr: IpAddress::Ipv6(Ipv6Address([
1643                     0xfe, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x42, 0x42, 0x42, 0x42, 0x42,
1644                     0xb, 0x1a,
1645                 ])),
1646                 port: 54217,
1647             }
1648         ))
1649     );
1650 
1651     let tx_token = device.transmit(Instant::now()).unwrap();
1652     iface.inner.dispatch_ieee802154(
1653         Ieee802154Address::default(),
1654         tx_token,
1655         IpPacket::Udp((
1656             IpRepr::Ipv6(Ipv6Repr {
1657                 src_addr: Ipv6Address::default(),
1658                 dst_addr: Ipv6Address::default(),
1659                 next_header: IpProtocol::Udp,
1660                 payload_len: udp_data.len(),
1661                 hop_limit: 64,
1662             }),
1663             UdpRepr {
1664                 src_port: 1234,
1665                 dst_port: 1234,
1666             },
1667             udp_data,
1668         )),
1669         &mut iface.fragmenter,
1670     );
1671 
1672     iface.poll(Instant::now(), &mut device, &mut sockets);
1673 
1674     assert_eq!(
1675         device.queue[0],
1676         &[
1677             0x41, 0xcc, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1678             0x0, 0x0, 0x0, 0x0, 0xc0, 0xb4, 0x5, 0x4e, 0x7e, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1679             0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf0, 0x4, 0xd2, 0x4, 0xd2, 0xf6,
1680             0x4d, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64,
1681             0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2c,
1682             0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61,
1683             0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x69, 0x74,
1684             0x2e, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x74, 0x20, 0x72, 0x68, 0x6f, 0x6e, 0x63, 0x75,
1685             0x73, 0x20, 0x74,
1686         ]
1687     );
1688 
1689     assert_eq!(
1690         device.queue[1],
1691         &[
1692             0x41, 0xcc, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1693             0x0, 0x0, 0x0, 0x0, 0xe0, 0xb4, 0x5, 0x4e, 0xf, 0x6f, 0x72, 0x74, 0x6f, 0x72, 0x2e,
1694             0x20, 0x43, 0x72, 0x61, 0x73, 0x20, 0x62, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x74, 0x20,
1695             0x74, 0x65, 0x6c, 0x6c, 0x75, 0x73, 0x20, 0x64, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x76,
1696             0x61, 0x72, 0x69, 0x75, 0x73, 0x20, 0x76, 0x65, 0x73, 0x74, 0x69, 0x62, 0x75, 0x6c,
1697             0x75, 0x6d, 0x20, 0x6e, 0x69, 0x62, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64,
1698             0x6f, 0x20, 0x6e, 0x65, 0x63, 0x2e,
1699         ]
1700     );
1701 }
1702