Skip to content

Add frame information to packet info popup #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions oryx-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,46 @@

use core::mem;

use network_types::{arp::ArpHdr, icmp::IcmpHdr, ip::IpHdr, tcp::TcpHdr, udp::UdpHdr};
use network_types::{arp::ArpHdr, eth::EthHdr, icmp::IcmpHdr, ip::IpHdr, tcp::TcpHdr, udp::UdpHdr};

pub mod protocols;

pub const MAX_FIREWALL_RULES: u32 = 32;
pub const MAX_RULES_PORT: usize = 32;

#[repr(C)]
#[derive(Clone)]
pub struct RawFrame {
pub header: EthHdr,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should define the header here with the fields we are interested in to be more explicit, what do you think ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh it would be easy enough to do this, I dont have a strong opinion either way. My thinking in using the already defined type was mostly for convenience since it is already defined and is returned from the TcContext so app layer dosnt need to do extra work to convert it (not a big deal to implement a From impl though). But also it includes additional information that could be interesting to render later, mainly in the eth type. But this assumes network_types expands the eth type enum to cover other interesting packet types like Wake on LAN, MPLS, or VLAN etc., but that would of course need changes in aya

pub payload: RawPacket,
}

impl RawFrame {
pub const LEN: usize = mem::size_of::<RawFrame>();
}

#[repr(C)]
pub enum RawPacket {
Ip(IpHdr, ProtoHdr),
Arp(ArpHdr),
}

impl Clone for RawPacket {
fn clone(&self) -> Self {
match self {
Self::Ip(ip_hdr, proto_hdr) => match ip_hdr {
IpHdr::V4(ipv4_hdr) => Self::Ip(IpHdr::V4(*ipv4_hdr), *proto_hdr),
IpHdr::V6(ipv6_hdr) => Self::Ip(IpHdr::V6(*ipv6_hdr), *proto_hdr),
},
Self::Arp(arp_hdr) => Self::Arp(*arp_hdr),
}
}
}

#[repr(C)]
#[derive(Copy, Clone)]
pub enum ProtoHdr {
Tcp(TcpHdr),
Udp(UdpHdr),
Icmp(IcmpHdr),
}

impl RawPacket {
pub const LEN: usize = mem::size_of::<RawPacket>();
}
81 changes: 51 additions & 30 deletions oryx-ebpf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use network_types::{
};
use oryx_common::{
protocols::{LinkProtocol, NetworkProtocol, Protocol, TransportProtocol},
ProtoHdr, RawPacket, MAX_FIREWALL_RULES, MAX_RULES_PORT,
ProtoHdr, RawFrame, RawPacket, MAX_FIREWALL_RULES, MAX_RULES_PORT,
};

#[map]
static DATA: RingBuf = RingBuf::with_byte_size(4096 * RawPacket::LEN as u32, 0);
static DATA: RingBuf = RingBuf::with_byte_size(4096 * RawFrame::LEN as u32, 0);

#[map]
static NETWORK_FILTERS: Array<u32> = Array::with_max_entries(8, 0);
Expand Down Expand Up @@ -56,9 +56,9 @@ pub fn oryx(ctx: TcContext) -> i32 {
}

#[inline]
fn submit(packet: RawPacket) {
if let Some(mut buf) = DATA.reserve::<RawPacket>(0) {
unsafe { (*buf.as_mut_ptr()) = packet };
fn submit(frame: RawFrame) {
if let Some(mut buf) = DATA.reserve::<RawFrame>(0) {
unsafe { (*buf.as_mut_ptr()) = frame };
buf.submit(0);
}
}
Expand Down Expand Up @@ -183,10 +183,13 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
return Ok(TC_ACT_PIPE);
}

submit(RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Tcp(unsafe { *tcphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Tcp(unsafe { *tcphdr }),
),
});
}
IpProto::Udp => {
let udphdr: *const UdpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv4Hdr::LEN)?;
Expand All @@ -207,20 +210,26 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
return Ok(TC_ACT_PIPE);
}

