fn test_eth_ipv4_arp_frame()

in src/dumbo/src/pdu/arp.rs [351:505]


    fn test_eth_ipv4_arp_frame() {
        let mut a = [0u8; 1000];
        let mut bad_array = [0u8; 1];

        let sha = MacAddr::parse_str("01:23:45:67:89:ab").unwrap();
        let tha = MacAddr::parse_str("cd:ef:01:23:45:67").unwrap();
        let spa = Ipv4Addr::new(10, 1, 2, 3);
        let tpa = Ipv4Addr::new(10, 4, 5, 6);

        // Slice is too short.
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(bad_array.as_ref()).unwrap_err(),
            Error::SliceExactLen
        );

        // Slice is too short.
        assert_eq!(
            EthIPv4ArpFrame::write_reply(bad_array.as_mut(), sha, spa, tha, tpa).unwrap_err(),
            Error::SliceExactLen
        );

        // Slice is too long.
        assert_eq!(
            EthIPv4ArpFrame::write_reply(a.as_mut(), sha, spa, tha, tpa).unwrap_err(),
            Error::SliceExactLen
        );

        // We write a valid ARP reply to the specified slice.
        {
            let f = EthIPv4ArpFrame::write_reply(&mut a[..ETH_IPV4_FRAME_LEN], sha, spa, tha, tpa)
                .unwrap();

            // This is a bit redundant given the following tests, but assert away!
            assert_eq!(f.htype(), HTYPE_ETHERNET);
            assert_eq!(f.ptype(), ETHERTYPE_IPV4);
            assert_eq!(f.hlen(), MAC_ADDR_LEN as u8);
            assert_eq!(f.plen(), IPV4_ADDR_LEN as u8);
            assert_eq!(f.operation(), OPER_REPLY);
            assert_eq!(f.sha(), sha);
            assert_eq!(f.spa(), spa);
            assert_eq!(f.tha(), tha);
            assert_eq!(f.tpa(), tpa);
        }

        // Now let's try to parse a request.

        // Slice is too long.
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(a.as_ref()).unwrap_err(),
            Error::SliceExactLen
        );

        // The length is fine now, but the operation is a reply instead of request.
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).unwrap_err(),
            Error::Operation
        );

        // TODO: The following test code is way more verbose than it should've been. Make it
        // prettier at some point.

        // Let's write a valid request.
        EthIPv4ArpFrame::write_raw(
            &mut a[..ETH_IPV4_FRAME_LEN],
            HTYPE_ETHERNET,
            ETHERTYPE_IPV4,
            MAC_ADDR_LEN as u8,
            IPV4_ADDR_LEN as u8,
            OPER_REQUEST,
            sha,
            spa,
            tha,
            tpa,
        )
        .unwrap();
        assert!(EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).is_ok());

        // Now we start writing invalid requests. We've already tried with an invalid operation.

        // Invalid htype.
        EthIPv4ArpFrame::write_raw(
            &mut a[..ETH_IPV4_FRAME_LEN],
            HTYPE_ETHERNET + 1,
            ETHERTYPE_IPV4,
            MAC_ADDR_LEN as u8,
            IPV4_ADDR_LEN as u8,
            OPER_REQUEST,
            sha,
            spa,
            tha,
            tpa,
        )
        .unwrap();
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).unwrap_err(),
            Error::HType
        );

        // Invalid ptype.
        EthIPv4ArpFrame::write_raw(
            &mut a[..ETH_IPV4_FRAME_LEN],
            HTYPE_ETHERNET,
            ETHERTYPE_IPV4 + 1,
            MAC_ADDR_LEN as u8,
            IPV4_ADDR_LEN as u8,
            OPER_REQUEST,
            sha,
            spa,
            tha,
            tpa,
        )
        .unwrap();
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).unwrap_err(),
            Error::PType
        );

        // Invalid hlen.
        EthIPv4ArpFrame::write_raw(
            &mut a[..ETH_IPV4_FRAME_LEN],
            HTYPE_ETHERNET,
            ETHERTYPE_IPV4,
            MAC_ADDR_LEN as u8 + 1,
            IPV4_ADDR_LEN as u8,
            OPER_REQUEST,
            sha,
            spa,
            tha,
            tpa,
        )
        .unwrap();
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).unwrap_err(),
            Error::HLen
        );

        // Invalid plen.
        EthIPv4ArpFrame::write_raw(
            &mut a[..ETH_IPV4_FRAME_LEN],
            HTYPE_ETHERNET,
            ETHERTYPE_IPV4,
            MAC_ADDR_LEN as u8,
            IPV4_ADDR_LEN as u8 + 1,
            OPER_REQUEST,
            sha,
            spa,
            tha,
            tpa,
        )
        .unwrap();
        assert_eq!(
            EthIPv4ArpFrame::request_from_bytes(&a[..ETH_IPV4_FRAME_LEN]).unwrap_err(),
            Error::PLen
        );
    }