Created
November 10, 2021 22:27
-
-
Save dave-tucker/67e3e252f4fc9b09c754d1f6721c318e to your computer and use it in GitHub Desktop.
SkSkb Echo Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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() } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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