submit(RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Udp(unsafe { *udphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Udp(unsafe { *udphdr }),
),
});
}
IpProto::Icmp => {
if filter_packet(Protocol::Network(NetworkProtocol::Icmp)) {
return Ok(TC_ACT_PIPE);
}
let icmphdr: *const IcmpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv4Hdr::LEN)?;
submit(RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Icmp(unsafe { *icmphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V4(header),
ProtoHdr::Icmp(unsafe { *icmphdr }),
),
});
}
_ => {}
}
Expand Down Expand Up @@ -252,10 +261,13 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
{
return Ok(TC_ACT_PIPE);
}
submit(RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Tcp(unsafe { *tcphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Tcp(unsafe { *tcphdr }),
),
});
}
IpProto::Udp => {
let udphdr: *const UdpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv6Hdr::LEN)?;
Expand All @@ -275,20 +287,26 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
{
return Ok(TC_ACT_PIPE);
}
submit(RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Udp(unsafe { *udphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Udp(unsafe { *udphdr }),
),
});
}
IpProto::Icmp => {
if filter_packet(Protocol::Network(NetworkProtocol::Icmp)) {
return Ok(TC_ACT_PIPE);
}
let icmphdr: *const IcmpHdr = ptr_at(&ctx, EthHdr::LEN + Ipv6Hdr::LEN)?;
submit(RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Icmp(unsafe { *icmphdr }),
));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Ip(
IpHdr::V6(header),
ProtoHdr::Icmp(unsafe { *icmphdr }),
),
});
}
_ => {}
}
Expand All @@ -298,7 +316,10 @@ fn process(ctx: TcContext) -> Result<i32, ()> {
return Ok(TC_ACT_PIPE);
}
let header: ArpHdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;
submit(RawPacket::Arp(header));
submit(RawFrame {
header: ethhdr,
payload: RawPacket::Arp(header),
});
}
_ => {}
};
Expand Down
34 changes: 17 additions & 17 deletions oryx-tui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::ArgMatches;
use itertools::Itertools;
use oryx_common::{
protocols::{LinkProtocol, NetworkProtocol, TransportProtocol},
RawPacket,
RawFrame,
};
use ratatui::{
layout::{Constraint, Direction, Layout},
Expand All @@ -19,7 +19,7 @@ use std::{
use crate::{
filter::Filter,
help::Help,
packet::{direction::TrafficDirection, NetworkPacket},
packet::{direction::TrafficDirection, EthFrame},
};
use crate::{filter::IoChannels, notification::Notification};
use crate::{packet::AppPacket, section::Section};
Expand All @@ -39,7 +39,7 @@ pub enum ActivePopup {

#[derive(Debug)]
pub struct DataEventHandler {
pub sender: kanal::Sender<[u8; RawPacket::LEN]>,
pub sender: kanal::Sender<[u8; RawFrame::LEN]>,
pub handler: thread::JoinHandle<()>,
}

Expand All @@ -49,39 +49,39 @@ pub struct App {
pub help: Help,
pub filter: Filter,
pub start_sniffing: bool,
pub packets: Arc<RwLock<Vec<AppPacket>>>,
pub frames: Arc<RwLock<Vec<AppPacket>>>,
pub notifications: Vec<Notification>,
pub section: Section,
pub data_channel_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>,
pub data_channel_sender: kanal::Sender<([u8; RawFrame::LEN], TrafficDirection)>,
pub is_editing: bool,
pub active_popup: Option<ActivePopup>,
pub start_from_cli: bool,
}

impl App {
pub fn new(cli_args: &ArgMatches) -> Self {
let packets = Arc::new(RwLock::new(Vec::with_capacity(
RawPacket::LEN * 1024 * 1024,
)));
let frames = Arc::new(RwLock::new(Vec::with_capacity(RawFrame::LEN * 1024 * 1024)));

let (sender, receiver) = kanal::unbounded();

let firewall_channels = IoChannels::new();

thread::spawn({
let packets = packets.clone();
let frames = frames.clone();
move || loop {
if let Ok((raw_packet, direction)) = receiver.recv() {
let network_packet = NetworkPacket::from(raw_packet);
let mut packets = packets.write().unwrap();
if packets.len() == packets.capacity() {
packets.reserve(1024 * 1024);
if let Ok((raw_frame, direction)) = receiver.recv() {
let eth_frame = EthFrame::from(raw_frame);
let network_packet = eth_frame.payload;
let mut frames = frames.write().unwrap();
if frames.len() == frames.capacity() {
frames.reserve(1024 * 1024);
}
let app_packet = AppPacket {
eth_header: eth_frame.header,
packet: network_packet,
direction,
};
packets.push(app_packet);
frames.push(app_packet);
}
}
});
Expand Down Expand Up @@ -186,9 +186,9 @@ impl App {
direction,
),
start_sniffing: false,
packets: packets.clone(),
frames: frames.clone(),
notifications: Vec::new(),
section: Section::new(packets.clone(), firewall_channels.clone()),
section: Section::new(frames.clone(), firewall_channels.clone()),
data_channel_sender: sender,
is_editing: false,
active_popup: None,
Expand Down
8 changes: 4 additions & 4 deletions oryx-tui/src/ebpf/egress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use aya::{
EbpfLoader,
};
use log::error;
use oryx_common::{protocols::Protocol, RawPacket, MAX_RULES_PORT};
use oryx_common::{protocols::Protocol, RawFrame, MAX_RULES_PORT};

use crate::{
event::Event,
Expand All @@ -32,7 +32,7 @@ use super::{
pub fn load_egress(
iface: String,
notification_sender: kanal::Sender<Event>,
data_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>,
data_sender: kanal::Sender<([u8; RawFrame::LEN], TrafficDirection)>,
filter_channel_receiver: kanal::Receiver<FilterChannelSignal>,
firewall_egress_receiver: kanal::Receiver<FirewallSignal>,
terminate: Arc<AtomicBool>,
Expand Down Expand Up @@ -219,8 +219,8 @@ pub fn load_egress(
if terminate.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
let packet: [u8; RawPacket::LEN] = item.to_owned().try_into().unwrap();
data_sender.send((packet, TrafficDirection::Egress)).ok();
let frame: [u8; RawFrame::LEN] = item.to_owned().try_into().unwrap();
data_sender.send((frame, TrafficDirection::Egress)).ok();
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions oryx-tui/src/ebpf/ingress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use aya::{
EbpfLoader,
};
use log::error;
use oryx_common::{protocols::Protocol, RawPacket, MAX_RULES_PORT};
use oryx_common::{protocols::Protocol, RawFrame, MAX_RULES_PORT};

use crate::{
event::Event,
Expand All @@ -32,7 +32,7 @@ use super::{
pub fn load_ingress(
iface: String,
notification_sender: kanal::Sender<Event>,
data_sender: kanal::Sender<([u8; RawPacket::LEN], TrafficDirection)>,
data_sender: kanal::Sender<([u8; RawFrame::LEN], TrafficDirection)>,
filter_channel_receiver: kanal::Receiver<FilterChannelSignal>,
firewall_ingress_receiver: kanal::Receiver<FirewallSignal>,
terminate: Arc<AtomicBool>,
Expand Down Expand Up @@ -223,8 +223,8 @@ pub fn load_ingress(
if terminate.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
let packet: [u8; RawPacket::LEN] = item.to_owned().try_into().unwrap();
data_sender.send((packet, TrafficDirection::Ingress)).ok();
let frame: [u8; RawFrame::LEN] = item.to_owned().try_into().unwrap();
data_sender.send((frame, TrafficDirection::Ingress)).ok();
}
}
}
Expand Down
Loading