From 808255b8e4b41ae7ef793872080047526e2323b7 Mon Sep 17 00:00:00 2001 From: weqe Date: Sat, 29 Jun 2024 13:37:10 +0300 Subject: [PATCH] Introduction of sending ARP pakcets. --- holo-vrrp/src/network.rs | 55 ++++++++++++++++++--------- holo-vrrp/src/packet.rs | 70 +++++++++++++++++++++++++++++++++++ holo-vrrp/tests/packet/arp.rs | 44 ++++++++++++++++++++++ holo-vrrp/tests/packet/mod.rs | 1 + 4 files changed, 152 insertions(+), 18 deletions(-) create mode 100644 holo-vrrp/tests/packet/arp.rs diff --git a/holo-vrrp/src/network.rs b/holo-vrrp/src/network.rs index 6b55ba38..d8d7a337 100644 --- a/holo-vrrp/src/network.rs +++ b/holo-vrrp/src/network.rs @@ -4,7 +4,7 @@ // SPDX-License-Identifier: MIT // -use std::net::IpAddr; +use std::net::{IpAddr, SocketAddrV4, Ipv4Addr}; use std::sync::Arc; use holo_utils::socket::{AsyncFd, Socket}; @@ -14,16 +14,20 @@ use socket2::{Domain, Protocol, Type}; use tokio::sync::mpsc::error::SendError; use crate::error::IoError; -use crate::packet::VrrpPacket; +use crate::packet::{VrrpPacket, ArpPacket}; use crate::tasks::messages::input::NetRxPacketMsg; use crate::tasks::messages::output::NetTxPacketMsg; -pub fn socket_vrrp(_ifname: &str) -> Result { +pub(crate) fn socket_vrrp(ifname: &str) -> Result { #[cfg(not(feature = "testing"))] { let socket = capabilities::raise(|| { Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::from(112))) })?; + + capabilities::raise(|| { + socket.bind_device(Some(ifname.as_bytes())) + })?; socket.set_broadcast(true)?; Ok(socket) } @@ -33,14 +37,15 @@ pub fn socket_vrrp(_ifname: &str) -> Result { } } -pub(crate) fn socket_arp(_ifname: &str) -> Result { +pub(crate) fn socket_arp(ifname: &str) -> Result { #[cfg(not(feature = "testing"))] { - // TODO + let eth_p_all = 0x0003; let socket = capabilities::raise(|| { - Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::from(112))) + Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::from(eth_p_all))) })?; socket.set_broadcast(true)?; + socket.bind_device(Some(ifname.as_bytes())); Ok(socket) } #[cfg(feature = "testing")] @@ -50,20 +55,19 @@ pub(crate) fn socket_arp(_ifname: &str) -> Result { } #[cfg(not(feature = "testing"))] -pub async fn send_packet_vrrp( +pub(crate) async fn send_packet_vrrp( socket: &AsyncFd, _src: IpAddr, _dst: IpAddr, packet: VrrpPacket, ) -> Result { - use std::net::{Ipv4Addr, SocketAddrV4}; let buf: &[u8] = &packet.encode(); let saddr = SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 8), 0); socket .async_io(tokio::io::Interest::WRITABLE, |sock| { - sock.send_to(&buf, &saddr.into()) + sock.send_to(buf, &saddr.into()) .map_err(|errno| errno.into()) }) .await @@ -71,12 +75,25 @@ pub async fn send_packet_vrrp( } #[cfg(not(feature = "testing"))] -async fn send_packet_arp( - _socket: &AsyncFd, - // TODO: add other params -) -> Result<(), IoError> { - // TODO - Ok(()) +pub(crate) async fn send_packet_arp( + socket: &AsyncFd, + packet: ArpPacket +) -> Result { + + let buf: &[u8]= &packet.encode(); + let target = Ipv4Addr::from(packet.clone().target_proto_address); + let saddr = SocketAddrV4::new(target, 0); + + socket + .async_io(tokio::io::Interest::WRITABLE, |sock| { + sock.send_to(&buf, &saddr.into()) + .map_err(|errno| { + println!("error...{:#?}", errno); + errno.into() + }) + }) + .await + .map_err(IoError::SendError) } #[cfg(not(feature = "testing"))] @@ -95,9 +112,11 @@ pub(crate) async fn write_loop( } } NetTxPacketMsg::Arp {} => { - if let Err(error) = send_packet_arp(&socket_arp).await { - error.log(); - } + + // if let Err(error) = send_packet_arp(&socket_arp).await { + // error.log(); + // } + } } } diff --git a/holo-vrrp/src/packet.rs b/holo-vrrp/src/packet.rs index 94bbdf1c..f0f83f9e 100644 --- a/holo-vrrp/src/packet.rs +++ b/holo-vrrp/src/packet.rs @@ -91,6 +91,21 @@ pub struct Ipv4Packet { pub padding: Option, } + +#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Deserialize, Serialize)] +pub struct ArpPacket { + pub hw_type: u16, + pub proto_type: u16, + pub hw_length: u8, + pub proto_length: u8, + pub operation: u16, + pub sender_hw_address: [u8; 6], // src mac + pub sender_proto_address: [u8; 4], // src ip + pub target_hw_address: [u8; 6], // src mac + pub target_proto_address: [u8; 4] // src ip +} + #[derive(Debug, Eq, PartialEq)] #[derive(Deserialize, Serialize)] pub enum DecodeError { @@ -306,6 +321,61 @@ impl Ipv4Packet { } } + +impl ArpPacket { + pub fn encode(&self) -> BytesMut { + let mut buf = BytesMut::with_capacity(28); + buf.put_u16(self.hw_type); + buf.put_u16(self.proto_type); + buf.put_u8(self.hw_length); + buf.put_u8(self.proto_length); + buf.put_u16(self.operation); + + for x in self.sender_hw_address { buf.put_u8(x); } + for x in self.sender_proto_address { buf.put_u8(x); } + for x in self.target_hw_address { buf.put_u8(x) } + for x in self.target_proto_address { buf.put_u8(x) } + buf + } + + pub fn decode(data: &[u8]) ->DecodeResult { + if data.len() != 28 { + return Err(DecodeError::PacketLengthError) + } + let mut buf = Bytes::copy_from_slice(data); + + let hw_type = buf.get_u16(); + let proto_type = buf.get_u16(); + let hw_length = buf.get_u8(); + let proto_length = buf.get_u8(); + let operation = buf.get_u16(); + let mut sender_hw_address: [u8; 6] = [0_u8; 6]; + for x in 0..6 { sender_hw_address[x] = buf.get_u8(); } + + let mut sender_proto_address: [u8; 4] = [0_u8; 4]; + for x in 0..4 { sender_proto_address[x] = buf.get_u8(); } + + let mut target_hw_address: [u8; 6] = [0_u8; 6]; + for x in 0..6 { target_hw_address[x] = buf.get_u8(); } + + let mut target_proto_address: [u8; 4] = [0_u8; 4]; + for x in 0..4 { target_hw_address[x] = buf.get_u8(); } + + Ok(Self { + hw_type, + proto_type, + hw_length, + proto_length, + operation, + sender_hw_address, + sender_proto_address, + target_hw_address, + target_proto_address, + }) + + } +} + pub mod checksum { pub fn calculate(data: &[u8], checksum_position: usize) -> u16 { let mut result: u16 = 0; diff --git a/holo-vrrp/tests/packet/arp.rs b/holo-vrrp/tests/packet/arp.rs new file mode 100644 index 00000000..bfee3c9b --- /dev/null +++ b/holo-vrrp/tests/packet/arp.rs @@ -0,0 +1,44 @@ +// +// Copyright (c) The Holo Core Contributors +// +// SPDX-License-Identifier: MIT +// + +use holo_vrrp::packet::{ArpPacket, DecodeError}; + + +/* +ARP packet => + + +hw_type: 1, +proto_type: 0x0800, +hw_length: 6, +proto_length: 4, +operation: 1, +sender_hw_address: [0xd4, 0xb1, 0x08, 0x4c, 0xbb, 0xf9], // src mac +sender_proto_address: [192, 168, 100, 1], // src ip +pub target_hw_address: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // src mac +pub target_proto_address: [192, 168, 100, 16] // src ip + +*/ +fn valid_pkt_data() -> [u8; 28] { + [ + + 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xd4, 0xb1, 0x08, 0x4c, 0xbb, 0xf9, + 0xc0, 0xa8, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x64, 0x10 + ] +} + + +#[test] +fn encode_valid_pkt(){ + let pkt_wrapped = ArpPacket::decode(&valid_pkt_data()); + assert!(pkt_wrapped.is_ok()); +} + +#[test] +fn test_pkt_invalid_length() { + let pkt = ArpPacket::decode(&[0x01]); + assert_eq!(pkt, Err(DecodeError::PacketLengthError)); +} diff --git a/holo-vrrp/tests/packet/mod.rs b/holo-vrrp/tests/packet/mod.rs index 9fef7bed..a21841f3 100644 --- a/holo-vrrp/tests/packet/mod.rs +++ b/holo-vrrp/tests/packet/mod.rs @@ -6,3 +6,4 @@ mod ipv4; mod vrrp; +mod arp; \ No newline at end of file