123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044 |
- use proc_macro2::TokenStream;
- use quote::quote;
- use syn::{
- parse::{Parse, ParseStream},
- punctuated::{Pair, Punctuated},
- token::Eq,
- Error, Ident, ItemFn, ItemStatic, LitStr, Result, Token,
- };
- pub struct NameValue {
- name: Ident,
- _eq: Eq,
- value: LitStr,
- }
- pub struct Args {
- args: Vec<NameValue>,
- }
- impl Parse for Args {
- fn parse(input: ParseStream) -> Result<Args> {
- let args = Punctuated::<NameValue, Token![,]>::parse_terminated_with(input, |input| {
- Ok(NameValue {
- name: input.parse()?,
- _eq: input.parse()?,
- value: input.parse()?,
- })
- })?
- .into_pairs()
- .map(|pair| match pair {
- Pair::Punctuated(name_val, _) => name_val,
- Pair::End(name_val) => name_val,
- })
- .collect();
- Ok(Args { args })
- }
- }
- pub struct SockAddrArgs {
- pub(crate) attach_type: Ident,
- pub(crate) args: Args,
- }
- impl Parse for SockAddrArgs {
- fn parse(input: ParseStream) -> Result<SockAddrArgs> {
- let attach_type: Ident = input.parse()?;
- match attach_type.to_string().as_str() {
- "connect4" | "connect6" | "bind4" | "bind6" | "getpeername4" | "getpeername6"
- | "getsockname4" | "getsockname6" | "sendmsg4" | "sendmsg6" | "recvmsg4"
- | "recvmsg6" => (),
- _ => return Err(input.error("invalid attach type")),
- }
- let args = if input.parse::<Token![,]>().is_ok() {
- Args::parse(input)?
- } else {
- Args { args: vec![] }
- };
- Ok(SockAddrArgs { attach_type, args })
- }
- }
- pub struct SockoptArgs {
- pub(crate) attach_type: Ident,
- pub(crate) args: Args,
- }
- impl Parse for SockoptArgs {
- fn parse(input: ParseStream) -> Result<SockoptArgs> {
- let attach_type: Ident = input.parse()?;
- match attach_type.to_string().as_str() {
- "getsockopt" | "setsockopt" => (),
- _ => return Err(input.error("invalid attach type")),
- }
- let args = if input.parse::<Token![,]>().is_ok() {
- Args::parse(input)?
- } else {
- Args { args: vec![] }
- };
- Ok(SockoptArgs { attach_type, args })
- }
- }
- pub struct Map {
- item: ItemStatic,
- name: String,
- }
- impl Map {
- pub fn from_syn(mut args: Args, item: ItemStatic) -> Result<Map> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.ident.to_string());
- Ok(Map { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = "maps";
- let name = &self.name;
- let item = &self.item;
- Ok(quote! {
- #[link_section = #section_name]
- #[export_name = #name]
- #item
- })
- }
- }
- pub struct Probe {
- kind: ProbeKind,
- item: ItemFn,
- name: String,
- }
- impl Probe {
- pub fn from_syn(kind: ProbeKind, mut args: Args, item: ItemFn) -> Result<Probe> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(Probe { kind, item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("{}/{}", self.kind, self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
- let _ = #fn_name(::aya_bpf::programs::ProbeContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct SockOps {
- item: ItemFn,
- name: Option<String>,
- }
- impl SockOps {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SockOps> {
- let name = name_arg(&mut args)?;
- Ok(SockOps { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- format!("sockops/{name}").into()
- } else {
- "sockops".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_ops) -> u32 {
- return #fn_name(::aya_bpf::programs::SockOpsContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct SkMsg {
- item: ItemFn,
- name: String,
- }
- impl SkMsg {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SkMsg> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(SkMsg { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("sk_msg/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::sk_msg_md) -> u32 {
- return #fn_name(::aya_bpf::programs::SkMsgContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct Xdp {
- item: ItemFn,
- name: Option<String>,
- frags: bool,
- }
- impl Xdp {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<Xdp> {
- let name = pop_arg(&mut args, "name");
- let mut frags = false;
- if let Some(s) = pop_arg(&mut args, "frags") {
- if let Ok(m) = s.parse() {
- frags = m
- } else {
- return Err(Error::new_spanned(
- s,
- "invalid value. should be 'true' or 'false'",
- ));
- }
- }
- err_on_unknown_args(&args)?;
- Ok(Xdp { item, name, frags })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_prefix = if self.frags { "xdp.frags" } else { "xdp" };
- let section_name = if let Some(name) = &self.name {
- format!("{section_prefix}/{name}")
- } else {
- section_prefix.to_string()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 {
- return #fn_name(::aya_bpf::programs::XdpContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct SchedClassifier {
- item: ItemFn,
- name: Option<String>,
- }
- impl SchedClassifier {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SchedClassifier> {
- let name = name_arg(&mut args)?;
- Ok(SchedClassifier { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- format!("classifier/{name}").into()
- } else {
- "classifier".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
- return #fn_name(::aya_bpf::programs::TcContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupSysctl {
- item: ItemFn,
- name: Option<String>,
- }
- impl CgroupSysctl {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<CgroupSysctl> {
- let name = name_arg(&mut args)?;
- Ok(CgroupSysctl { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = if let Some(name) = &self.name {
- format!("cgroup/sysctl/{name}")
- } else {
- ("cgroup/sysctl").to_owned()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sysctl) -> i32 {
- return #fn_name(::aya_bpf::programs::SysctlContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupSockopt {
- item: ItemFn,
- attach_type: String,
- name: Option<String>,
- }
- impl CgroupSockopt {
- pub fn from_syn(mut args: Args, item: ItemFn, attach_type: String) -> Result<CgroupSockopt> {
- let name = pop_arg(&mut args, "name");
- err_on_unknown_args(&args)?;
- Ok(CgroupSockopt {
- item,
- attach_type,
- name,
- })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = if let Some(name) = &self.name {
- format!("cgroup/{}/{}", self.attach_type, name)
- } else {
- format!("cgroup/{}", self.attach_type)
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sockopt) -> i32 {
- return #fn_name(::aya_bpf::programs::SockoptContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupSkb {
- item: ItemFn,
- expected_attach_type: Option<String>,
- name: Option<String>,
- }
- impl CgroupSkb {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<CgroupSkb> {
- let name = pop_arg(&mut args, "name");
- let expected_attach_type = pop_arg(&mut args, "attach");
- err_on_unknown_args(&args)?;
- Ok(CgroupSkb {
- item,
- expected_attach_type,
- name,
- })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = if let Some(attach) = &self.expected_attach_type {
- if let Some(name) = &self.name {
- format!("cgroup_skb/{attach}/{name}")
- } else {
- format!("cgroup_skb/{attach}")
- }
- } else if let Some(name) = &self.name {
- format!("cgroup/skb/{name}")
- } else {
- ("cgroup/skb").to_owned()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i32 {
- return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupSockAddr {
- item: ItemFn,
- attach_type: String,
- name: Option<String>,
- }
- impl CgroupSockAddr {
- pub fn from_syn(mut args: Args, item: ItemFn, attach_type: String) -> Result<CgroupSockAddr> {
- let name = pop_arg(&mut args, "name");
- err_on_unknown_args(&args)?;
- Ok(CgroupSockAddr {
- item,
- attach_type,
- name,
- })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = if let Some(name) = &self.name {
- format!("cgroup/{}/{}", self.attach_type, name)
- } else {
- format!("cgroup/{}", self.attach_type)
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock_addr) -> i32 {
- return #fn_name(::aya_bpf::programs::SockAddrContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupSock {
- item: ItemFn,
- attach_type: Option<String>,
- name: Option<String>,
- }
- impl CgroupSock {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<CgroupSock> {
- let name = pop_arg(&mut args, "name");
- let attach_type = pop_arg(&mut args, "attach");
- err_on_unknown_args(&args)?;
- Ok(CgroupSock {
- item,
- attach_type,
- name,
- })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- if let Some(attach_type) = &self.attach_type {
- format!("cgroup/{attach_type}/{name}").into()
- } else {
- format!("cgroup/sock/{name}").into()
- }
- } else if let Some(attach_type) = &self.attach_type {
- format!("cgroup/{attach_type}").into()
- } else {
- "cgroup/sock".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sock) -> i32 {
- return #fn_name(::aya_bpf::programs::SockContext::new(ctx));
- #item
- }
- })
- }
- }
- fn pop_arg(args: &mut Args, name: &str) -> Option<String> {
- match args.args.iter().position(|arg| arg.name == name) {
- Some(index) => Some(args.args.remove(index).value.value()),
- None => None,
- }
- }
- fn err_on_unknown_args(args: &Args) -> Result<()> {
- if let Some(arg) = args.args.get(0) {
- return Err(Error::new_spanned(&arg.name, "invalid argument"));
- }
- Ok(())
- }
- fn name_arg(args: &mut Args) -> Result<Option<String>> {
- let name = pop_arg(args, "name");
- err_on_unknown_args(args)?;
- Ok(name)
- }
- #[allow(clippy::enum_variant_names)]
- #[derive(Debug, Copy, Clone)]
- pub enum ProbeKind {
- KProbe,
- KRetProbe,
- UProbe,
- URetProbe,
- }
- impl std::fmt::Display for ProbeKind {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use ProbeKind::*;
- match self {
- KProbe => write!(f, "kprobe"),
- KRetProbe => write!(f, "kretprobe"),
- UProbe => write!(f, "uprobe"),
- URetProbe => write!(f, "uretprobe"),
- }
- }
- }
- pub struct TracePoint {
- item: ItemFn,
- name: String,
- }
- impl TracePoint {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<TracePoint> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(TracePoint { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("tp/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
- let _ = #fn_name(::aya_bpf::programs::TracePointContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct PerfEvent {
- item: ItemFn,
- name: String,
- }
- impl PerfEvent {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<PerfEvent> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(PerfEvent { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("perf_event/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
- let _ = #fn_name(::aya_bpf::programs::PerfEventContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct RawTracePoint {
- item: ItemFn,
- name: String,
- }
- impl RawTracePoint {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<RawTracePoint> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(RawTracePoint { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("raw_tp/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
- let _ = #fn_name(::aya_bpf::programs::RawTracePointContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct Lsm {
- item: ItemFn,
- name: Option<String>,
- sleepable: bool,
- }
- impl Lsm {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<Lsm> {
- let name = pop_arg(&mut args, "name");
- let mut sleepable = false;
- if let Some(s) = pop_arg(&mut args, "sleepable") {
- if let Ok(m) = s.parse() {
- sleepable = m
- } else {
- return Err(Error::new_spanned(
- s,
- "invalid value. should be 'true' or 'false'",
- ));
- }
- }
- err_on_unknown_args(&args)?;
- Ok(Lsm {
- item,
- name,
- sleepable,
- })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" };
- let section_name = if let Some(name) = &self.name {
- format!("{section_prefix}/{name}")
- } else {
- section_prefix.to_string()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- // LSM probes need to return an integer corresponding to the correct
- // policy decision. Therefore we do not simply default to a return value
- // of 0 as in other program types.
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
- return #fn_name(::aya_bpf::programs::LsmContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct BtfTracePoint {
- item: ItemFn,
- name: String,
- }
- impl BtfTracePoint {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<BtfTracePoint> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(BtfTracePoint { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("tp_btf/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
- let _ = #fn_name(::aya_bpf::programs::BtfTracePointContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- #[allow(clippy::enum_variant_names)]
- #[derive(Debug, Copy, Clone)]
- pub enum SkSkbKind {
- StreamVerdict,
- StreamParser,
- }
- impl std::fmt::Display for SkSkbKind {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- use SkSkbKind::*;
- match self {
- StreamVerdict => write!(f, "stream_verdict"),
- StreamParser => write!(f, "stream_parser"),
- }
- }
- }
- pub struct SkSkb {
- kind: SkSkbKind,
- item: ItemFn,
- name: Option<String>,
- }
- impl SkSkb {
- pub fn from_syn(kind: SkSkbKind, mut args: Args, item: ItemFn) -> Result<SkSkb> {
- let name = pop_arg(&mut args, "name");
- err_on_unknown_args(&args)?;
- Ok(SkSkb { item, kind, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let kind = &self.kind;
- let section_name = if let Some(name) = &self.name {
- format!("sk_skb/{kind}/{name}")
- } else {
- format!("sk_skb/{kind}")
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> u32 {
- return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct SocketFilter {
- item: ItemFn,
- name: Option<String>,
- }
- impl SocketFilter {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SocketFilter> {
- let name = name_arg(&mut args)?;
- err_on_unknown_args(&args)?;
- Ok(SocketFilter { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- format!("socket/{name}").into()
- } else {
- "socket".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::__sk_buff) -> i64 {
- return #fn_name(::aya_bpf::programs::SkBuffContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct FEntry {
- item: ItemFn,
- name: String,
- }
- impl FEntry {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<FEntry> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(FEntry { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("fentry/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
- let _ = #fn_name(::aya_bpf::programs::FEntryContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct FExit {
- item: ItemFn,
- name: String,
- }
- impl FExit {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<FExit> {
- let name = name_arg(&mut args)?.unwrap_or_else(|| item.sig.ident.to_string());
- Ok(FExit { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name = format!("fexit/{}", self.name);
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
- let _ = #fn_name(::aya_bpf::programs::FExitContext::new(ctx));
- return 0;
- #item
- }
- })
- }
- }
- pub struct SkLookup {
- item: ItemFn,
- name: Option<String>,
- }
- impl SkLookup {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<SkLookup> {
- let name = name_arg(&mut args)?;
- Ok(SkLookup { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- format!("sk_lookup/{name}").into()
- } else {
- "sk_lookup".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_sk_lookup) -> u32 {
- return #fn_name(::aya_bpf::programs::SkLookupContext::new(ctx));
- #item
- }
- })
- }
- }
- pub struct CgroupDevice {
- item: ItemFn,
- name: Option<String>,
- }
- impl CgroupDevice {
- pub fn from_syn(mut args: Args, item: ItemFn) -> Result<Self> {
- let name = name_arg(&mut args)?;
- Ok(CgroupDevice { item, name })
- }
- pub fn expand(&self) -> Result<TokenStream> {
- let section_name: std::borrow::Cow<'_, _> = if let Some(name) = &self.name {
- format!("cgroup/dev/{name}").into()
- } else {
- "cgroup/dev".into()
- };
- let fn_vis = &self.item.vis;
- let fn_name = &self.item.sig.ident;
- let item = &self.item;
- Ok(quote! {
- #[no_mangle]
- #[link_section = #section_name]
- #fn_vis fn #fn_name(ctx: *mut ::aya_bpf::bindings::bpf_cgroup_dev_ctx) -> i32 {
- return #fn_name(::aya_bpf::programs::DeviceContext::new(ctx));
- #item
- }
- })
- }
- }
- #[cfg(test)]
- mod tests {
- use syn::parse_quote;
- use super::*;
- #[test]
- fn cgroup_skb_with_attach_and_name() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(name = "foo", attach = "ingress"),
- parse_quote!(
- fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream
- .to_string()
- .contains("[link_section = \"cgroup_skb/ingress/foo\"]"));
- }
- #[test]
- fn cgroup_skb_with_name() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(name = "foo"),
- parse_quote!(
- fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream
- .to_string()
- .contains("[link_section = \"cgroup/skb/foo\"]"));
- }
- #[test]
- fn cgroup_skb_no_name() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(),
- parse_quote!(
- fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream
- .to_string()
- .contains("[link_section = \"cgroup/skb\"]"));
- }
- #[test]
- fn cgroup_skb_with_attach_no_name() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(attach = "egress"),
- parse_quote!(
- fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream
- .to_string()
- .contains("[link_section = \"cgroup_skb/egress\"]"));
- }
- #[test]
- fn cgroup_device_no_name() {
- let prog = CgroupDevice::from_syn(
- parse_quote!(),
- parse_quote!(
- fn foo(ctx: DeviceContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream
- .to_string()
- .contains("[link_section = \"cgroup/dev\"]"));
- }
- #[test]
- fn priv_function() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(attach = "egress"),
- parse_quote!(
- fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream.to_string().contains("] fn foo ("));
- }
- #[test]
- fn pub_function() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(attach = "egress"),
- parse_quote!(
- pub fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream.to_string().contains("] pub fn foo ("));
- }
- #[test]
- fn pub_crate_function() {
- let prog = CgroupSkb::from_syn(
- parse_quote!(attach = "egress"),
- parse_quote!(
- pub(crate) fn foo(ctx: SkBuffContext) -> i32 {
- 0
- }
- ),
- )
- .unwrap();
- let stream = prog.expand().unwrap();
- assert!(stream.to_string().contains("] pub (crate) fn foo ("));
- }
- }
|