|
1 | | - |
2 | 1 | use aya_ebpf::programs::ProbeContext; |
| 2 | +use aya_ebpf::helpers::{ |
| 3 | + bpf_get_current_comm, |
| 4 | + bpf_get_current_pid_tgid, |
| 5 | + bpf_get_current_cgroup_id, |
| 6 | +}; |
| 7 | + |
| 8 | +use crate::bindings::{ sk_buff }; |
| 9 | +use crate::offsets::OFFSETS; |
| 10 | +use crate::data_structures::{ PACKET_REGISTRY, TcpPacketRegistry }; |
| 11 | +use crate::veth_tracer::{ read_linux_inner_struct, read_linux_inner_value }; |
| 12 | + |
| 13 | +// docs: |
| 14 | +// TODO: add function documentation |
3 | 15 |
|
| 16 | +// docs: |
| 17 | +// |
| 18 | +// how skb works? http://oldvger.kernel.org/~davem/skb_data.html |
| 19 | +// |
| 20 | +// ref: https://elixir.bootlin.com/linux/v6.17.7/source/net/ipv4/tcp_ipv4.c#L2195 |
| 21 | +// |
| 22 | + |
| 23 | +//in tcp_v4_recv skb->data |
4 | 24 | pub fn try_tcp_analyzer(ctx: ProbeContext) -> Result<u32, i64> { |
5 | | - todo!() |
| 25 | + let sk_buff_pointer: *const sk_buff = ctx.arg(0).ok_or(1i64)?; |
| 26 | + // first control: i'm, verifying that the pointer is not null |
| 27 | + if sk_buff_pointer.is_null() { |
| 28 | + return Err(1); |
| 29 | + } |
| 30 | + |
| 31 | + let skb_data_pointer = read_linux_inner_struct::<u8>( |
| 32 | + sk_buff_pointer as *const u8, |
| 33 | + OFFSETS::SKB_DATA_POINTER |
| 34 | + )?; |
| 35 | + let first_ipv4_byte = read_linux_inner_value::<u8>(skb_data_pointer as *const u8, 0)?; |
| 36 | + let ihl = (first_ipv4_byte & 0x0f) as usize; // 0x0F=00001111 &=AND bit a bit operator to extract the last 4 bit |
| 37 | + let ip_header_len = ihl * 4; //returns the header lenght in bytes |
| 38 | + |
| 39 | + let proto = read_linux_inner_struct::<u8>( |
| 40 | + skb_data_pointer, |
| 41 | + OFFSETS::IPV4_PROTOCOL_OFFSET |
| 42 | + )? as u8; |
| 43 | + |
| 44 | + if proto != 6 { |
| 45 | + return Ok(0); |
| 46 | + } else { |
| 47 | + // get the source ip,destination ip and connection id |
| 48 | + let src_ip = read_linux_inner_value::<u32>(skb_data_pointer, OFFSETS::SRC_BYTE_OFFSET)?; |
| 49 | + let dst_ip = read_linux_inner_value::<u32>(skb_data_pointer, OFFSETS::DST_BYTE_OFFSET)?; |
| 50 | + let src_port = u16::from_be( |
| 51 | + read_linux_inner_value( |
| 52 | + skb_data_pointer, |
| 53 | + ip_header_len + OFFSETS::SRC_PORT_OFFSET_FROM_IP_HEADER |
| 54 | + )? |
| 55 | + ); |
| 56 | + let dst_port = u16::from_be( |
| 57 | + read_linux_inner_value( |
| 58 | + skb_data_pointer, |
| 59 | + ip_header_len + OFFSETS::DST_PORT_OFFSET_FROM_IP_HEADER |
| 60 | + )? |
| 61 | + ); |
| 62 | + |
| 63 | + let command = bpf_get_current_comm()?; |
| 64 | + let pid = (bpf_get_current_pid_tgid() >> 32) as u32; |
| 65 | + let cgroup_id = unsafe { bpf_get_current_cgroup_id() }; |
| 66 | + |
| 67 | + let log = TcpPacketRegistry { |
| 68 | + proto, |
| 69 | + src_ip, |
| 70 | + dst_ip, |
| 71 | + src_port, |
| 72 | + dst_port, |
| 73 | + pid, |
| 74 | + command, |
| 75 | + cgroup_id, |
| 76 | + }; |
| 77 | + unsafe { |
| 78 | + PACKET_REGISTRY.output(&ctx, &log, 0); |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + Ok(0) |
6 | 83 | } |
0 commit comments