diff --git a/rust/src/applayer.rs b/rust/src/applayer.rs index 4b7869532624..884a6f66c865 100644 --- a/rust/src/applayer.rs +++ b/rust/src/applayer.rs @@ -472,12 +472,49 @@ pub type ApplyTxConfigFn = unsafe extern "C" fn (*mut c_void, *mut c_void, c_int pub type GetFrameIdByName = unsafe extern "C" fn(*const c_char) -> c_int; pub type GetFrameNameById = unsafe extern "C" fn(u8) -> *const c_char; +// Also defined in output-json.h +/// cbindgen:ignore +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[allow(non_camel_case_types)] +pub enum OutputJsonLogDirection { + LOG_DIR_PACKET = 0, + LOG_DIR_FLOW = 1, +} + +// Also defined in output.h +// canot use JsonBuilder as it is not #[repr(C)] +pub type EveJsonSimpleTxLogFunc = unsafe extern "C" fn(*const c_void, *mut c_void) -> bool; + +// Also defined in output.h +#[repr(C)] +#[allow(non_snake_case)] +pub struct EveJsonTxLoggerRegistrationData { + pub confname: *const c_char, + pub logname: *const c_char, + pub alproto: AppProto, + pub dir: u8, + pub LogTx: EveJsonSimpleTxLogFunc, +} + +// Defined in output.h +/// cbindgen:ignore +extern { + pub fn OutputPreRegisterLogger(reg_data: EveJsonTxLoggerRegistrationData) -> c_int; +} + +// Defined in detect-engine-register.h +/// cbindgen:ignore +extern { + pub fn SigTablePreRegister(cb: unsafe extern "C" fn ()); +} // Defined in app-layer-register.h /// cbindgen:ignore extern { pub fn AppLayerRegisterProtocolDetection(parser: *const RustParser, enable_default: c_int) -> AppProto; pub fn AppLayerRegisterParserAlias(parser_name: *const c_char, alias_name: *const c_char); + pub fn AppProtoNewProtoFromString(name: *const c_char) -> AppProto; } #[allow(non_snake_case)] diff --git a/rust/src/dns/log.rs b/rust/src/dns/log.rs index 6e131e3d5e71..7003e70c1949 100644 --- a/rust/src/dns/log.rs +++ b/rust/src/dns/log.rs @@ -820,7 +820,7 @@ pub extern "C" fn SCDnsLogJsonQuery( /// "dns" object. /// /// This logger implements V3 style DNS logging. -fn log_json(tx: &mut DNSTransaction, flags: u64, jb: &mut JsonBuilder) -> Result<(), JsonError> { +fn log_json(tx: &DNSTransaction, flags: u64, jb: &mut JsonBuilder) -> Result<(), JsonError> { jb.open_object("dns")?; jb.set_int("version", 3)?; @@ -921,7 +921,7 @@ fn log_json(tx: &mut DNSTransaction, flags: u64, jb: &mut JsonBuilder) -> Result /// FFI wrapper around the common V3 style DNS logger. #[no_mangle] -pub extern "C" fn SCDnsLogJson(tx: &mut DNSTransaction, flags: u64, jb: &mut JsonBuilder) -> bool { +pub extern "C" fn SCDnsLogJson(tx: &DNSTransaction, flags: u64, jb: &mut JsonBuilder) -> bool { log_json(tx, flags, jb).is_ok() } diff --git a/rust/src/krb/log.rs b/rust/src/krb/log.rs index 58c0d64b4893..1f57da24f2c1 100644 --- a/rust/src/krb/log.rs +++ b/rust/src/krb/log.rs @@ -20,7 +20,7 @@ use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::krb::krb5::{KRB5Transaction,test_weak_encryption}; -fn krb5_log_response(jsb: &mut JsonBuilder, tx: &mut KRB5Transaction) -> Result<(), JsonError> +fn krb5_log_response(jsb: &mut JsonBuilder, tx: &KRB5Transaction) -> Result<(), JsonError> { jsb.open_object("krb5")?; match tx.error_code { @@ -70,7 +70,7 @@ fn krb5_log_response(jsb: &mut JsonBuilder, tx: &mut KRB5Transaction) -> Result< } #[no_mangle] -pub extern "C" fn rs_krb5_log_json_response(tx: &mut KRB5Transaction, jsb: &mut JsonBuilder) -> bool +pub extern "C" fn rs_krb5_log_json_response(tx: &KRB5Transaction, jsb: &mut JsonBuilder) -> bool { krb5_log_response(jsb, tx).is_ok() } diff --git a/rust/src/mime/smtp_log.rs b/rust/src/mime/smtp_log.rs index de8ab6d2341c..5d0165fd1ce2 100644 --- a/rust/src/mime/smtp_log.rs +++ b/rust/src/mime/smtp_log.rs @@ -23,7 +23,7 @@ use digest::Update; use md5::Md5; use std::ffi::CStr; -fn log_subject_md5(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), JsonError> { +fn log_subject_md5(js: &mut JsonBuilder, ctx: &MimeStateSMTP) -> Result<(), JsonError> { for h in &ctx.headers[..ctx.main_headers_nb] { if mime::slice_equals_lowercase(&h.name, b"subject") { let hash = format!("{:x}", Md5::new().chain(&h.value).finalize()); @@ -36,12 +36,12 @@ fn log_subject_md5(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), #[no_mangle] pub unsafe extern "C" fn SCMimeSmtpLogSubjectMd5( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, ) -> bool { return log_subject_md5(js, ctx).is_ok(); } -fn log_body_md5(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), JsonError> { +fn log_body_md5(js: &mut JsonBuilder, ctx: &MimeStateSMTP) -> Result<(), JsonError> { if ctx.md5_state == MimeSmtpMd5State::MimeSmtpMd5Completed { let hash = format!("{:x}", ctx.md5_result); js.set_string("body_md5", &hash)?; @@ -51,13 +51,13 @@ fn log_body_md5(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), Jso #[no_mangle] pub unsafe extern "C" fn SCMimeSmtpLogBodyMd5( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, ) -> bool { return log_body_md5(js, ctx).is_ok(); } fn log_field_array( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, c: &str, e: &str, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, c: &str, e: &str, ) -> Result<(), JsonError> { let mark = js.get_mark(); let mut found = false; @@ -81,7 +81,7 @@ fn log_field_array( #[no_mangle] pub unsafe extern "C" fn SCMimeSmtpLogFieldArray( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, email: *const std::os::raw::c_char, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, email: *const std::os::raw::c_char, config: *const std::os::raw::c_char, ) -> bool { let e: &CStr = CStr::from_ptr(email); //unsafe @@ -101,7 +101,7 @@ enum FieldCommaState { } fn log_field_comma( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, c: &str, e: &str, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, c: &str, e: &str, ) -> Result<(), JsonError> { for h in &ctx.headers[..ctx.main_headers_nb] { if mime::slice_equals_lowercase(&h.name, e.as_bytes()) { @@ -158,7 +158,7 @@ fn log_field_comma( #[no_mangle] pub unsafe extern "C" fn SCMimeSmtpLogFieldComma( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, email: *const std::os::raw::c_char, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, email: *const std::os::raw::c_char, config: *const std::os::raw::c_char, ) -> bool { let e: &CStr = CStr::from_ptr(email); //unsafe @@ -172,7 +172,7 @@ pub unsafe extern "C" fn SCMimeSmtpLogFieldComma( } fn log_field_string( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, c: &str, e: &str, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, c: &str, e: &str, ) -> Result<(), JsonError> { for h in &ctx.headers[..ctx.main_headers_nb] { if mime::slice_equals_lowercase(&h.name, e.as_bytes()) { @@ -185,7 +185,7 @@ fn log_field_string( #[no_mangle] pub unsafe extern "C" fn SCMimeSmtpLogFieldString( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, email: *const std::os::raw::c_char, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, email: *const std::os::raw::c_char, config: *const std::os::raw::c_char, ) -> bool { let e: &CStr = CStr::from_ptr(email); //unsafe @@ -199,7 +199,7 @@ pub unsafe extern "C" fn SCMimeSmtpLogFieldString( } fn log_data_header( - js: &mut JsonBuilder, ctx: &mut MimeStateSMTP, hname: &str, + js: &mut JsonBuilder, ctx: &MimeStateSMTP, hname: &str, ) -> Result<(), JsonError> { for h in &ctx.headers[..ctx.main_headers_nb] { if mime::slice_equals_lowercase(&h.name, hname.as_bytes()) { @@ -210,7 +210,7 @@ fn log_data_header( return Ok(()); } -fn log_data(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), JsonError> { +fn log_data(js: &mut JsonBuilder, ctx: &MimeStateSMTP) -> Result<(), JsonError> { log_data_header(js, ctx, "from")?; log_field_comma(js, ctx, "to", "to")?; log_field_comma(js, ctx, "cc", "cc")?; @@ -236,6 +236,6 @@ fn log_data(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> Result<(), JsonErr } #[no_mangle] -pub unsafe extern "C" fn SCMimeSmtpLogData(js: &mut JsonBuilder, ctx: &mut MimeStateSMTP) -> bool { +pub unsafe extern "C" fn SCMimeSmtpLogData(js: &mut JsonBuilder, ctx: &MimeStateSMTP) -> bool { return log_data(js, ctx).is_ok(); } diff --git a/rust/src/modbus/log.rs b/rust/src/modbus/log.rs index 24e703c245f7..a77b92060455 100644 --- a/rust/src/modbus/log.rs +++ b/rust/src/modbus/log.rs @@ -21,7 +21,7 @@ use crate::jsonbuilder::{JsonBuilder, JsonError}; use sawp_modbus::{Data, Message, Read, Write}; #[no_mangle] -pub extern "C" fn rs_modbus_to_json(tx: &mut ModbusTransaction, js: &mut JsonBuilder) -> bool { +pub extern "C" fn rs_modbus_to_json(tx: &ModbusTransaction, js: &mut JsonBuilder) -> bool { log(tx, js).is_ok() } diff --git a/rust/src/nfs/log.rs b/rust/src/nfs/log.rs index f6fdc8f5828a..8e1d8c8325b1 100644 --- a/rust/src/nfs/log.rs +++ b/rust/src/nfs/log.rs @@ -23,7 +23,7 @@ use crc::crc32; #[no_mangle] pub extern "C" fn rs_nfs_tx_logging_is_filtered(state: &mut NFSState, - tx: &mut NFSTransaction) + tx: &NFSTransaction) -> u8 { // TODO probably best to make this configurable @@ -119,7 +119,7 @@ fn nfs_log_request(state: &NFSState, tx: &NFSTransaction, js: &mut JsonBuilder) } #[no_mangle] -pub extern "C" fn rs_nfs_log_json_request(state: &mut NFSState, tx: &mut NFSTransaction, +pub extern "C" fn rs_nfs_log_json_request(state: &mut NFSState, tx: &NFSTransaction, js: &mut JsonBuilder) -> bool { nfs_log_request(state, tx, js).is_ok() @@ -152,7 +152,7 @@ fn nfs_log_response(state: &NFSState, tx: &NFSTransaction, js: &mut JsonBuilder) } #[no_mangle] -pub extern "C" fn rs_nfs_log_json_response(state: &mut NFSState, tx: &mut NFSTransaction, +pub extern "C" fn rs_nfs_log_json_response(state: &mut NFSState, tx: &NFSTransaction, js: &mut JsonBuilder) -> bool { nfs_log_response(state, tx, js).is_ok() @@ -173,7 +173,7 @@ fn rpc_log_response(tx: &NFSTransaction, js: &mut JsonBuilder) } #[no_mangle] -pub extern "C" fn rs_rpc_log_json_response(tx: &mut NFSTransaction, +pub extern "C" fn rs_rpc_log_json_response(tx: &NFSTransaction, js: &mut JsonBuilder) -> bool { rpc_log_response(tx, js).is_ok() diff --git a/rust/src/rdp/log.rs b/rust/src/rdp/log.rs index e0a71a839b8f..d91febf9cf53 100644 --- a/rust/src/rdp/log.rs +++ b/rust/src/rdp/log.rs @@ -24,7 +24,7 @@ use crate::rdp::windows; use x509_parser::prelude::{X509Certificate, FromDer}; #[no_mangle] -pub extern "C" fn rs_rdp_to_json(tx: &mut RdpTransaction, js: &mut JsonBuilder) -> bool { +pub extern "C" fn rs_rdp_to_json(tx: &RdpTransaction, js: &mut JsonBuilder) -> bool { log(tx, js).is_ok() } diff --git a/rust/src/sip/log.rs b/rust/src/sip/log.rs index 058b7850cb69..49e30a00db95 100644 --- a/rust/src/sip/log.rs +++ b/rust/src/sip/log.rs @@ -57,6 +57,6 @@ fn log(tx: &SIPTransaction, js: &mut JsonBuilder) -> Result<(), JsonError> { } #[no_mangle] -pub extern "C" fn rs_sip_log_json(tx: &mut SIPTransaction, js: &mut JsonBuilder) -> bool { +pub extern "C" fn rs_sip_log_json(tx: &SIPTransaction, js: &mut JsonBuilder) -> bool { log(tx, js).is_ok() } diff --git a/rust/src/smb/log.rs b/rust/src/smb/log.rs index 01d3d9e13846..d6b68dd070f9 100644 --- a/rust/src/smb/log.rs +++ b/rust/src/smb/log.rs @@ -445,13 +445,13 @@ fn smb_common_header(jsb: &mut JsonBuilder, state: &SMBState, tx: &SMBTransactio } #[no_mangle] -pub extern "C" fn rs_smb_log_json_request(jsb: &mut JsonBuilder, state: &mut SMBState, tx: &mut SMBTransaction) -> bool +pub extern "C" fn rs_smb_log_json_request(jsb: &mut JsonBuilder, state: &mut SMBState, tx: &SMBTransaction) -> bool { smb_common_header(jsb, state, tx).is_ok() } #[no_mangle] -pub extern "C" fn rs_smb_log_json_response(jsb: &mut JsonBuilder, state: &mut SMBState, tx: &mut SMBTransaction) -> bool +pub extern "C" fn rs_smb_log_json_response(jsb: &mut JsonBuilder, state: &mut SMBState, tx: &SMBTransaction) -> bool { smb_common_header(jsb, state, tx).is_ok() } diff --git a/rust/src/snmp/log.rs b/rust/src/snmp/log.rs index 5707f30ccb4e..abdca633f97f 100644 --- a/rust/src/snmp/log.rs +++ b/rust/src/snmp/log.rs @@ -37,7 +37,7 @@ fn str_of_pdu_type(t:&PduType) -> Cow { } } -fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result<(), JsonError> +fn snmp_log_response(jsb: &mut JsonBuilder, tx: &SNMPTransaction) -> Result<(), JsonError> { jsb.open_object("snmp")?; jsb.set_uint("version", tx.version as u64)?; @@ -77,7 +77,9 @@ fn snmp_log_response(jsb: &mut JsonBuilder, tx: &mut SNMPTransaction) -> Result< } #[no_mangle] -pub extern "C" fn rs_snmp_log_json_response(tx: &mut SNMPTransaction, jsb: &mut JsonBuilder) -> bool +pub unsafe extern "C" fn rs_snmp_log_json_response(tx: *const std::os::raw::c_void, jsb: *mut std::os::raw::c_void) -> bool { + let tx = cast_pointer!(tx, SNMPTransaction); + let jsb = cast_pointer!(jsb, JsonBuilder); snmp_log_response(jsb, tx).is_ok() } diff --git a/rust/src/snmp/snmp.rs b/rust/src/snmp/snmp.rs index c0a121d13a45..f13a634d6bdc 100644 --- a/rust/src/snmp/snmp.rs +++ b/rust/src/snmp/snmp.rs @@ -20,6 +20,8 @@ use crate::snmp::snmp_parser::*; use crate::core::{self, *}; use crate::applayer::{self, *}; +use super::log::rs_snmp_log_json_response; +use super::detect::ScDetectSNMPRegister; use std; use std::ffi::CString; @@ -410,20 +412,28 @@ pub unsafe extern "C" fn rs_register_snmp_parser() { get_frame_name_by_id: None, }; let ip_proto_str = CString::new("udp").unwrap(); + ALPROTO_SNMP = AppProtoNewProtoFromString(PARSER_NAME.as_ptr() as *const std::os::raw::c_char); + let reg_data = EveJsonTxLoggerRegistrationData { + confname: b"eve-log.snmp\0".as_ptr() as *const std::os::raw::c_char, + logname: b"JsonSNMPLog\0".as_ptr() as *const std::os::raw::c_char, + alproto: ALPROTO_SNMP, + dir: OutputJsonLogDirection::LOG_DIR_PACKET as u8, + LogTx: rs_snmp_log_json_response, + }; + OutputPreRegisterLogger(reg_data); + SigTablePreRegister(ScDetectSNMPRegister); if AppLayerProtoDetectConfProtoDetectionEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { // port 161 - let alproto = AppLayerRegisterProtocolDetection(&parser, 1); - // store the allocated ID for the probe function - ALPROTO_SNMP = alproto; + _ = AppLayerRegisterProtocolDetection(&parser, 1); if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { - let _ = AppLayerRegisterParser(&parser, alproto); + let _ = AppLayerRegisterParser(&parser, ALPROTO_SNMP); } // port 162 let default_port_traps = CString::new("162").unwrap(); parser.default_port = default_port_traps.as_ptr(); let _ = AppLayerRegisterProtocolDetection(&parser, 1); if AppLayerParserConfParserEnabled(ip_proto_str.as_ptr(), parser.name) != 0 { - let _ = AppLayerRegisterParser(&parser, alproto); + let _ = AppLayerRegisterParser(&parser, ALPROTO_SNMP); } AppLayerParserRegisterLogger(IPPROTO_UDP, ALPROTO_SNMP); } else { diff --git a/rust/src/tftp/log.rs b/rust/src/tftp/log.rs index f6e63531a07e..d5e710e5ffc5 100644 --- a/rust/src/tftp/log.rs +++ b/rust/src/tftp/log.rs @@ -20,7 +20,7 @@ use crate::jsonbuilder::{JsonBuilder, JsonError}; use crate::tftp::tftp::TFTPTransaction; -fn tftp_log_request(tx: &mut TFTPTransaction, +fn tftp_log_request(tx: &TFTPTransaction, jb: &mut JsonBuilder) -> Result<(), JsonError> { @@ -37,7 +37,7 @@ fn tftp_log_request(tx: &mut TFTPTransaction, } #[no_mangle] -pub extern "C" fn rs_tftp_log_json_request(tx: &mut TFTPTransaction, +pub extern "C" fn rs_tftp_log_json_request(tx: &TFTPTransaction, jb: &mut JsonBuilder) -> bool { diff --git a/src/app-layer-detect-proto.c b/src/app-layer-detect-proto.c index af98c6cbe2fe..bf742ce1ea8b 100644 --- a/src/app-layer-detect-proto.c +++ b/src/app-layer-detect-proto.c @@ -161,12 +161,14 @@ typedef struct AppLayerProtoDetectCtx_ { * ipproto. It should be allocated to contain ALPROTO_MAX * protocols. */ const char **alproto_names; + size_t alproto_names_len; /* Protocol expectations, like ftp-data on tcp. * It should be allocated to contain ALPROTO_MAX * app-layer protocols. For each protocol, an iptype * is referenced (or 0 if there is no expectation). */ uint8_t *expectation_proto; + size_t expectation_proto_len; } AppLayerProtoDetectCtx; typedef struct AppLayerProtoDetectAliases_ { @@ -1729,11 +1731,13 @@ int AppLayerProtoDetectSetup(void) if (unlikely(alpd_ctx.alproto_names == NULL)) { FatalError("Unable to alloc alproto_names."); } + alpd_ctx.alproto_names_len = g_alproto_max; // to realloc when dynamic protos are added alpd_ctx.expectation_proto = SCCalloc(g_alproto_max, sizeof(uint8_t)); if (unlikely(alpd_ctx.expectation_proto == NULL)) { FatalError("Unable to alloc expectation_proto."); } + alpd_ctx.expectation_proto_len = g_alproto_max; AppLayerExpectationSetup(); SCReturnInt(0); @@ -1767,8 +1771,10 @@ int AppLayerProtoDetectDeSetup(void) SCFree(alpd_ctx.alproto_names); alpd_ctx.alproto_names = NULL; + alpd_ctx.alproto_names_len = 0; SCFree(alpd_ctx.expectation_proto); alpd_ctx.expectation_proto = NULL; + alpd_ctx.expectation_proto_len = 0; SpmDestroyGlobalThreadCtx(alpd_ctx.spm_global_thread_ctx); @@ -1783,7 +1789,17 @@ void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_n { SCEnter(); - // should have just been realloced when dynamic protos is added + if (alpd_ctx.alproto_names_len <= alproto && alproto < g_alproto_max) { + void *tmp = SCRealloc(alpd_ctx.alproto_names, sizeof(char *) * g_alproto_max); + if (unlikely(tmp == NULL)) { + FatalError("Unable to realloc alproto_names."); + } + alpd_ctx.alproto_names = tmp; + for (AppProto a = alpd_ctx.alproto_names_len; a < g_alproto_max; a++) { + alpd_ctx.alproto_names[a] = NULL; + } + alpd_ctx.alproto_names_len = g_alproto_max; + } if (alpd_ctx.alproto_names[alproto] == NULL) alpd_ctx.alproto_names[alproto] = alproto_name; @@ -2136,6 +2152,9 @@ void AppLayerProtoDetectSupportedAppProtocols(AppProto *alprotos) static void AppLayerProtoDetectPEGetIpprotos(AppProto alproto, uint8_t *ipprotos) { + if (alproto >= alpd_ctx.expectation_proto_len) { + return; + } if (alpd_ctx.expectation_proto[alproto] == IPPROTO_TCP) { ipprotos[IPPROTO_TCP / 8] |= 1 << (IPPROTO_TCP % 8); } diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 6285b67d256c..37e9384f9340 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -124,6 +124,7 @@ typedef struct AppLayerParserProtoCtx_ typedef struct AppLayerParserCtx_ { AppLayerParserProtoCtx (*ctxs)[FLOW_PROTO_MAX]; + size_t ctxs_len; } AppLayerParserCtx; struct AppLayerParserState_ { @@ -254,6 +255,7 @@ int AppLayerParserSetup(void) if (unlikely(alp_ctx.ctxs == NULL)) { FatalError("Unable to alloc alp_ctx.ctxs."); } + alp_ctx.ctxs_len = g_alproto_max; SCReturnInt(0); } @@ -426,6 +428,17 @@ void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, { SCEnter(); + if (alp_ctx.ctxs_len <= alproto && alproto < g_alproto_max) { + // Realloc now as AppLayerParserRegisterStateFuncs is called first + void *tmp = SCRealloc( + alp_ctx.ctxs, sizeof(AppLayerParserProtoCtx[FLOW_PROTO_MAX]) * g_alproto_max); + if (unlikely(tmp == NULL)) { + FatalError("Unable to realloc alp_ctx.ctxs."); + } + alp_ctx.ctxs = tmp; + alp_ctx.ctxs_len = g_alproto_max; + } + alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateAlloc = StateAlloc; alp_ctx.ctxs[alproto][FlowGetProtoMapping(ipproto)].StateFree = StateFree; @@ -1683,7 +1696,6 @@ static void ValidateParserProto(AppProto alproto, uint8_t ipproto) } #undef BOTH_SET #undef BOTH_SET_OR_BOTH_UNSET -#undef THREE_SET_OR_THREE_UNSET #undef THREE_SET static void ValidateParser(AppProto alproto) diff --git a/src/app-layer-protos.c b/src/app-layer-protos.c index 3f991f35d404..19db07cd8477 100644 --- a/src/app-layer-protos.c +++ b/src/app-layer-protos.c @@ -71,6 +71,12 @@ AppProto StringToAppProto(const char *proto_name) return ALPROTO_UNKNOWN; } +AppProto AppProtoNewProtoFromString(const char *proto_name) +{ + AppProtoRegisterProtoString(g_alproto_max, proto_name); + return g_alproto_max - 1; +} + void AppProtoRegisterProtoString(AppProto alproto, const char *proto_name) { if (alproto < ALPROTO_MAX_STATIC) { diff --git a/src/app-layer-protos.h b/src/app-layer-protos.h index 813e58f13d3b..d3a1932fd017 100644 --- a/src/app-layer-protos.h +++ b/src/app-layer-protos.h @@ -56,7 +56,6 @@ enum AppProtoEnum { ALPROTO_KRB5, ALPROTO_QUIC, ALPROTO_DHCP, - ALPROTO_SNMP, ALPROTO_SIP, ALPROTO_RFB, ALPROTO_MQTT, @@ -78,6 +77,7 @@ enum AppProtoEnum { /* keep last */ ALPROTO_MAX_STATIC, // After this ALPROTO_MAX_STATIC can come dynamic alproto ids + // For example, ALPROTO_SNMP is now dynamic }; // NOTE: if ALPROTO's get >= 256, update SignatureNonPrefilterStore @@ -175,6 +175,8 @@ const char *AppProtoToString(AppProto alproto); */ AppProto StringToAppProto(const char *proto_name); +AppProto AppProtoNewProtoFromString(const char *proto_name); + void AppProtoRegisterProtoString(AppProto alproto, const char *proto_name); #endif /* SURICATA_APP_LAYER_PROTOS_H */ diff --git a/src/app-layer.c b/src/app-layer.c index 14d93c84aa02..f0b4bc2fc1e0 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -1055,7 +1055,6 @@ static void AppLayerNamesSetup(void) AppProtoRegisterProtoString(ALPROTO_KRB5, "krb5"); AppProtoRegisterProtoString(ALPROTO_QUIC, "quic"); AppProtoRegisterProtoString(ALPROTO_DHCP, "dhcp"); - AppProtoRegisterProtoString(ALPROTO_SNMP, "snmp"); AppProtoRegisterProtoString(ALPROTO_SIP, "sip"); AppProtoRegisterProtoString(ALPROTO_RFB, "rfb"); AppProtoRegisterProtoString(ALPROTO_MQTT, "mqtt"); diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index b9faff49bae8..f0a5d7561ee5 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -730,7 +730,6 @@ void SigTableSetup(void) DetectVlanIdRegister(); DetectVlanLayersRegister(); - ScDetectSNMPRegister(); ScDetectDHCPRegister(); ScDetectWebsocketRegister(); ScDetectEnipRegister(); diff --git a/src/detect-parse.c b/src/detect-parse.c index 10e9903e80af..34a9158f5e4b 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -119,7 +119,9 @@ void DetectFileRegisterProto( al_protocols[i].direction = direction; al_protocols[i].to_client_progress = to_client_progress; al_protocols[i].to_server_progress = to_server_progress; - al_protocols[i + 1].alproto = ALPROTO_UNKNOWN; + if (i + 1 < ALPROTO_WITHFILES_MAX) { + al_protocols[i + 1].alproto = ALPROTO_UNKNOWN; + } } void DetectFileRegisterFileProtocols(DetectFileHandlerTableElmt *reg) diff --git a/src/output.c b/src/output.c index 6af423fb4744..21ff23814ad0 100644 --- a/src/output.c +++ b/src/output.c @@ -885,8 +885,6 @@ void OutputRegisterRootLoggers(void) ALPROTO_KRB5, (EveJsonSimpleTxLogFunc)rs_krb5_log_json_response, NULL); RegisterSimpleJsonApplayerLogger(ALPROTO_QUIC, rs_quic_to_json, NULL); // ALPROTO_DHCP TODO missing - RegisterSimpleJsonApplayerLogger( - ALPROTO_SNMP, (EveJsonSimpleTxLogFunc)rs_snmp_log_json_response, NULL); RegisterSimpleJsonApplayerLogger(ALPROTO_SIP, (EveJsonSimpleTxLogFunc)rs_sip_log_json, NULL); RegisterSimpleJsonApplayerLogger(ALPROTO_RFB, rs_rfb_logger_log, NULL); RegisterSimpleJsonApplayerLogger(ALPROTO_MQTT, JsonMQTTAddMetadata, NULL); @@ -975,6 +973,15 @@ int OutputPreRegisterLogger(EveJsonTxLoggerRegistrationData reg_data) return 0; } +static TxLogger JsonLoggerFromDir(uint8_t dir) +{ + if (dir == LOG_DIR_PACKET) { + return JsonGenericDirPacketLogger; + } + BUG_ON(dir != LOG_DIR_FLOW); + return JsonGenericDirFlowLogger; +} + /** * \brief Register all non-root logging modules. */ @@ -1075,12 +1082,7 @@ void OutputRegisterLoggers(void) SCLogDebug("quic json logger registered."); /* DHCP JSON logger. */ JsonDHCPLogRegister(); - /* SNMP JSON logger. */ - OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonSNMPLog", "eve-log.snmp", - OutputJsonLogInitSub, ALPROTO_SNMP, JsonGenericDirPacketLogger, JsonLogThreadInit, - JsonLogThreadDeinit); - SCLogDebug("SNMP JSON logger registered."); /* SIP JSON logger. */ OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", "JsonSIPLog", "eve-log.sip", OutputJsonLogInitSub, ALPROTO_SIP, JsonGenericDirPacketLogger, JsonLogThreadInit, @@ -1135,8 +1137,8 @@ void OutputRegisterLoggers(void) for (size_t i = 0; i < preregistered_loggers_nb; i++) { OutputRegisterTxSubModule(LOGGER_JSON_TX, "eve-log", preregistered_loggers[i].logname, preregistered_loggers[i].confname, OutputJsonLogInitSub, - preregistered_loggers[i].alproto, JsonGenericDirFlowLogger, JsonLogThreadInit, - JsonLogThreadDeinit); + preregistered_loggers[i].alproto, JsonLoggerFromDir(preregistered_loggers[i].dir), + JsonLogThreadInit, JsonLogThreadDeinit); SCLogDebug( "%s JSON logger registered.", AppProtoToString(preregistered_loggers[i].alproto)); RegisterSimpleJsonApplayerLogger( diff --git a/src/output.h b/src/output.h index 87a05adfbd79..7ffed7e20150 100644 --- a/src/output.h +++ b/src/output.h @@ -174,6 +174,7 @@ typedef struct EveJsonTxLoggerRegistrationData { const char *confname; const char *logname; AppProto alproto; + uint8_t dir; EveJsonSimpleTxLogFunc LogTx; } EveJsonTxLoggerRegistrationData; diff --git a/src/suricata-plugin.h b/src/suricata-plugin.h index 8bc2183d70fd..6958d16c4891 100644 --- a/src/suricata-plugin.h +++ b/src/suricata-plugin.h @@ -53,7 +53,7 @@ typedef struct SCCapturePlugin_ { int SCPluginRegisterCapture(SCCapturePlugin *); // Every change in the API used by plugins should change this number -#define SC_PLUGIN_API_VERSION 8 +#define SC_PLUGIN_API_VERSION 0x801 typedef struct SCAppLayerPlugin_ { // versioning to check suricata/plugin API compatibility @@ -63,6 +63,7 @@ typedef struct SCAppLayerPlugin_ { void (*KeywordsRegister)(void); char *logname; char *confname; + uint8_t dir; bool (*Logger)(void *tx, void *jb); } SCAppLayerPlugin; diff --git a/src/util-plugin.c b/src/util-plugin.c index eb2ce7647e66..dba255d1f0cb 100644 --- a/src/util-plugin.c +++ b/src/util-plugin.c @@ -159,8 +159,7 @@ int SCPluginRegisterAppLayer(SCAppLayerPlugin *plugin) if (plugin->version != SC_PLUGIN_API_VERSION) { return 1; } - AppProto alproto = g_alproto_max; - AppProtoRegisterProtoString(alproto, plugin->name); + AppProto alproto = AppProtoNewProtoFromString(plugin->name); if (plugin->Register) { if (AppLayerParserPreRegister(plugin->Register) != 0) { return 1; @@ -176,6 +175,7 @@ int SCPluginRegisterAppLayer(SCAppLayerPlugin *plugin) .confname = plugin->confname, .logname = plugin->logname, .alproto = alproto, + .dir = plugin->dir, .LogTx = (EveJsonSimpleTxLogFunc)plugin->Logger, }; if (OutputPreRegisterLogger(reg_data) != 0) {