smb: use lru for ssnguid2vec_map; rename

Reimplement the ssnguid2vec_map HashMap as a LruCache.

Since this is a DCERPC record cache, name it as such.

Default size is 128. Can be controlled by
`app-layer.protocols.smb.max-dcerpc-frag-cache-size`.

Ticket: #5672.
pull/12094/head
Victor Julien 9 months ago committed by Victor Julien
parent 0f23557ef7
commit ba7a4ece76

@ -455,7 +455,7 @@ pub fn smb_read_dcerpc_record(state: &mut SMBState,
// msg_id 0 as this data crosses cmd/reply pairs
let ehdr = SMBHashKeyHdrGuid::new(SMBCommonHdr::new(SMBHDR_TYPE_TRANS_FRAG,
hdr.ssn_id, hdr.tree_id, 0_u64), guid.to_vec());
let mut prevdata = state.ssnguid2vec_map.remove(&ehdr).unwrap_or_default();
let mut prevdata = state.dcerpc_rec_frag_cache.pop(&ehdr).unwrap_or_default();
SCLogDebug!("indata {} prevdata {}", indata.len(), prevdata.len());
prevdata.extend_from_slice(indata);
let data = prevdata;
@ -476,7 +476,7 @@ pub fn smb_read_dcerpc_record(state: &mut SMBState,
if ntstatus == SMB_NTSTATUS_BUFFER_OVERFLOW && data.len() < dcer.frag_len as usize {
SCLogDebug!("short record {} < {}: storing partial data in state",
data.len(), dcer.frag_len);
state.ssnguid2vec_map.insert(ehdr, data.to_vec());
state.dcerpc_rec_frag_cache.put(ehdr, data.to_vec());
return true; // TODO review
}

@ -69,12 +69,12 @@ impl SMBState {
#[cfg(feature = "debug")]
pub fn _debug_state_stats(&self) {
SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} ssnguid2vec_map {} file_ts_guid {} file_tc_guid {} transactions {}",
SCLogDebug!("ssn2vec_map {} guid2name_cache {} read_offset_cache {} ssn2tree_cache {} dcerpc_rec_frag_cache {} file_ts_guid {} file_tc_guid {} transactions {}",
self.ssn2vec_map.len(),
self.guid2name_cache.len(),
self.read_offset_cache.len(),
self.ssn2tree_cache.len(),
self.ssnguid2vec_map.len(),
self.dcerpc_rec_frag_cache.len(),
self.file_ts_guid.len(),
self.file_tc_guid.len(),
self.transactions.len());

@ -88,6 +88,8 @@ pub static mut SMB_CFG_MAX_GUID_CACHE_SIZE: usize = 1024;
pub static mut SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE: usize = 128;
/// For SMBState::ssn2tree_cache
pub static mut SMB_CFG_MAX_TREE_CACHE_SIZE: usize = 512;
/// For SMBState::dcerpc_rec_frag_cache
pub static mut SMB_CFG_MAX_FRAG_CACHE_SIZE: usize = 128;
static mut ALPROTO_SMB: AppProto = ALPROTO_UNKNOWN;
@ -712,9 +714,9 @@ pub struct SMBState<> {
/// Map session key to SMBTree
pub ssn2tree_cache: LruCache<SMBCommonHdr, SMBTree>,
// store partial data records that are transferred in multiple
// requests for DCERPC.
pub ssnguid2vec_map: HashMap<SMBHashKeyHdrGuid, Vec<u8>>,
/// store partial data records that are transferred in multiple
/// requests for DCERPC.
pub dcerpc_rec_frag_cache: LruCache<SMBHashKeyHdrGuid, Vec<u8>>,
skip_ts: u32,
skip_tc: u32,
@ -787,7 +789,7 @@ impl SMBState {
guid2name_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_GUID_CACHE_SIZE }).unwrap()),
read_offset_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_READ_OFFSET_CACHE_SIZE }).unwrap()),
ssn2tree_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_TREE_CACHE_SIZE }).unwrap()),
ssnguid2vec_map:HashMap::new(),
dcerpc_rec_frag_cache:LruCache::new(NonZeroUsize::new(unsafe { SMB_CFG_MAX_FRAG_CACHE_SIZE }).unwrap()),
skip_ts:0,
skip_tc:0,
file_ts_left:0,
@ -2483,6 +2485,18 @@ pub unsafe extern "C" fn rs_smb_register_parser() {
SCLogError!("Invalid max-tree-cache-size value");
}
}
let retval = conf_get("app-layer.protocols.smb.max-dcerpc-frag-cache-size");
if let Some(val) = retval {
if let Ok(v) = val.parse::<usize>() {
if v > 0 {
SMB_CFG_MAX_FRAG_CACHE_SIZE = v;
} else {
SCLogError!("Invalid max-dcerpc-frag-cache-size value");
}
} else {
SCLogError!("Invalid max-dcerpc-frag-cache-size value");
}
}
SCLogConfig!("read: max record size: {}, max queued chunks {}, max queued size {}",
SMB_CFG_MAX_READ_SIZE, SMB_CFG_MAX_READ_QUEUE_CNT, SMB_CFG_MAX_READ_QUEUE_SIZE);
SCLogConfig!("write: max record size: {}, max queued chunks {}, max queued size {}",

@ -910,7 +910,7 @@ pub fn smb1_trans_response_record(state: &mut SMBState, r: &SmbRecord)
if r.nt_status == SMB_NTSTATUS_BUFFER_OVERFLOW {
let key = SMBHashKeyHdrGuid::new(SMBCommonHdr::from1(r, SMBHDR_TYPE_TRANS_FRAG), fid);
SCLogDebug!("SMBv1/TRANS: queueing data for len {} key {:?}", rd.data.len(), key);
state.ssnguid2vec_map.insert(key, rd.data.to_vec());
state.dcerpc_rec_frag_cache.put(key, rd.data.to_vec());
} else if is_dcerpc {
SCLogDebug!("SMBv1 TRANS TO PIPE");
let hdr = SMBCommonHdr::from1(r, SMBHDR_TYPE_HEADER);

Loading…
Cancel
Save