Skip to content

Commit

Permalink
ARP packet sending...still to work on malformed
Browse files Browse the repository at this point in the history
packet errors
  • Loading branch information
Paul-weqe committed Jul 4, 2024
1 parent 808255b commit 2ddf8ef
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 29 deletions.
92 changes: 64 additions & 28 deletions holo-vrrp/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@
// SPDX-License-Identifier: MIT
//

use std::io;
use std::net::{IpAddr, SocketAddrV4, Ipv4Addr};
use std::os::fd::FromRawFd;
use std::sync::Arc;

use holo_utils::socket::{AsyncFd, Socket};
use holo_utils::socket::AsyncFd;
use holo_utils::{capabilities, Sender, UnboundedReceiver};
use libc::ETH_P_ALL;
use socket2::{Domain, Protocol, Type};
use libc::{socket, AF_PACKET, ETH_P_ALL, ETH_P_ARP, SOCK_RAW};
use socket2::{Domain, Protocol, Type, Socket};
use tokio::sync::mpsc::error::SendError;

use crate::error::IoError;
use crate::packet::{VrrpPacket, ArpPacket};
use crate::packet::{VrrpPacket, ArpPacket, EthernetFrame};
use crate::tasks::messages::input::NetRxPacketMsg;
use crate::tasks::messages::output::NetTxPacketMsg;

Expand All @@ -37,20 +39,22 @@ pub(crate) fn socket_vrrp(ifname: &str) -> Result<Socket, std::io::Error> {
}
}

pub(crate) fn socket_arp(ifname: &str) -> Result<Socket, std::io::Error> {
pub fn socket_arp(ifname: &str) -> Result<Socket, std::io::Error> {
#[cfg(not(feature = "testing"))]
{
let eth_p_all = 0x0003;
let socket = capabilities::raise(|| {
Socket::new(Domain::IPV4, Type::RAW, Some(Protocol::from(eth_p_all)))
let sock = capabilities::raise(|| {
Socket::new(Domain::PACKET, Type::RAW, Some(Protocol::from(ETH_P_ARP)))
})?;
socket.set_broadcast(true)?;
socket.bind_device(Some(ifname.as_bytes()));
Ok(socket)
capabilities::raise(|| {
sock.bind_device(Some(ifname.as_bytes()));
sock.set_broadcast(true);
});
Ok(sock)

}
#[cfg(feature = "testing")]
{
Ok(Socket {})
Ok(Socket { })
}
}

Expand All @@ -75,25 +79,57 @@ pub(crate) async fn send_packet_vrrp(
}

#[cfg(not(feature = "testing"))]
pub(crate) async fn send_packet_arp(
socket: &AsyncFd<Socket>,
packet: ArpPacket
pub fn send_packet_arp(
sock: Socket,
ifname: &str,
eth_frame: EthernetFrame,
arp_packet: ArpPacket,
) -> Result<usize, IoError> {
use std::{ffi::{CString, NulError}, os::{self, fd::AsRawFd}};

use bytes::Buf;
use libc::{c_void, if_indextoname, if_nametoindex, sendto, sockaddr, sockaddr_ll};

use crate::packet::ARPframe;
let mut arpframe = ARPframe::new(eth_frame, arp_packet);

let c_ifname = match CString::new(ifname.clone()){
Ok(c_ifname) => c_ifname,
Err(err) => return Err(IoError::SocketError(std::io::Error::new(io::ErrorKind::NotFound, err))),
};
let ifindex = unsafe { libc::if_nametoindex(c_ifname.as_ptr()) };

let buf: &[u8]= &packet.encode();
let target = Ipv4Addr::from(packet.clone().target_proto_address);
let saddr = SocketAddrV4::new(target, 0);
let mut sa = sockaddr_ll {
sll_family: AF_PACKET as u16,
sll_protocol: 0x806_u16.to_be(),
sll_ifindex: ifindex as i32,
sll_hatype: 0,
sll_pkttype: 0,
sll_halen: 0,
sll_addr: [0; 8],
};

unsafe {
let ptr_sockaddr = std::mem::transmute::<*mut sockaddr_ll, *mut sockaddr>(&mut sa);

match sendto(
sock.as_raw_fd(),
&mut arpframe as *mut _ as *const c_void,
std::mem::size_of_val(&arpframe),
0,
ptr_sockaddr,
std::mem::size_of_val(&sa) as u32
) {
-1 => {
Err(IoError::SendError(io::Error::last_os_error()))
},
fd => {
Ok(fd as usize)
}
}

}

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"))]
Expand Down
74 changes: 73 additions & 1 deletion holo-vrrp/src/packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,54 @@ pub struct Ipv4Packet {
pub padding: Option<u8>,
}

#[repr(C)]
pub struct ARPframe {
// Ethernet Header
pub dst_mac: [u8; 6], // destination MAC address
pub src_mac: [u8; 6], // source MAC address
pub ethertype: u16, // ether type

// ARP
pub hardware_type: u16, // network link type (0x1=ethernet)
pub protocol_type: u16, // upper-layer protocol for resolution
pub hw_addr_len: u8, // length of hardware address (bytes)
pub proto_addr_len: u8, // upper-layer protocol address length
pub opcode: u16, // operation (0x1=request, 0x2=reply)
pub sender_hw_addr: [u8; 6], // sender hardware address
pub sender_proto_addr: [u8; 4], // internetwork address of sender
pub target_hw_addr: [u8; 6], // hardware address of target
pub target_proto_addr: [u8; 4], // internetwork address of target
}

impl ARPframe {
pub fn new(eth_pkt: EthernetFrame, arp_pkt: ArpPacket) -> Self {
Self {
dst_mac: eth_pkt.dst_mac,
src_mac: eth_pkt.src_mac,
ethertype: eth_pkt.ethertype.to_be(),


hardware_type: arp_pkt.hw_type.to_be(),
protocol_type: arp_pkt.proto_type.to_be(),
hw_addr_len: arp_pkt.hw_length,
proto_addr_len: arp_pkt.hw_length,
opcode: arp_pkt.operation.to_be(),

sender_hw_addr: arp_pkt.sender_hw_address,
sender_proto_addr: arp_pkt.sender_proto_address,
target_hw_addr: arp_pkt.target_hw_address,
target_proto_addr: arp_pkt.target_proto_address,
}
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
pub struct EthernetFrame {
pub dst_mac: [u8; 6],
pub src_mac: [u8; 6],
pub ethertype: u16
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -321,6 +369,30 @@ impl Ipv4Packet {
}
}

impl EthernetFrame {
pub fn encode(&self) -> BytesMut {
let mut buf = BytesMut::with_capacity(14);
self.dst_mac.iter().for_each(|i| buf.put_u8(*i));
self.src_mac.iter().for_each(|i| buf.put_u8(*i));
buf.put_u16(self.ethertype);
buf
}

pub fn decode(data: &[u8]) -> DecodeResult<Self> {
let mut buf = Bytes::copy_from_slice(data);
let mut dst_mac: [u8; 6] = [0u8; 6];
let mut src_mac: [u8; 6] = [0u8; 6];

for x in 0..6 { dst_mac[x] = buf.get_u8(); }
for x in 0..6 { src_mac[x] = buf.get_u8(); }

Ok(Self {
dst_mac,
src_mac,
ethertype: buf.get_u16(),
})
}
}

impl ArpPacket {
pub fn encode(&self) -> BytesMut {
Expand Down Expand Up @@ -372,8 +444,8 @@ impl ArpPacket {
target_hw_address,
target_proto_address,
})

}

}

pub mod checksum {
Expand Down

0 comments on commit 2ddf8ef

Please sign in to comment.