diff --git a/crates/lanparty-client-core/src/lib.rs b/crates/lanparty-client-core/src/lib.rs index edde7e1..ab1768f 100644 --- a/crates/lanparty-client-core/src/lib.rs +++ b/crates/lanparty-client-core/src/lib.rs @@ -914,6 +914,18 @@ mod tests { .send_datagram(Bytes::from(misdirected_response)) .unwrap(); + let dhcp_response = encode_datagram( + FrameType::Ethernet, + 7, + 1, + 0, + &lan_dhcpv4_server_reply_to_client(), + ) + .unwrap(); + connection + .send_datagram(Bytes::from(dhcp_response)) + .unwrap(); + let response = encode_datagram( FrameType::Ethernet, 7, @@ -938,7 +950,7 @@ mod tests { let ControlMessage::Stats(stats) = stats_message else { panic!("expected client stats event"); }; - assert_eq!(stats, TunnelStats::new(1, 3, 1, 3, 10, 1)); + assert_eq!(stats, TunnelStats::new(1, 4, 1, 4, 11, 1)); stats_received_tx.send(()).unwrap(); let mut disconnect_recv = connection.accept_uni().await.unwrap(); @@ -1028,6 +1040,20 @@ mod tests { misdirected_unicast_ethernet_frame().as_slice() ); + let received = + tokio::time::timeout(Duration::from_secs(5), relay_io.recv_ethernet_outcome()) + .await + .unwrap() + .unwrap(); + let ClientReceiveOutcome::Accepted(received) = received else { + panic!("expected accepted LAN DHCP server reply"); + }; + assert_eq!(received.source_peer_id(), 1); + assert_eq!( + received.payload(), + lan_dhcpv4_server_reply_to_client().as_slice() + ); + let received = tokio::time::timeout(Duration::from_secs(5), relay_io.recv_ethernet_outcome()) .await @@ -1107,14 +1133,20 @@ mod tests { .unwrap(), ClientSendOutcome::Dropped(DropReason::VlanTaggedFrame) ); + assert_eq!( + relay_io + .send_ethernet_with_outcome(&remote_dhcpv4_server_reply()) + .unwrap(), + ClientSendOutcome::Dropped(DropReason::DhcpServerReply) + ); let stats = relay_io.stats_snapshot(); assert_eq!(stats.ethernet_frames_tx(), 1); - assert_eq!(stats.ethernet_frames_rx(), 3); + assert_eq!(stats.ethernet_frames_rx(), 4); assert_eq!(stats.broadcast_frames_tx(), 0); assert_eq!(stats.broadcast_frames_rx(), 0); assert_eq!(stats.datagrams_tx(), 1); - assert_eq!(stats.datagrams_rx(), 3); - assert_eq!(stats.dropped_frames(), 10); + assert_eq!(stats.datagrams_rx(), 4); + assert_eq!(stats.dropped_frames(), 11); assert_eq!(stats.malformed_frames(), 1); assert_eq!(client.stats_snapshot(), stats); @@ -1265,6 +1297,33 @@ mod tests { ) } + fn lan_dhcpv4_server_reply_to_client() -> Vec { + ethernet_frame_with_headers( + MacAddr::new([0x02, 0, 0, 0, 0, 1]), + MacAddr::new([0x0a, 0, 0, 0, 0, 2]), + lanparty_proto::ETHERTYPE_IPV4, + &ipv4_udp_payload(67, 68), + ) + } + + fn remote_dhcpv4_server_reply() -> Vec { + ethernet_frame_with_headers( + MacAddr::BROADCAST, + MacAddr::new([0x02, 0, 0, 0, 0, 1]), + lanparty_proto::ETHERTYPE_IPV4, + &ipv4_udp_payload(67, 68), + ) + } + + fn ipv4_udp_payload(source_port: u16, destination_port: u16) -> Vec { + let mut packet = vec![0; 28]; + packet[0] = 0x45; + packet[9] = 17; + packet[20..22].copy_from_slice(&source_port.to_be_bytes()); + packet[22..24].copy_from_slice(&destination_port.to_be_bytes()); + packet + } + fn ethernet_frame_with_headers( destination: MacAddr, source: MacAddr,