pub struct PluginRegistry { /* private fields */ }

Implementations§

Examples found in repository?
src/plugins/mod.rs (line 50)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    pub fn build_plugins(&self, config: &Config) -> Result<PluginRegistry, PluginBuilderError> {
        let mut registry = PluginRegistry::new();

        for b in &self.list {
            b.build(&mut registry, config)?;
        }

        Ok(registry)
    }

    /// Instantiate plugins if they match predicate
    pub fn build_filter_plugins<P>(
        &self,
        predicate: P,
        config: &Config,
    ) -> Result<PluginRegistry, PluginBuilderError>
    where
        P: Fn(&str) -> bool,
    {
        let mut registry = PluginRegistry::new();

        for b in &self.list {
            if predicate(b.name()) {
                b.build(&mut registry, config)?;
            }
        }

        Ok(registry)
    }

Return the count of different plugins

A plugin can be registered for several layers, but it will count as one.

Add a plugin to the registry, and return the identifier

Run function F on all known plugins (registered or not) matching P

Examples found in repository?
src/threaded_analyzer.rs (line 170)
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    fn init(&mut self) -> Result<(), Error> {
        self.registry.run_plugins(|_| true, |p| p.pre_process());

        Ok(())
    }

    fn handle_packet(&mut self, packet: &Packet, ctx: &ParseContext) -> Result<(), Error> {
        // NOTE: remove packet from lifetime management, it must be made 'static
        // to be sent to threads
        let packet: Packet<'static> = unsafe { ::std::mem::transmute(packet.clone()) };
        self.dispatch(packet, ctx)?;
        Ok(())
    }

    fn teardown(&mut self) {
        debug!("main: exit");
        self.wait_for_empty_jobs();
        for job in self.local_jobs.iter() {
            // XXX expire flows?
            job.send(Job::PrintDebug).expect("Error while sending job");
            job.send(Job::Exit).expect("Error while sending job");
        }
        while let Some(w) = self.workers.pop() {
            w.handler.join().expect("panic occurred in a thread");
        }
        self.local_jobs.clear();
        debug!("main: all workers ended");

        self.registry.run_plugins(|_| true, |p| p.post_process());
    }
More examples
Hide additional examples
src/analyzer.rs (lines 1159-1162)
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
pub(crate) fn gen_event_new_flow(flow: &Flow, registry: &PluginRegistry) {
    // let start = ::std::time::Instant::now();
    registry.run_plugins(
        |p| p.plugin_type() & PLUGIN_FLOW_NEW != 0,
        |p| p.flow_created(flow),
    );
    // let elapsed = start.elapsed();
    // debug!("Time to run flow_created: {}.{}", elapsed.as_secs(), elapsed.as_millis());
}

impl PcapAnalyzer for Analyzer {
    /// Initialize all plugins
    fn init(&mut self) -> Result<(), Error> {
        self.registry.run_plugins(|_| true, |p| p.pre_process());
        Ok(())
    }

    /// Dispatch function: given a packet, use link type to get the real data, and
    /// call the matching handling function (some pcap blocks encode ethernet, or IPv4 etc.)
    fn handle_packet(&mut self, packet: &Packet, ctx: &ParseContext) -> Result<(), Error> {
        if ctx.pcap_index < self.skip_index {
            return Ok(());
        }
        match packet.data {
            PacketData::L2(data) => self.handle_l2(packet, ctx, data),
            PacketData::L3(ethertype, data) => {
                handle_l3(packet, ctx, data, EtherType(ethertype), self)
            }
            PacketData::L4(_, _) => unimplemented!(), // XXX
            PacketData::Unsupported(raw) => {
                // fixups
                if packet.link_type == Linktype(12) {
                    // defined as DLT_RAW in libpcap/dlt.h
                    if let Some(PacketData::L3(ethertype, packet_data)) =
                        get_packetdata_raw(raw, packet.caplen as usize)
                    {
                        return handle_l3(packet, ctx, packet_data, EtherType(ethertype), self);
                    }
                }
                warn!(
                    "Unsupported data format (unknown linktype {}) idx={}",
                    packet.link_type, ctx.pcap_index
                );
                Ok(())
            }
        }
    }

