Skip to content

Instantly share code, notes, and snippets.

@dave-tucker
Created November 10, 2021 22:27
Show Gist options
  • Save dave-tucker/67e3e252f4fc9b09c754d1f6721c318e to your computer and use it in GitHub Desktop.
Save dave-tucker/67e3e252f4fc9b09c754d1f6721c318e to your computer and use it in GitHub Desktop.
SkSkb Echo Example
#![no_std]
#![no_main]
use aya_bpf::{
bindings::sk_action,
macros::{map, stream_parser, stream_verdict},
maps::{SockMap},
programs::{SkSkbContext}};
#[map(name = "sockmap")]
static mut SOCKMAP: SockMap= SockMap::with_max_entries(1, 0);
#[stream_parser(name="my_parser")]
fn my_parser(ctx: SkSkbContext) -> u32 {
match { try_stream_parser(ctx) } {
Ok(ret) => ret,
Err(ret) => ret,
}
}
fn try_stream_parser(ctx: SkSkbContext) -> Result<u32, u32> {
Ok(ctx.len())
}
#[stream_verdict(name="my_verdict")]
fn my_verdict(ctx: SkSkbContext) -> u32 {
match unsafe { try_stream_verdict(ctx) }{
Ok(_) => sk_action::SK_PASS,
Err(_) => sk_action::SK_DROP,
}
}
unsafe fn try_stream_verdict(ctx: SkSkbContext) -> Result<u32, u32> {
match SOCKMAP.redirect_skb(&ctx, 0, 0) as u32 {
sk_action::SK_PASS=> Ok(sk_action::SK_PASS),
sk_action::SK_DROP => Err(sk_action::SK_DROP),
_=> Err(sk_action::SK_DROP),
}
}
#[panic_handler]b
fn panic(_info: &core::panic::PanicInfo) -> ! {
unsafe { core::hint::unreachable_unchecked() }
}
use aya::maps::{MapRefMut, SockMap};
use aya::programs::SkSkb;
use aya::Bpf;
use tokio::io::AsyncReadExt;
use std::convert::{TryFrom, TryInto};
use structopt::StructOpt;
use tokio::net::TcpListener;
#[derive(Debug, StructOpt)]
struct Opt {
#[structopt(short, long)]
path: String,
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let opt = Opt::from_args();
let mut bpf = Bpf::load_file(&opt.path)?;
let mut sock_map = SockMap::<MapRefMut>::try_from(bpf.map_mut("sockmap")?)?;
let parser: &mut SkSkb = bpf.program_mut("my_parser")?.try_into()?;
parser.load()?;
parser.attach(&sock_map)?;
let verdict: &mut SkSkb = bpf.program_mut("my_verdict")?.try_into()?;
verdict.load()?;
verdict.attach(&sock_map)?;
let listener = TcpListener::bind("127.0.0.1:65000").await?;
println!("Server Listening on {}", listener.local_addr().unwrap());
loop {
println!("waiting for connections... use nc localhost 65000");
let (mut socket, _) = listener.accept().await?;
println!("connected! adding socket to map");
sock_map.set(0, &socket, 0)?;
println!("ready to echo data");
tokio::spawn(async move {
let mut buf = [0; 0];
// Even though it awaits for something to read, it only
// ends after the connection is hung up. Because all data
// is echo-ed by BPF program, the user level socket does
// not receive anything.
socket.read(&mut buf[..]).await.unwrap();
println!("connection closed!");
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment