Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3067,6 +3067,7 @@ jobs:
env:
DISTCHECK_CONFIGURE_FLAGS: "--enable-unittests --enable-debug --enable-geoip --enable-profiling --enable-profiling-locks --enable-dpdk --enable-ebpf --enable-ebpf-build"
- run: python3 scripts/check-dist-rules.py
- run: python3 scripts/check-uint-keywords.py
- run: test -e doc/userguide/suricata.1
- run: test -e doc/userguide/userguide.pdf
- name: Building Rust documentation
Expand Down
6 changes: 6 additions & 0 deletions doc/userguide/rules/enip-keyword.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ This allows to match without needing to match on cip.service.

enip.cip_attribute uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.

enip.cip_attribute is also a :ref:`multi-integer <multi-integers>`.

Examples::

enip.cip_attribute:1;
Expand All @@ -84,6 +86,8 @@ It uses a 32-bit unsigned integer as value.

enip.cip_instance uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.

enip.cip_instance is also a :ref:`multi-integer <multi-integers>`.

Examples::

enip.cip_instance:1;
Expand All @@ -97,6 +101,8 @@ It uses a 32-bit unsigned integer as value.

enip.cip_class uses an :ref:`unsigned 32-bits integer <rules-integer-keywords>`.

enip.cip_class is also a :ref:`multi-integer <multi-integers>`.

This allows to match without needing to match on cip.service.

Examples::
Expand Down
59 changes: 50 additions & 9 deletions rust/src/dhcp/dhcp.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (C) 2018-2021 Open Information Security Foundation
/* Copyright (C) 2018-2026 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand All @@ -23,6 +23,7 @@ use suricata_sys::sys::{
use crate::applayer::{self, *};
use crate::core::{ALPROTO_UNKNOWN, IPPROTO_UDP};
use crate::dhcp::parser::*;
use crate::direction::Direction;
use crate::flow::Flow;
use std;
use std::ffi::CString;
Expand Down Expand Up @@ -89,11 +90,11 @@ pub struct DHCPTransaction {
}

impl DHCPTransaction {
pub fn new(id: u64, message: DHCPMessage) -> DHCPTransaction {
pub fn new(id: u64, message: DHCPMessage, direction: Direction) -> DHCPTransaction {
DHCPTransaction {
tx_id: id,
message,
tx_data: applayer::AppLayerTxData::new(),
tx_data: applayer::AppLayerTxData::for_direction(direction),
}
}
}
Expand Down Expand Up @@ -132,13 +133,13 @@ impl DHCPState {
Default::default()
}

pub fn parse(&mut self, input: &[u8]) -> bool {
pub fn parse(&mut self, input: &[u8], direction: Direction) -> bool {
match parse_dhcp(input) {
Ok((_, message)) => {
let malformed_options = message.malformed_options;
let truncated_options = message.truncated_options;
self.tx_id += 1;
let transaction = DHCPTransaction::new(self.tx_id, message);
let transaction = DHCPTransaction::new(self.tx_id, message, direction);
self.transactions.push(transaction);
if malformed_options {
self.set_event(DHCPEvent::MalformedOptions);
Expand Down Expand Up @@ -227,12 +228,23 @@ unsafe extern "C" fn dhcp_state_get_tx_count(state: *mut std::os::raw::c_void) -
return state.tx_id;
}

unsafe extern "C" fn dhcp_parse(
unsafe extern "C" fn dhcp_parse_request(
_flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
stream_slice: StreamSlice, _data: *mut std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, DHCPState);
if state.parse(stream_slice.as_slice()) {
if state.parse(stream_slice.as_slice(), Direction::ToServer) {
return AppLayerResult::ok();
}
return AppLayerResult::err();
}

unsafe extern "C" fn dhcp_parse_response(
_flow: *mut Flow, state: *mut std::os::raw::c_void, _pstate: *mut AppLayerParserState,
stream_slice: StreamSlice, _data: *mut std::os::raw::c_void,
) -> AppLayerResult {
let state = cast_pointer!(state, DHCPState);
if state.parse(stream_slice.as_slice(), Direction::ToClient) {
return AppLayerResult::ok();
}
return AppLayerResult::err();
Expand Down Expand Up @@ -275,8 +287,8 @@ pub unsafe extern "C" fn SCRegisterDhcpParser() {
state_new: dhcp_state_new,
state_free: dhcp_state_free,
tx_free: dhcp_state_tx_free,
parse_ts: dhcp_parse,
parse_tc: dhcp_parse,
parse_ts: dhcp_parse_request,
parse_tc: dhcp_parse_response,
get_tx_count: dhcp_state_get_tx_count,
get_tx: dhcp_state_get_tx,
tx_comp_st_ts: 1,
Expand Down Expand Up @@ -310,3 +322,32 @@ pub unsafe extern "C" fn SCRegisterDhcpParser() {
SCLogDebug!("Protocol detector and parser disabled for DHCP.");
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_tx_skip_inspect_direction() {
let pcap = include_bytes!("discover.pcap");
let payload = &pcap[24 + 16 + 42..];

// a to-server tx should be marked to skip the to-client inspection it
// will never be observed in, and a to-client tx the reverse
let (_rem, message) = parse_dhcp(payload).unwrap();
let ts_tx = DHCPTransaction::new(1, message, Direction::ToServer);
assert_eq!(
APP_LAYER_TX_SKIP_INSPECT_TC,
ts_tx.tx_data.0.flags & APP_LAYER_TX_SKIP_INSPECT_TC
);
assert_eq!(0, ts_tx.tx_data.0.flags & APP_LAYER_TX_SKIP_INSPECT_TS);

let (_rem, message) = parse_dhcp(payload).unwrap();
let tc_tx = DHCPTransaction::new(2, message, Direction::ToClient);
assert_eq!(
APP_LAYER_TX_SKIP_INSPECT_TS,
tc_tx.tx_data.0.flags & APP_LAYER_TX_SKIP_INSPECT_TS
);
assert_eq!(0, tc_tx.tx_data.0.flags & APP_LAYER_TX_SKIP_INSPECT_TC);
}
}
Loading
Loading