vmm/mmds/
ns.rs

1// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4// TODO: get rid of this when splitting dumbo into public and internal parts.
5#![allow(missing_docs)]
6
7use std::convert::From;
8use std::net::Ipv4Addr;
9use std::num::NonZeroUsize;
10use std::str::FromStr;
11use std::sync::{Arc, Mutex};
12
13use utils::time::timestamp_cycles;
14
15use crate::dumbo::pdu::Incomplete;
16use crate::dumbo::pdu::arp::{
17    ArpError as ArpFrameError, ETH_IPV4_FRAME_LEN, EthIPv4ArpFrame, test_speculative_tpa,
18};
19use crate::dumbo::pdu::ethernet::{
20    ETHERTYPE_ARP, ETHERTYPE_IPV4, EthernetError as EthernetFrameError, EthernetFrame,
21};
22use crate::dumbo::pdu::ipv4::{
23    IPv4Packet, Ipv4Error as IPv4PacketError, PROTOCOL_TCP, test_speculative_dst_addr,
24};
25use crate::dumbo::pdu::tcp::TcpError as TcpSegmentError;
26use crate::dumbo::tcp::NextSegmentStatus;
27use crate::dumbo::tcp::handler::{RecvEvent, TcpIPv4Handler, WriteEvent, WriteNextError};
28use crate::logger::{IncMetric, METRICS};
29use crate::mmds::data_store::Mmds;
30use crate::utils::net::mac::MacAddr;
31
32const DEFAULT_MAC_ADDR: &str = "06:01:23:45:67:01";
33const DEFAULT_IPV4_ADDR: [u8; 4] = [169, 254, 169, 254];
34const DEFAULT_TCP_PORT: u16 = 80;
35const DEFAULT_MAX_CONNECTIONS: usize = 30;
36const DEFAULT_MAX_PENDING_RESETS: usize = 100;
37
38#[derive(Debug, PartialEq, thiserror::Error, displaydoc::Display)]
39enum WriteArpFrameError {
40    /// NoPendingArpReply
41    NoPendingArpReply,
42    /// ARP error: {0}
43    Arp(#[from] ArpFrameError),
44    /// Ethernet error: {0}
45    Ethernet(#[from] EthernetFrameError),
46}
47
48#[derive(Debug, PartialEq, thiserror::Error, displaydoc::Display)]
49enum WritePacketError {
50    /// IPv4Packet error: {0}
51    IPv4Packet(#[from] IPv4PacketError),
52    /// Ethernet error: {0}
53    Ethernet(#[from] EthernetFrameError),
54    /// TcpSegment error: {0}
55    TcpSegment(#[from] TcpSegmentError),
56    /// WriteNext error: {0}
57    WriteNext(#[from] WriteNextError),
58}
59
60#[derive(Debug)]
61pub struct MmdsNetworkStack {
62    // Network interface MAC address used by frames/packets heading to MMDS server.
63    remote_mac_addr: MacAddr,
64    // The Ethernet MAC address of the MMDS server.
65    pub(crate) mac_addr: MacAddr,
66    // MMDS server IPv4 address.
67    pub ipv4_addr: Ipv4Addr,
68    // ARP reply destination IPv4 address (requester of address resolution reply).
69    // It is the Ipv4Addr of the network interface for which the MmdsNetworkStack
70    // routes the packets.
71    pending_arp_reply_dest: Option<Ipv4Addr>,
72    // This handles MMDS<->guest interaction at the TCP level.
73    pub(crate) tcp_handler: TcpIPv4Handler,
74    // Data store reference shared across all MmdsNetworkStack instances.
75    pub mmds: Arc<Mutex<Mmds>>,
76}
77
78impl MmdsNetworkStack {
79    pub fn new(
80        mac_addr: MacAddr,
81        ipv4_addr: Ipv4Addr,
82        tcp_port: u16,
83        mmds: Arc<Mutex<Mmds>>,
84    ) -> Self {
85        MmdsNetworkStack {
86            remote_mac_addr: mac_addr,
87            mac_addr,
88            ipv4_addr,
89            pending_arp_reply_dest: None,
90            tcp_handler: TcpIPv4Handler::new(
91                ipv4_addr,
92                tcp_port,
93                NonZeroUsize::new(DEFAULT_MAX_CONNECTIONS).unwrap(),
94                NonZeroUsize::new(DEFAULT_MAX_PENDING_RESETS).unwrap(),
95            ),
96            mmds,
97        }
98    }
99
100    pub fn new_with_defaults(mmds_ipv4_addr: Option<Ipv4Addr>, mmds: Arc<Mutex<Mmds>>) -> Self {
101        let mac_addr = MacAddr::from_str(DEFAULT_MAC_ADDR).unwrap();
102        let ipv4_addr = mmds_ipv4_addr.unwrap_or_else(|| Ipv4Addr::from(DEFAULT_IPV4_ADDR));
103
104        // The unwrap()s are safe because the given literals are greater than 0.
105        Self::new(mac_addr, ipv4_addr, DEFAULT_TCP_PORT, mmds)
106    }
107
108    pub fn set_ipv4_addr(&mut self, ipv4_addr: Ipv4Addr) {
109        self.ipv4_addr = ipv4_addr;
110        self.tcp_handler.set_local_ipv4_addr(ipv4_addr);
111    }
112
113    pub fn ipv4_addr(&self) -> Ipv4Addr {
114        self.ipv4_addr
115    }
116
117    pub fn default_ipv4_addr() -> Ipv4Addr {
118        Ipv4Addr::from(DEFAULT_IPV4_ADDR)
119    }
120
121    /// Check if a frame is destined for `mmds`
122    ///
123    /// This returns `true` if the frame is an ARP or IPv4 frame destined for
124    /// the `mmds` service, or `false` otherwise. It does not consume the frame.
125    pub fn is_mmds_frame(&self, src: &[u8]) -> bool {
126        if let Ok(eth) = EthernetFrame::from_bytes(src) {
127            match eth.ethertype() {
128                ETHERTYPE_ARP => test_speculative_tpa(src, self.ipv4_addr),
129                ETHERTYPE_IPV4 => test_speculative_dst_addr(src, self.ipv4_addr),
130                _ => false,
131            }
132        } else {
133            false
134        }
135    }
136
137    /// Handles a frame destined for `mmds`
138    ///
139    /// It assumes that the frame is indeed destined for `mmds`, so the caller
140    /// must make a call to `is_mmds_frame` to ensure that.
141    ///
142    /// # Returns
143    ///
144    /// `true` if the frame was consumed by `mmds` or `false` if an error occured
145    pub fn detour_frame(&mut self, src: &[u8]) -> bool {
146        if let Ok(eth) = EthernetFrame::from_bytes(src) {
147            match eth.ethertype() {
148                ETHERTYPE_ARP => return self.detour_arp(eth),
149                ETHERTYPE_IPV4 => return self.detour_ipv4(eth),
150                _ => (),
151            }
152        } else {
153            METRICS.mmds.rx_bad_eth.inc();
154        }
155
156        false
157    }
158
159    fn detour_arp(&mut self, eth: EthernetFrame<&[u8]>) -> bool {
160        if let Ok(arp) = EthIPv4ArpFrame::request_from_bytes(eth.payload()) {
161            self.remote_mac_addr = arp.sha();
162            self.pending_arp_reply_dest = Some(arp.spa());
163            return true;
164        }
165
166        false
167    }
168
169    fn detour_ipv4(&mut self, eth: EthernetFrame<&[u8]>) -> bool {
170        // TODO: We skip verifying the checksum, just in case the device model relies on offloading
171        // checksum computation from the guest driver to some other entity. Clear up this entire
172        // context at some point!
173        if let Ok(ip) = IPv4Packet::from_bytes(eth.payload(), false) {
174            if ip.protocol() == PROTOCOL_TCP {
175                // Note-1: `remote_mac_address` is actually the network device mac address, where
176                // this TCP segment came from.
177                // Note-2: For every routed packet we will have a single source MAC address, because
178                // each MmdsNetworkStack routes packets for only one network device.
179                self.remote_mac_addr = eth.src_mac();
180                let mmds_instance = self.mmds.clone();
181                match &mut self.tcp_handler.receive_packet(&ip, move |request| {
182                    super::convert_to_response(mmds_instance, request)
183                }) {
184                    Ok(event) => {
185                        METRICS.mmds.rx_count.inc();
186                        match event {
187                            RecvEvent::NewConnectionSuccessful => {
188                                METRICS.mmds.connections_created.inc()
189                            }
190                            RecvEvent::NewConnectionReplacing => {
191                                METRICS.mmds.connections_created.inc();
192                                METRICS.mmds.connections_destroyed.inc();
193                            }
194                            RecvEvent::EndpointDone => {
195                                METRICS.mmds.connections_destroyed.inc();
196                            }
197                            _ => (),
198                        }
199                    }
200                    Err(_) => METRICS.mmds.rx_accepted_err.inc(),
201                }
202            } else {
203                // A non-TCP IPv4 packet heading towards the MMDS; we consider it unusual.
204                METRICS.mmds.rx_accepted_unusual.inc();
205            }
206            return true;
207        }
208
209        false
210    }
211
212    // Allows the MMDS network stack to write a frame to the specified buffer. Will return:
213    // - None, if the MMDS network stack has no frame to send at this point. The buffer can be
214    // used for something else by the device model.
215    // - Some(len), if a frame of the given length has been written to the specified buffer.
216    pub fn write_next_frame(&mut self, buf: &mut [u8]) -> Option<NonZeroUsize> {
217        // We try to send ARP replies first.
218        if self.pending_arp_reply_dest.is_some() {
219            return match self.write_arp_reply(buf) {
220                Ok(something) => {
221                    METRICS.mmds.tx_count.inc();
222                    self.pending_arp_reply_dest = None;
223                    something
224                }
225                Err(_) => {
226                    METRICS.mmds.tx_errors.inc();
227                    None
228                }
229            };
230        } else {
231            let call_write = match self.tcp_handler.next_segment_status() {
232                NextSegmentStatus::Available => true,
233                NextSegmentStatus::Timeout(value) => timestamp_cycles() >= value,
234                NextSegmentStatus::Nothing => false,
235            };
236
237            if call_write {
238                return match self.write_packet(buf) {
239                    Ok(something) => {
240                        METRICS.mmds.tx_count.inc();
241                        something
242                    }
243                    Err(_) => {
244                        METRICS.mmds.tx_errors.inc();
245                        None
246                    }
247                };
248            }
249        }
250        None
251    }
252
253    fn prepare_eth_unsized<'a>(
254        &self,
255        buf: &'a mut [u8],
256        ethertype: u16,
257    ) -> Result<Incomplete<EthernetFrame<'a, &'a mut [u8]>>, EthernetFrameError> {
258        EthernetFrame::write_incomplete(buf, self.remote_mac_addr, self.mac_addr, ethertype)
259    }
260
261    fn write_arp_reply(&self, buf: &mut [u8]) -> Result<Option<NonZeroUsize>, WriteArpFrameError> {
262        let arp_reply_dest = self
263            .pending_arp_reply_dest
264            .ok_or(WriteArpFrameError::NoPendingArpReply)?;
265
266        let mut eth_unsized = self.prepare_eth_unsized(buf, ETHERTYPE_ARP)?;
267
268        let arp_len = EthIPv4ArpFrame::write_reply(
269            eth_unsized
270                .inner_mut()
271                .payload_mut()
272                .split_at_mut(ETH_IPV4_FRAME_LEN)
273                .0,
274            self.mac_addr,
275            self.ipv4_addr,
276            self.remote_mac_addr,
277            arp_reply_dest,
278        )?
279        .len();
280
281        Ok(Some(
282            // The unwrap() is safe because arp_len > 0.
283            NonZeroUsize::new(eth_unsized.with_payload_len_unchecked(arp_len).len()).unwrap(),
284        ))
285    }
286
287    fn write_packet(&mut self, buf: &mut [u8]) -> Result<Option<NonZeroUsize>, WritePacketError> {
288        let mut eth_unsized = self.prepare_eth_unsized(buf, ETHERTYPE_IPV4)?;
289
290        let (maybe_len, event) = self
291            .tcp_handler
292            .write_next_packet(eth_unsized.inner_mut().payload_mut())?;
293
294        if let WriteEvent::EndpointDone = event {
295            METRICS.mmds.connections_destroyed.inc()
296        }
297
298        if let Some(packet_len) = maybe_len {
299            return Ok(Some(
300                // The unwrap() is safe because packet_len > 0.
301                NonZeroUsize::new(
302                    eth_unsized
303                        .with_payload_len_unchecked(packet_len.get())
304                        .len(),
305                )
306                .unwrap(),
307            ));
308        }
309
310        Ok(None)
311    }
312}
313
314#[cfg(test)]
315mod tests {
316    use std::str::FromStr;
317
318    use super::*;
319    use crate::dumbo::pdu::tcp::{Flags as TcpFlags, TcpSegment};
320
321    // We use LOCALHOST here because const new() is not stable yet, so just reuse this const, since
322    // all we're interested in is having some address different from the MMDS one.
323    const REMOTE_ADDR: Ipv4Addr = Ipv4Addr::LOCALHOST;
324    const REMOTE_MAC_STR: &str = "11:11:11:22:22:22";
325    const MMDS_PORT: u16 = 80;
326    const REMOTE_PORT: u16 = 1235;
327    const SEQ_NUMBER: u32 = 123;
328
329    // Helper methods which only make sense for testing.
330    impl MmdsNetworkStack {
331        fn write_arp_request(&mut self, buf: &mut [u8], for_mmds: bool) -> usize {
332            // Write a reply and then modify it into a request.
333            self.pending_arp_reply_dest = Some(REMOTE_ADDR);
334            let len = self.write_arp_reply(buf).unwrap().unwrap().get();
335            self.pending_arp_reply_dest = None;
336
337            let mut eth = EthernetFrame::from_bytes_unchecked(&mut buf[..len]);
338            let mut arp = EthIPv4ArpFrame::from_bytes_unchecked(eth.payload_mut());
339
340            // Set the operation to REQUEST.
341            arp.set_operation(1);
342            arp.set_sha(MacAddr::from_str(REMOTE_MAC_STR).unwrap());
343            arp.set_spa(REMOTE_ADDR);
344
345            // The tpa remains REMOTE_ADDR otherwise, and is thus invalid for the MMDS.
346            if for_mmds {
347                arp.set_tpa(self.ipv4_addr);
348            }
349            len
350        }
351
352        fn write_incoming_tcp_segment(
353            &self,
354            buf: &mut [u8],
355            addr: Ipv4Addr,
356            flags: TcpFlags,
357        ) -> usize {
358            let mut eth_unsized = self.prepare_eth_unsized(buf, ETHERTYPE_IPV4).unwrap();
359            let packet_len = {
360                let mut packet = IPv4Packet::write_header(
361                    eth_unsized.inner_mut().payload_mut(),
362                    PROTOCOL_TCP,
363                    REMOTE_ADDR,
364                    addr,
365                )
366                .unwrap();
367
368                let segment_len = TcpSegment::write_incomplete_segment::<[u8]>(
369                    packet.inner_mut().payload_mut(),
370                    SEQ_NUMBER,
371                    1234,
372                    flags,
373                    10000,
374                    None,
375                    0,
376                    None,
377                )
378                .unwrap()
379                .finalize(REMOTE_PORT, MMDS_PORT, Some((REMOTE_ADDR, addr)))
380                .len();
381
382                packet.with_payload_len_unchecked(segment_len, true).len()
383            };
384
385            eth_unsized.with_payload_len_unchecked(packet_len).len()
386        }
387
388        fn next_frame_as_ipv4_packet<'a>(&mut self, buf: &'a mut [u8]) -> IPv4Packet<'_, &'a [u8]> {
389            let len = self.write_next_frame(buf).unwrap().get();
390            let eth = EthernetFrame::from_bytes(&buf[..len]).unwrap();
391            IPv4Packet::from_bytes(&buf[eth.payload_offset()..len], true).unwrap()
392        }
393    }
394
395    #[test]
396    fn test_ns_new_with_defaults() {
397        let ns = MmdsNetworkStack::new_with_defaults(None, Arc::new(Mutex::new(Mmds::default())));
398        assert_eq!(ns.mac_addr, MacAddr::from_str(DEFAULT_MAC_ADDR).unwrap());
399        assert_eq!(ns.ipv4_addr, Ipv4Addr::from(DEFAULT_IPV4_ADDR));
400
401        let ns = MmdsNetworkStack::new_with_defaults(
402            Some(Ipv4Addr::LOCALHOST),
403            Arc::new(Mutex::new(Mmds::default())),
404        );
405        assert_eq!(ns.mac_addr, MacAddr::from_str(DEFAULT_MAC_ADDR).unwrap());
406        assert_eq!(ns.ipv4_addr, Ipv4Addr::LOCALHOST);
407    }
408
409    #[test]
410    #[allow(clippy::cognitive_complexity)]
411    fn test_ns() {
412        let mut ns =
413            MmdsNetworkStack::new_with_defaults(None, Arc::new(Mutex::new(Mmds::default())));
414        let mut buf = [0u8; 2000];
415        let mut bad_buf = [0u8; 1];
416
417        let remote_mac = MacAddr::from_str(REMOTE_MAC_STR).unwrap();
418        let mmds_addr = ns.ipv4_addr;
419        let bad_mmds_addr = Ipv4Addr::from_str("1.2.3.4").unwrap();
420
421        // Buffer is too small.
422        assert!(!ns.is_mmds_frame(&bad_buf));
423        assert!(!ns.detour_frame(bad_buf.as_ref()));
424
425        // There's nothing to send right now.
426        assert!(ns.write_next_frame(buf.as_mut()).is_none());
427
428        {
429            let len = ns.write_arp_request(buf.as_mut(), false);
430            // Not asking for MMDS MAC address.
431            assert!(!ns.is_mmds_frame(&buf[..len]));
432            // There's still nothing to send.
433            assert!(ns.write_next_frame(buf.as_mut()).is_none());
434        }
435
436        {
437            let len = ns.write_arp_request(buf.as_mut(), true);
438
439            // Asking for MMDS MAC address.
440            assert!(ns.detour_frame(&buf[..len]));
441            assert_eq!(ns.remote_mac_addr, remote_mac);
442        }
443
444        // There should be an ARP reply to send.
445        {
446            // Buffer is too small.
447            assert!(ns.write_next_frame(bad_buf.as_mut()).is_none());
448            let curr_tx_count = METRICS.mmds.tx_count.count();
449            let len = ns.write_next_frame(buf.as_mut()).unwrap().get();
450            assert_eq!(curr_tx_count + 1, METRICS.mmds.tx_count.count());
451            let eth = EthernetFrame::from_bytes(&buf[..len]).unwrap();
452            let arp_reply = EthIPv4ArpFrame::from_bytes_unchecked(eth.payload());
453
454            // REPLY = 2
455            assert_eq!(arp_reply.operation(), 2);
456            assert_eq!(arp_reply.sha(), ns.mac_addr);
457            assert_eq!(arp_reply.spa(), ns.ipv4_addr);
458            assert_eq!(arp_reply.tha(), ns.remote_mac_addr);
459            assert_eq!(arp_reply.tpa(), REMOTE_ADDR);
460        }
461
462        // Nothing to send anymore.
463        assert!(ns.write_next_frame(buf.as_mut()).is_none());
464
465        // Let's send a TCP segment which will be rejected, because it's heading to the wrong
466        // address.
467        {
468            let len = ns.write_incoming_tcp_segment(buf.as_mut(), bad_mmds_addr, TcpFlags::ACK);
469            assert!(!ns.is_mmds_frame(&buf[..len]));
470
471            // Nothing to send in response.
472            assert!(ns.write_next_frame(buf.as_mut()).is_none());
473        }
474
475        // Let's send a TCP segment which will cause a RST to come out of the inner TCP handler.
476        {
477            let len = ns.write_incoming_tcp_segment(buf.as_mut(), mmds_addr, TcpFlags::ACK);
478            let curr_rx_count = METRICS.mmds.rx_count.count();
479            assert!(ns.detour_frame(&buf[..len]));
480            assert_eq!(curr_rx_count + 1, METRICS.mmds.rx_count.count());
481        }
482
483        // Let's check we actually get a RST when writing the next frame.
484        {
485            assert!(ns.write_next_frame(bad_buf.as_mut()).is_none());
486
487            let ip = ns.next_frame_as_ipv4_packet(buf.as_mut());
488            assert_eq!(ip.source_address(), mmds_addr);
489            assert_eq!(ip.destination_address(), REMOTE_ADDR);
490
491            let s = TcpSegment::from_bytes(
492                ip.payload(),
493                Some((ip.source_address(), ip.destination_address())),
494            )
495            .unwrap();
496            assert_eq!(s.flags_after_ns(), TcpFlags::RST);
497            assert_eq!(s.source_port(), MMDS_PORT);
498            assert_eq!(s.destination_port(), REMOTE_PORT);
499        }
500
501        // Nothing else to send.
502        assert!(ns.write_next_frame(buf.as_mut()).is_none());
503
504        // Let's send a TCP SYN into the ns.
505        {
506            let len = ns.write_incoming_tcp_segment(buf.as_mut(), mmds_addr, TcpFlags::SYN);
507            assert!(ns.detour_frame(&buf[..len]));
508        }
509
510        // We should be getting a SYNACK out of the ns in response.
511        {
512            let ip = ns.next_frame_as_ipv4_packet(buf.as_mut());
513            assert_eq!(ip.source_address(), mmds_addr);
514            assert_eq!(ip.destination_address(), REMOTE_ADDR);
515
516            let s = TcpSegment::from_bytes(
517                ip.payload(),
518                Some((ip.source_address(), ip.destination_address())),
519            )
520            .unwrap();
521            assert_eq!(s.flags_after_ns(), TcpFlags::SYN | TcpFlags::ACK);
522            assert_eq!(s.source_port(), MMDS_PORT);
523            assert_eq!(s.destination_port(), REMOTE_PORT);
524            assert_eq!(s.ack_number(), SEQ_NUMBER.wrapping_add(1));
525        }
526
527        // Nothing else to send.
528        assert!(ns.write_next_frame(buf.as_mut()).is_none());
529    }
530
531    #[test]
532    fn test_set_ipv4_addr() {
533        let mut ns =
534            MmdsNetworkStack::new_with_defaults(None, Arc::new(Mutex::new(Mmds::default())));
535        assert_ne!(ns.ipv4_addr, Ipv4Addr::LOCALHOST);
536        assert_ne!(ns.tcp_handler.local_ipv4_addr(), Ipv4Addr::LOCALHOST);
537        ns.set_ipv4_addr(Ipv4Addr::LOCALHOST);
538        assert_eq!(ns.ipv4_addr, Ipv4Addr::LOCALHOST);
539        assert_eq!(ns.tcp_handler.local_ipv4_addr(), Ipv4Addr::LOCALHOST);
540    }
541
542    #[test]
543    fn test_default_ipv4_addr() {
544        let actual = MmdsNetworkStack::default_ipv4_addr();
545        let expected = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
546        assert_eq!(actual, expected);
547    }
548
549    #[test]
550    fn test_break_speculative_check_detour_arp() {
551        let mut buf = [0u8; 2000];
552        let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
553        let other_ip = Ipv4Addr::new(5, 6, 7, 8);
554        let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
555        let mut ns =
556            MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
557
558        let mut eth =
559            EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap();
560        let mut arp = EthIPv4ArpFrame::from_bytes_unchecked(eth.inner_mut().payload_mut());
561        arp.set_tpa(other_ip);
562        let len = ns.write_arp_request(buf.as_mut(), false);
563
564        eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap();
565        IPv4Packet::from_bytes_unchecked(eth.inner_mut().payload_mut()).set_destination_address(ip);
566
567        assert!(!ns.is_mmds_frame(&buf[..len]));
568    }
569
570    #[test]
571    fn test_break_speculative_check_detour_ipv4() {
572        let mut buf = [0u8; 2000];
573        let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
574        let other_ip = Ipv4Addr::new(5, 6, 7, 8);
575        let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
576        let ns =
577            MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
578
579        let mut eth =
580            EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap();
581        IPv4Packet::from_bytes_unchecked(eth.inner_mut().payload_mut())
582            .set_destination_address(other_ip);
583        let len = ns.write_incoming_tcp_segment(buf.as_mut(), other_ip, TcpFlags::SYN);
584        eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap();
585        let mut arp = EthIPv4ArpFrame::from_bytes_unchecked(eth.inner_mut().payload_mut());
586        arp.set_tpa(ip);
587        assert!(!ns.is_mmds_frame(&buf[..len]));
588    }
589
590    #[test]
591    fn test_wrong_ethertype() {
592        let mut buf = [0u8; 2000];
593        let ip = Ipv4Addr::from(DEFAULT_IPV4_ADDR);
594        let other_ip = Ipv4Addr::new(5, 6, 7, 8);
595        let mac = MacAddr::from_bytes_unchecked(&[0; 6]);
596        let mut ns =
597            MmdsNetworkStack::new_with_defaults(Some(ip), Arc::new(Mutex::new(Mmds::default())));
598
599        // try IPv4 with detour_arp
600        let mut eth =
601            EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap();
602        IPv4Packet::from_bytes_unchecked(eth.inner_mut().payload_mut())
603            .set_destination_address(other_ip);
604        let len = ns.write_incoming_tcp_segment(buf.as_mut(), other_ip, TcpFlags::SYN);
605
606        eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_IPV4).unwrap();
607        let mut arp = EthIPv4ArpFrame::from_bytes_unchecked(eth.inner_mut().payload_mut());
608        arp.set_tpa(ip);
609
610        assert!(ns.detour_ipv4(EthernetFrame::from_bytes(&buf[..len]).unwrap()));
611        assert!(!ns.detour_arp(EthernetFrame::from_bytes(&buf[..len]).unwrap()));
612
613        // try IPv4 with detour_arp
614        let mut eth =
615            EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap();
616        let mut arp = EthIPv4ArpFrame::from_bytes_unchecked(eth.inner_mut().payload_mut());
617        arp.set_tpa(other_ip);
618        let len = ns.write_arp_request(buf.as_mut(), false);
619
620        eth = EthernetFrame::write_incomplete(buf.as_mut(), mac, mac, ETHERTYPE_ARP).unwrap();
621        IPv4Packet::from_bytes_unchecked(eth.inner_mut().payload_mut()).set_destination_address(ip);
622
623        assert!(ns.detour_arp(EthernetFrame::from_bytes(&buf[..len]).unwrap()));
624        assert!(!ns.detour_ipv4(EthernetFrame::from_bytes(&buf[..len]).unwrap()));
625    }
626}