    /// Finalize analysis and notify plugins
    fn teardown(&mut self) {
        {
            // expire all TCP connections in reassembly engine
            finalize_tcp_streams(self);
            // expire remaining flows
            let flows = &self.flows;
            trace!("{} flows remaining in table", flows.len());
            // let start = ::std::time::Instant::now();
            self.registry.run_plugins(
                |p| p.plugin_type() & PLUGIN_FLOW_DEL != 0,
                |p| {
                    flows.values().for_each(|flow| {
                        p.flow_destroyed(flow);
                    });
                },
            );
            // let elapsed = start.elapsed();
            // debug!("Time to run flow_destroyed {}.{}", elapsed.as_secs(), elapsed.as_millis());
            self.flows.clear();

            self.registry.run_plugins(|_| true, |p| p.post_process());

            if let Some(output_dir) = &self.output_dir {
                self.registry.run_plugins(
                    |_| true,
                    |p| {
                        let res = p.save_results(output_dir);
                        if let Err(e) = res {
                            warn!("error while saving results for {}: {}", p.name(), e);
                        }
                    },
                );
            }
        };
    }

Register a layer for analysis, for the identified plugin

layer_filter is a filter on the value relative to the layer: for L3, use for ex. ETHERNET_IPV4, for L4, TRANSPORT_TCP, etc. Special value 0 for layer_filter means all possible values.

Get plugins matching the given layer and layer_filter

Examples found in repository?
src/analyzer.rs (line 1060)
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
fn run_plugins_v2<'i, F>(
    packet: &Packet,
    ctx: &ParseContext,
    layer: u8,
    layer_filter: u16,
    cb: F,
    analyzer: &mut Analyzer,
) -> Result<(), Error>
where
    F: for<'p> Fn(&'p mut dyn Plugin) -> PluginResult<'i>,
{
    trace!(
        "running plugins for layer={} filter=0x{:04x}",
        layer,
        layer_filter
    );
    // clone the registry (which is an Arc)
    // so analyzer is not borrowed for the plugins loop
    let registry = analyzer.registry.clone();
    let empty_vec = vec![];
    // get plugins for this specific filter
    let l1 = registry
        .get_plugins_for_layer(layer, layer_filter)
        .unwrap_or(&empty_vec)
        .as_slice();
    // get catch-all plugins (filter == 0)
    let l2 = registry
        .get_plugins_for_layer(layer, 0)
        .unwrap_or(&empty_vec)
        .as_slice();
    for plugin in l1.iter().chain(l2) {
        let r = {
            // limit duration of lock to vallback
            let mut p = plugin.lock().expect("locking plugin failed (recursion ?)");
            cb(p.deref_mut())
        };
        match r {
            PluginResult::None => continue,
            PluginResult::Error(e) => {
                // XXX ignore error in plugins ? just log ?
                warn!("Plugin returned error {:?}", e);
                continue;
            }
            PluginResult::L2(e, payload) => {
                handle_l3(packet, ctx, payload, EtherType(e), analyzer)?
            }
            PluginResult::L3(l3, payload) => handle_l3_common(packet, ctx, payload, l3, analyzer)?,
            PluginResult::L4(t5, payload) => {
                let l3_info = L3Info::default(); // XXX
                handle_l4_common(
                    packet,
                    ctx,
                    &[],
                    &l3_info,
                    t5.src_port,
                    t5.dst_port,
                    Some(payload),
                    analyzer,
                )?;
            }
        }
    }
    Ok(())
}

Return an iterator on registered plugins

The same plugin instance can be present multiple times, if registered with different PluginInfo (for ex. layer filters).

Return an iterator on all known plugins

Known plugins are plugins present in the registry (registered or not for layers)

Trait Implementations§

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.