falco_plugin/plugin/tables/vtable/
mod.rs1use crate::plugin::error::as_result::{AsResult, WithLastError};
2use crate::plugin::error::last_error::LastError;
3use crate::plugin::exported_tables::entry::table_metadata::traits::TableMetadata;
4use crate::plugin::exported_tables::entry::traits::Entry;
5use crate::plugin::exported_tables::table::Table;
6use crate::plugin::exported_tables::wrappers::{fields_vtable, reader_vtable, writer_vtable};
7use crate::plugin::tables::data::Key;
8use crate::plugin::tables::table::raw::RawTable;
9use crate::plugin::tables::traits::{TableAccess, TableMetadata as ImportedTableMetadata};
10use falco_plugin_api::{
11 ss_plugin_init_input, ss_plugin_owner_t, ss_plugin_rc, ss_plugin_state_type,
12 ss_plugin_table_fields_vtable, ss_plugin_table_info, ss_plugin_table_input,
13 ss_plugin_table_reader_vtable, ss_plugin_table_t, ss_plugin_table_writer_vtable,
14};
15use std::borrow::Borrow;
16use std::ffi::CStr;
17use thiserror::Error;
18
19pub mod fields;
20pub mod reader;
21pub mod writer;
22
23use crate::tables::LazyTableReader;
24use fields::TableFields;
25use writer::LazyTableWriter;
26
27#[derive(Error, Debug)]
28pub enum TableError {
29 #[error("Missing entry {0} in table operations vtable")]
30 BadVtable(&'static str),
31}
32
33#[derive(Debug)]
34pub struct TablesInput<'t> {
39 owner: *mut ss_plugin_owner_t,
40 pub(in crate::plugin::tables) last_error: LastError,
41 pub(in crate::plugin::tables) list_tables:
42 unsafe extern "C-unwind" fn(
43 o: *mut ss_plugin_owner_t,
44 ntables: *mut u32,
45 ) -> *mut ss_plugin_table_info,
46 pub(in crate::plugin::tables) get_table: unsafe extern "C-unwind" fn(
47 o: *mut ss_plugin_owner_t,
48 name: *const ::std::os::raw::c_char,
49 key_type: ss_plugin_state_type,
50 )
51 -> *mut ss_plugin_table_t,
52 pub(in crate::plugin::tables) add_table: unsafe extern "C-unwind" fn(
53 o: *mut ss_plugin_owner_t,
54 in_: *const ss_plugin_table_input,
55 ) -> ss_plugin_rc,
56
57 pub(in crate::plugin::tables) reader_ext: LazyTableReader<'t>,
59
60 pub(in crate::plugin::tables) writer_ext: LazyTableWriter<'t>,
62
63 pub(in crate::plugin::tables) fields_ext: TableFields<'t>,
65}
66
67impl TablesInput<'_> {
68 pub(crate) fn try_from(value: &ss_plugin_init_input) -> Result<Option<Self>, TableError> {
69 if let Some(table_init_input) = unsafe { value.tables.as_ref() } {
70 let reader_ext = unsafe {
71 table_init_input
72 .reader_ext
73 .as_ref()
74 .ok_or(TableError::BadVtable("reader_ext"))?
75 };
76 let writer_ext = unsafe {
77 table_init_input
78 .writer_ext
79 .as_ref()
80 .ok_or(TableError::BadVtable("writer_ext"))?
81 };
82 let fields_ext = unsafe {
83 table_init_input
84 .fields_ext
85 .as_ref()
86 .ok_or(TableError::BadVtable("fields_ext"))?
87 };
88
89 let get_owner_last_error = value
90 .get_owner_last_error
91 .ok_or(TableError::BadVtable("get_owner_last_error"))?;
92 let last_error = unsafe { LastError::new(value.owner, get_owner_last_error) };
93
94 Ok(Some(TablesInput {
95 owner: value.owner,
96 last_error: last_error.clone(),
97 list_tables: table_init_input
98 .list_tables
99 .ok_or(TableError::BadVtable("list_tables"))?,
100 get_table: table_init_input
101 .get_table
102 .ok_or(TableError::BadVtable("get_table"))?,
103 add_table: table_init_input
104 .add_table
105 .ok_or(TableError::BadVtable("add_table"))?,
106 reader_ext: LazyTableReader::new(reader_ext, last_error.clone()),
107 writer_ext: LazyTableWriter::try_from(writer_ext, last_error)?,
108 fields_ext: TableFields::try_from(fields_ext)?,
109 }))
110 } else {
111 Ok(None)
112 }
113 }
114}
115
116impl TablesInput<'_> {
117 pub fn list_tables(&self) -> &[ss_plugin_table_info] {
123 let mut num_tables = 0u32;
124 let tables = unsafe { (self.list_tables)(self.owner, &mut num_tables as *mut _) };
125 if tables.is_null() {
126 &[]
127 } else {
128 unsafe { std::slice::from_raw_parts(tables, num_tables as usize) }
129 }
130 }
131
132 pub fn get_table<T, K>(&self, name: &CStr) -> Result<T, anyhow::Error>
137 where
138 T: TableAccess<Key = K>,
139 K: Key,
140 {
141 let table = unsafe {
142 (self.get_table)(
143 self.owner,
144 name.as_ptr().cast(),
145 K::TYPE_ID as ss_plugin_state_type,
146 )
147 };
148 if table.is_null() {
149 Err(anyhow::anyhow!("Could not get table {:?}", name)).with_last_error(&self.last_error)
150 } else {
151 let table = RawTable { table };
153 let metadata = T::Metadata::new(&table, self)?;
154 Ok(T::new(table, metadata, false))
155 }
156 }
157
158 pub fn add_table<K, E>(&self, table: Table<K, E>) -> Result<Box<Table<K, E>>, anyhow::Error>
164 where
165 K: Key + Ord,
166 K: Borrow<<K as Key>::Borrowed>,
167 <K as Key>::Borrowed: Ord + ToOwned<Owned = K>,
168 E: Entry,
169 E::Metadata: TableMetadata,
170 {
171 let mut reader_vtable_ext = reader_vtable::<K, E>();
172 let mut writer_vtable_ext = writer_vtable::<K, E>();
173 let mut fields_vtable_ext = fields_vtable::<K, E>();
174
175 let mut table = Box::new(table);
176 let table_ptr = table.as_mut() as *mut Table<K, E>;
177
178 let table_input = ss_plugin_table_input {
182 name: table.name().as_ptr(),
183 key_type: K::TYPE_ID as ss_plugin_state_type,
184 table: table_ptr.cast(),
185 reader: ss_plugin_table_reader_vtable {
186 get_table_name: reader_vtable_ext.get_table_name,
187 get_table_size: reader_vtable_ext.get_table_size,
188 get_table_entry: reader_vtable_ext.get_table_entry,
189 read_entry_field: reader_vtable_ext.read_entry_field,
190 },
191 writer: ss_plugin_table_writer_vtable {
192 clear_table: writer_vtable_ext.clear_table,
193 erase_table_entry: writer_vtable_ext.erase_table_entry,
194 create_table_entry: writer_vtable_ext.create_table_entry,
195 destroy_table_entry: writer_vtable_ext.destroy_table_entry,
196 add_table_entry: writer_vtable_ext.add_table_entry,
197 write_entry_field: writer_vtable_ext.write_entry_field,
198 },
199 fields: ss_plugin_table_fields_vtable {
200 list_table_fields: fields_vtable_ext.list_table_fields,
201 get_table_field: fields_vtable_ext.get_table_field,
202 add_table_field: fields_vtable_ext.add_table_field,
203 },
204 reader_ext: &mut reader_vtable_ext as *mut _,
205 writer_ext: &mut writer_vtable_ext as *mut _,
206 fields_ext: &mut fields_vtable_ext as *mut _,
207 };
208
209 unsafe { (self.add_table)(self.owner, &table_input as *const _) }
210 .as_result()
211 .with_last_error(&self.last_error)?;
212 Ok(table)
213 }
214}