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