|
|
|
|
@ -171,7 +171,7 @@ pub struct NFSTransaction {
|
|
|
|
|
pub is_file_closed: bool,
|
|
|
|
|
/// file transactions are unidirectional in the sense that they track
|
|
|
|
|
/// a single file on one direction
|
|
|
|
|
pub file_tx_direction: u8, // STREAM_TOCLIENT or STREAM_TOSERVER
|
|
|
|
|
pub file_tx_direction: Direction, // Direction::ToClient or Direction::ToServer
|
|
|
|
|
pub file_handle: Vec<u8>,
|
|
|
|
|
|
|
|
|
|
/// Procedure type specific data
|
|
|
|
|
@ -205,7 +205,7 @@ impl NFSTransaction {
|
|
|
|
|
nfs_version:0,
|
|
|
|
|
is_file_tx: false,
|
|
|
|
|
is_file_closed: false,
|
|
|
|
|
file_tx_direction: 0,
|
|
|
|
|
file_tx_direction: Direction::ToServer,
|
|
|
|
|
file_handle:Vec::new(),
|
|
|
|
|
type_data: None,
|
|
|
|
|
de_state: None,
|
|
|
|
|
@ -474,7 +474,7 @@ impl NFSState {
|
|
|
|
|
if self.ts > f.post_gap_ts {
|
|
|
|
|
tx.request_done = true;
|
|
|
|
|
tx.response_done = true;
|
|
|
|
|
let (files, flags) = self.files.get(tx.file_tx_direction.into());
|
|
|
|
|
let (files, flags) = self.files.get(tx.file_tx_direction);
|
|
|
|
|
f.file_tracker.trunc(files, flags);
|
|
|
|
|
} else {
|
|
|
|
|
post_gap_txs = true;
|
|
|
|
|
@ -490,9 +490,9 @@ impl NFSState {
|
|
|
|
|
* can handle gaps. For the file transactions we set the current
|
|
|
|
|
* (flow) time and prune them in 60 seconds if no update for them
|
|
|
|
|
* was received. */
|
|
|
|
|
fn post_gap_housekeeping(&mut self, dir: u8)
|
|
|
|
|
fn post_gap_housekeeping(&mut self, dir: Direction)
|
|
|
|
|
{
|
|
|
|
|
if self.ts_ssn_gap && dir == STREAM_TOSERVER {
|
|
|
|
|
if self.ts_ssn_gap && dir == Direction::ToServer {
|
|
|
|
|
for tx in &mut self.transactions {
|
|
|
|
|
if tx.id >= self.tx_id {
|
|
|
|
|
SCLogDebug!("post_gap_housekeeping: done");
|
|
|
|
|
@ -510,7 +510,7 @@ impl NFSState {
|
|
|
|
|
tx.request_done = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if self.tc_ssn_gap && dir == STREAM_TOCLIENT {
|
|
|
|
|
} else if self.tc_ssn_gap && dir == Direction::ToClient {
|
|
|
|
|
for tx in &mut self.transactions {
|
|
|
|
|
if tx.id >= self.tx_id {
|
|
|
|
|
SCLogDebug!("post_gap_housekeeping: done");
|
|
|
|
|
@ -576,7 +576,7 @@ impl NFSState {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn new_file_tx(&mut self, file_handle: &Vec<u8>, file_name: &Vec<u8>, direction: u8)
|
|
|
|
|
pub fn new_file_tx(&mut self, file_handle: &Vec<u8>, file_name: &Vec<u8>, direction: Direction)
|
|
|
|
|
-> (&mut NFSTransaction, &mut FileContainer, u16)
|
|
|
|
|
{
|
|
|
|
|
let mut tx = self.new_tx();
|
|
|
|
|
@ -594,11 +594,11 @@ impl NFSState {
|
|
|
|
|
tx.id, String::from_utf8_lossy(file_name));
|
|
|
|
|
self.transactions.push(tx);
|
|
|
|
|
let tx_ref = self.transactions.last_mut();
|
|
|
|
|
let (files, flags) = self.files.get(direction.into());
|
|
|
|
|
let (files, flags) = self.files.get(direction);
|
|
|
|
|
return (tx_ref.unwrap(), files, flags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_file_tx_by_handle(&mut self, file_handle: &Vec<u8>, direction: u8)
|
|
|
|
|
pub fn get_file_tx_by_handle(&mut self, file_handle: &Vec<u8>, direction: Direction)
|
|
|
|
|
-> Option<(&mut NFSTransaction, &mut FileContainer, u16)>
|
|
|
|
|
{
|
|
|
|
|
let fh = file_handle.to_vec();
|
|
|
|
|
@ -608,7 +608,7 @@ impl NFSState {
|
|
|
|
|
tx.file_handle == fh
|
|
|
|
|
{
|
|
|
|
|
SCLogDebug!("Found NFS file TX with ID {} XID {:04X}", tx.id, tx.xid);
|
|
|
|
|
let (files, flags) = self.files.get(direction.into());
|
|
|
|
|
let (files, flags) = self.files.get(direction);
|
|
|
|
|
return Some((tx, files, flags));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -635,7 +635,7 @@ impl NFSState {
|
|
|
|
|
Vec::new()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let found = match self.get_file_tx_by_handle(&file_handle, STREAM_TOSERVER) {
|
|
|
|
|
let found = match self.get_file_tx_by_handle(&file_handle, Direction::ToServer) {
|
|
|
|
|
Some((tx, files, flags)) => {
|
|
|
|
|
if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
|
|
|
|
|
filetracker_newchunk(&mut tdf.file_tracker, files, flags,
|
|
|
|
|
@ -656,7 +656,7 @@ impl NFSState {
|
|
|
|
|
None => { false },
|
|
|
|
|
};
|
|
|
|
|
if !found {
|
|
|
|
|
let (tx, files, flags) = self.new_file_tx(&file_handle, &file_name, STREAM_TOSERVER);
|
|
|
|
|
let (tx, files, flags) = self.new_file_tx(&file_handle, &file_name, Direction::ToServer);
|
|
|
|
|
if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
|
|
|
|
|
filetracker_newchunk(&mut tdf.file_tracker, files, flags,
|
|
|
|
|
&file_name, w.file_data, w.offset,
|
|
|
|
|
@ -739,8 +739,8 @@ impl NFSState {
|
|
|
|
|
|
|
|
|
|
// update in progress chunks for file transfers
|
|
|
|
|
// return how much data we consumed
|
|
|
|
|
fn filetracker_update(&mut self, direction: u8, data: &[u8], gap_size: u32) -> u32 {
|
|
|
|
|
let mut chunk_left = if direction == STREAM_TOSERVER {
|
|
|
|
|
fn filetracker_update(&mut self, direction: Direction, data: &[u8], gap_size: u32) -> u32 {
|
|
|
|
|
let mut chunk_left = if direction == Direction::ToServer {
|
|
|
|
|
self.ts_chunk_left
|
|
|
|
|
} else {
|
|
|
|
|
self.tc_chunk_left
|
|
|
|
|
@ -748,7 +748,7 @@ impl NFSState {
|
|
|
|
|
if chunk_left == 0 {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
let xid = if direction == STREAM_TOSERVER {
|
|
|
|
|
let xid = if direction == Direction::ToServer {
|
|
|
|
|
self.ts_chunk_xid
|
|
|
|
|
} else {
|
|
|
|
|
self.tc_chunk_xid
|
|
|
|
|
@ -760,7 +760,7 @@ impl NFSState {
|
|
|
|
|
if chunk_left <= data.len() as u32 {
|
|
|
|
|
chunk_left = 0;
|
|
|
|
|
|
|
|
|
|
if direction == STREAM_TOSERVER {
|
|
|
|
|
if direction == Direction::ToServer {
|
|
|
|
|
self.ts_chunk_xid = 0;
|
|
|
|
|
file_handle = self.ts_chunk_fh.to_vec();
|
|
|
|
|
self.ts_chunk_fh.clear();
|
|
|
|
|
@ -781,7 +781,7 @@ impl NFSState {
|
|
|
|
|
} else {
|
|
|
|
|
chunk_left -= data.len() as u32;
|
|
|
|
|
|
|
|
|
|
if direction == STREAM_TOSERVER {
|
|
|
|
|
if direction == Direction::ToServer {
|
|
|
|
|
file_handle = self.ts_chunk_fh.to_vec();
|
|
|
|
|
} else {
|
|
|
|
|
// see if we have a file handle to work on
|
|
|
|
|
@ -797,7 +797,7 @@ impl NFSState {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if direction == STREAM_TOSERVER {
|
|
|
|
|
if direction == Direction::ToServer {
|
|
|
|
|
self.ts_chunk_left = chunk_left;
|
|
|
|
|
} else {
|
|
|
|
|
self.tc_chunk_left = chunk_left;
|
|
|
|
|
@ -825,7 +825,7 @@ impl NFSState {
|
|
|
|
|
let cs = tdf.file_tracker.update(files, flags, data, gap_size);
|
|
|
|
|
/* see if we need to close the tx */
|
|
|
|
|
if tdf.file_tracker.is_done() {
|
|
|
|
|
if direction == STREAM_TOCLIENT {
|
|
|
|
|
if direction == Direction::ToClient {
|
|
|
|
|
tx.response_done = true;
|
|
|
|
|
tx.is_file_closed = true;
|
|
|
|
|
SCLogDebug!("TX {} response is done now that the file track is ready", tx.id);
|
|
|
|
|
@ -901,7 +901,7 @@ impl NFSState {
|
|
|
|
|
let is_partial = reply.data.len() < reply.count as usize;
|
|
|
|
|
SCLogDebug!("partial data? {}", is_partial);
|
|
|
|
|
|
|
|
|
|
let found = match self.get_file_tx_by_handle(&file_handle, STREAM_TOCLIENT) {
|
|
|
|
|
let found = match self.get_file_tx_by_handle(&file_handle, Direction::ToClient) {
|
|
|
|
|
Some((tx, files, flags)) => {
|
|
|
|
|
SCLogDebug!("updated TX {:?}", tx);
|
|
|
|
|
if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
|
|
|
|
|
@ -931,7 +931,7 @@ impl NFSState {
|
|
|
|
|
None => { false },
|
|
|
|
|
};
|
|
|
|
|
if !found {
|
|
|
|
|
let (tx, files, flags) = self.new_file_tx(&file_handle, &file_name, STREAM_TOCLIENT);
|
|
|
|
|
let (tx, files, flags) = self.new_file_tx(&file_handle, &file_name, Direction::ToClient);
|
|
|
|
|
if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
|
|
|
|
|
filetracker_newchunk(&mut tdf.file_tracker, files, flags,
|
|
|
|
|
&file_name, reply.data, chunk_offset,
|
|
|
|
|
@ -986,7 +986,7 @@ impl NFSState {
|
|
|
|
|
pub fn parse_tcp_data_ts_gap<'b>(&mut self, gap_size: u32) -> AppLayerResult {
|
|
|
|
|
SCLogDebug!("parse_tcp_data_ts_gap ({})", gap_size);
|
|
|
|
|
let gap = vec![0; gap_size as usize];
|
|
|
|
|
let consumed = self.filetracker_update(STREAM_TOSERVER, &gap, gap_size);
|
|
|
|
|
let consumed = self.filetracker_update(Direction::ToServer, &gap, gap_size);
|
|
|
|
|
if consumed > gap_size {
|
|
|
|
|
SCLogDebug!("consumed more than GAP size: {} > {}", consumed, gap_size);
|
|
|
|
|
return AppLayerResult::ok();
|
|
|
|
|
@ -1000,7 +1000,7 @@ impl NFSState {
|
|
|
|
|
pub fn parse_tcp_data_tc_gap<'b>(&mut self, gap_size: u32) -> AppLayerResult {
|
|
|
|
|
SCLogDebug!("parse_tcp_data_tc_gap ({})", gap_size);
|
|
|
|
|
let gap = vec![0; gap_size as usize];
|
|
|
|
|
let consumed = self.filetracker_update(STREAM_TOCLIENT, &gap, gap_size);
|
|
|
|
|
let consumed = self.filetracker_update(Direction::ToClient, &gap, gap_size);
|
|
|
|
|
if consumed > gap_size {
|
|
|
|
|
SCLogDebug!("consumed more than GAP size: {} > {}", consumed, gap_size);
|
|
|
|
|
return AppLayerResult::ok();
|
|
|
|
|
@ -1016,7 +1016,7 @@ impl NFSState {
|
|
|
|
|
let mut cur_i = i;
|
|
|
|
|
// take care of in progress file chunk transfers
|
|
|
|
|
// and skip buffer beyond it
|
|
|
|
|
let consumed = self.filetracker_update(STREAM_TOSERVER, cur_i, 0);
|
|
|
|
|
let consumed = self.filetracker_update(Direction::ToServer, cur_i, 0);
|
|
|
|
|
if consumed > 0 {
|
|
|
|
|
if consumed > cur_i.len() as u32 {
|
|
|
|
|
return AppLayerResult::err();
|
|
|
|
|
@ -1032,7 +1032,7 @@ impl NFSState {
|
|
|
|
|
let mut _cnt = 0;
|
|
|
|
|
while cur_i.len() > 0 {
|
|
|
|
|
_cnt += 1;
|
|
|
|
|
match nfs_probe(cur_i, STREAM_TOSERVER) {
|
|
|
|
|
match nfs_probe(cur_i, Direction::ToServer) {
|
|
|
|
|
1 => {
|
|
|
|
|
SCLogDebug!("expected data found");
|
|
|
|
|
self.ts_gap = false;
|
|
|
|
|
@ -1155,7 +1155,7 @@ impl NFSState {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.post_gap_housekeeping(STREAM_TOSERVER);
|
|
|
|
|
self.post_gap_housekeeping(Direction::ToServer);
|
|
|
|
|
if self.check_post_gap_file_txs && !self.post_gap_files_checked {
|
|
|
|
|
self.post_gap_housekeeping_for_files();
|
|
|
|
|
self.post_gap_files_checked = true;
|
|
|
|
|
@ -1169,7 +1169,7 @@ impl NFSState {
|
|
|
|
|
let mut cur_i = i;
|
|
|
|
|
// take care of in progress file chunk transfers
|
|
|
|
|
// and skip buffer beyond it
|
|
|
|
|
let consumed = self.filetracker_update(STREAM_TOCLIENT, cur_i, 0);
|
|
|
|
|
let consumed = self.filetracker_update(Direction::ToClient, cur_i, 0);
|
|
|
|
|
if consumed > 0 {
|
|
|
|
|
if consumed > cur_i.len() as u32 {
|
|
|
|
|
return AppLayerResult::err();
|
|
|
|
|
@ -1185,7 +1185,7 @@ impl NFSState {
|
|
|
|
|
let mut _cnt = 0;
|
|
|
|
|
while cur_i.len() > 0 {
|
|
|
|
|
_cnt += 1;
|
|
|
|
|
match nfs_probe(cur_i, STREAM_TOCLIENT) {
|
|
|
|
|
match nfs_probe(cur_i, Direction::ToClient) {
|
|
|
|
|
1 => {
|
|
|
|
|
SCLogDebug!("expected data found");
|
|
|
|
|
self.tc_gap = false;
|
|
|
|
|
@ -1306,7 +1306,7 @@ impl NFSState {
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
self.post_gap_housekeeping(STREAM_TOCLIENT);
|
|
|
|
|
self.post_gap_housekeeping(Direction::ToClient);
|
|
|
|
|
if self.check_post_gap_file_txs && !self.post_gap_files_checked {
|
|
|
|
|
self.post_gap_housekeeping_for_files();
|
|
|
|
|
self.post_gap_files_checked = true;
|
|
|
|
|
@ -1361,17 +1361,17 @@ impl NFSState {
|
|
|
|
|
AppLayerResult::ok()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn getfiles(&mut self, direction: u8) -> * mut FileContainer {
|
|
|
|
|
//SCLogDebug!("direction: {}", direction);
|
|
|
|
|
if direction == STREAM_TOCLIENT {
|
|
|
|
|
fn getfiles(&mut self, direction: Direction) -> * mut FileContainer {
|
|
|
|
|
//SCLogDebug!("direction: {:?}", direction);
|
|
|
|
|
if direction == Direction::ToClient {
|
|
|
|
|
&mut self.files.files_tc as *mut FileContainer
|
|
|
|
|
} else {
|
|
|
|
|
&mut self.files.files_ts as *mut FileContainer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fn setfileflags(&mut self, direction: u8, flags: u16) {
|
|
|
|
|
SCLogDebug!("direction: {}, flags: {}", direction, flags);
|
|
|
|
|
if direction == STREAM_TOCLIENT {
|
|
|
|
|
fn setfileflags(&mut self, direction: Direction, flags: u16) {
|
|
|
|
|
SCLogDebug!("direction: {:?}, flags: {}", direction, flags);
|
|
|
|
|
if direction == Direction::ToClient {
|
|
|
|
|
self.files.flags_tc = flags;
|
|
|
|
|
} else {
|
|
|
|
|
self.files.flags_ts = flags;
|
|
|
|
|
@ -1410,8 +1410,8 @@ pub unsafe extern "C" fn rs_nfs_parse_request(flow: *const Flow,
|
|
|
|
|
{
|
|
|
|
|
let state = cast_pointer!(state, NFSState);
|
|
|
|
|
let flow = cast_pointer!(flow, Flow);
|
|
|
|
|
let file_flags = FileFlowToFlags(flow, STREAM_TOSERVER);
|
|
|
|
|
rs_nfs_setfileflags(STREAM_TOSERVER, state, file_flags);
|
|
|
|
|
let file_flags = FileFlowToFlags(flow, Direction::ToServer.into());
|
|
|
|
|
rs_nfs_setfileflags(Direction::ToServer.into(), state, file_flags);
|
|
|
|
|
|
|
|
|
|
if input.is_null() == true && input_len > 0 {
|
|
|
|
|
return rs_nfs_parse_request_tcp_gap(state, input_len);
|
|
|
|
|
@ -1444,8 +1444,8 @@ pub unsafe extern "C" fn rs_nfs_parse_response(flow: *const Flow,
|
|
|
|
|
{
|
|
|
|
|
let state = cast_pointer!(state, NFSState);
|
|
|
|
|
let flow = cast_pointer!(flow, Flow);
|
|
|
|
|
let file_flags = FileFlowToFlags(flow, STREAM_TOCLIENT);
|
|
|
|
|
rs_nfs_setfileflags(STREAM_TOCLIENT, state, file_flags);
|
|
|
|
|
let file_flags = FileFlowToFlags(flow, Direction::ToClient.into());
|
|
|
|
|
rs_nfs_setfileflags(Direction::ToClient.into(), state, file_flags);
|
|
|
|
|
|
|
|
|
|
if input.is_null() == true && input_len > 0 {
|
|
|
|
|
return rs_nfs_parse_response_tcp_gap(state, input_len);
|
|
|
|
|
@ -1477,8 +1477,8 @@ pub unsafe extern "C" fn rs_nfs_parse_request_udp(f: *const Flow,
|
|
|
|
|
_flags: u8) -> AppLayerResult
|
|
|
|
|
{
|
|
|
|
|
let state = cast_pointer!(state, NFSState);
|
|
|
|
|
let file_flags = FileFlowToFlags(f, STREAM_TOSERVER);
|
|
|
|
|
rs_nfs_setfileflags(STREAM_TOSERVER, state, file_flags);
|
|
|
|
|
let file_flags = FileFlowToFlags(f, Direction::ToServer.into());
|
|
|
|
|
rs_nfs_setfileflags(Direction::ToServer.into(), state, file_flags);
|
|
|
|
|
|
|
|
|
|
let buf = std::slice::from_raw_parts(input, input_len as usize);
|
|
|
|
|
SCLogDebug!("parsing {} bytes of request data", input_len);
|
|
|
|
|
@ -1495,8 +1495,8 @@ pub unsafe extern "C" fn rs_nfs_parse_response_udp(f: *const Flow,
|
|
|
|
|
_flags: u8) -> AppLayerResult
|
|
|
|
|
{
|
|
|
|
|
let state = cast_pointer!(state, NFSState);
|
|
|
|
|
let file_flags = FileFlowToFlags(f, STREAM_TOCLIENT);
|
|
|
|
|
rs_nfs_setfileflags(STREAM_TOCLIENT, state, file_flags);
|
|
|
|
|
let file_flags = FileFlowToFlags(f, Direction::ToClient.into());
|
|
|
|
|
rs_nfs_setfileflags(Direction::ToClient.into(), state, file_flags);
|
|
|
|
|
SCLogDebug!("parsing {} bytes of response data", input_len);
|
|
|
|
|
let buf = std::slice::from_raw_parts(input, input_len as usize);
|
|
|
|
|
state.parse_udp_tc(buf)
|
|
|
|
|
@ -1565,10 +1565,10 @@ pub unsafe extern "C" fn rs_nfs_tx_get_alstate_progress(tx: *mut std::os::raw::c
|
|
|
|
|
-> std::os::raw::c_int
|
|
|
|
|
{
|
|
|
|
|
let tx = cast_pointer!(tx, NFSTransaction);
|
|
|
|
|
if direction == STREAM_TOSERVER && tx.request_done {
|
|
|
|
|
if direction == Direction::ToServer.into() && tx.request_done {
|
|
|
|
|
//SCLogNotice!("TOSERVER progress 1");
|
|
|
|
|
return 1;
|
|
|
|
|
} else if direction == STREAM_TOCLIENT && tx.response_done {
|
|
|
|
|
} else if direction == Direction::ToClient.into() && tx.response_done {
|
|
|
|
|
//SCLogNotice!("TOCLIENT progress 1");
|
|
|
|
|
return 1;
|
|
|
|
|
} else {
|
|
|
|
|
@ -1715,11 +1715,11 @@ fn nfs_probe_dir(i: &[u8], rdir: *mut u8) -> i8 {
|
|
|
|
|
match parse_rpc_packet_header(i) {
|
|
|
|
|
Ok((_, ref hdr)) => {
|
|
|
|
|
let dir = if hdr.msgtype == 0 {
|
|
|
|
|
STREAM_TOSERVER
|
|
|
|
|
Direction::ToServer
|
|
|
|
|
} else {
|
|
|
|
|
STREAM_TOCLIENT
|
|
|
|
|
Direction::ToClient
|
|
|
|
|
};
|
|
|
|
|
unsafe { *rdir = dir };
|
|
|
|
|
unsafe { *rdir = dir as u8 };
|
|
|
|
|
return 1;
|
|
|
|
|
},
|
|
|
|
|
Err(nom::Err::Incomplete(_)) => {
|
|
|
|
|
@ -1731,8 +1731,8 @@ fn nfs_probe_dir(i: &[u8], rdir: *mut u8) -> i8 {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn nfs_probe(i: &[u8], direction: u8) -> i32 {
|
|
|
|
|
if direction == STREAM_TOCLIENT {
|
|
|
|
|
pub fn nfs_probe(i: &[u8], direction: Direction) -> i32 {
|
|
|
|
|
if direction == Direction::ToClient {
|
|
|
|
|
match parse_rpc_reply(i) {
|
|
|
|
|
Ok((_, ref rpc)) => {
|
|
|
|
|
if rpc.hdr.frag_len >= 24 && rpc.hdr.frag_len <= 35000 && rpc.hdr.msgtype == 1 && rpc.reply_state == 0 && rpc.accept_state == 0 {
|
|
|
|
|
@ -1787,8 +1787,8 @@ pub fn nfs_probe(i: &[u8], direction: u8) -> i32 {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn nfs_probe_udp(i: &[u8], direction: u8) -> i32 {
|
|
|
|
|
if direction == STREAM_TOCLIENT {
|
|
|
|
|
pub fn nfs_probe_udp(i: &[u8], direction: Direction) -> i32 {
|
|
|
|
|
if direction == Direction::ToClient {
|
|
|
|
|
match parse_rpc_udp_reply(i) {
|
|
|
|
|
Ok((_, ref rpc)) => {
|
|
|
|
|
if i.len() >= 32 && rpc.hdr.msgtype == 1 && rpc.reply_state == 0 && rpc.accept_state == 0 {
|
|
|
|
|
@ -1833,15 +1833,15 @@ pub unsafe extern "C" fn rs_nfs_probe_ms(
|
|
|
|
|
let mut adirection : u8 = 0;
|
|
|
|
|
match nfs_probe_dir(slice, &mut adirection) {
|
|
|
|
|
1 => {
|
|
|
|
|
if adirection == STREAM_TOSERVER {
|
|
|
|
|
SCLogDebug!("nfs_probe_dir said STREAM_TOSERVER");
|
|
|
|
|
if adirection == Direction::ToServer.into() {
|
|
|
|
|
SCLogDebug!("nfs_probe_dir said Direction::ToServer");
|
|
|
|
|
} else {
|
|
|
|
|
SCLogDebug!("nfs_probe_dir said STREAM_TOCLIENT");
|
|
|
|
|
SCLogDebug!("nfs_probe_dir said Direction::ToClient");
|
|
|
|
|
}
|
|
|
|
|
match nfs_probe(slice, adirection) {
|
|
|
|
|
match nfs_probe(slice, adirection.into()) {
|
|
|
|
|
1 => {
|
|
|
|
|
SCLogDebug!("nfs_probe success: dir {:02x} adir {:02x}", direction, adirection);
|
|
|
|
|
if (direction & (STREAM_TOSERVER|STREAM_TOCLIENT)) != adirection {
|
|
|
|
|
if (direction & DIR_BOTH) != adirection {
|
|
|
|
|
*rdir = adirection;
|
|
|
|
|
}
|
|
|
|
|
ALPROTO_NFS
|
|
|
|
|
@ -1869,7 +1869,7 @@ pub unsafe extern "C" fn rs_nfs_probe(_f: *const Flow,
|
|
|
|
|
{
|
|
|
|
|
let slice: &[u8] = build_slice!(input, len as usize);
|
|
|
|
|
SCLogDebug!("rs_nfs_probe: running probe");
|
|
|
|
|
match nfs_probe(slice, direction) {
|
|
|
|
|
match nfs_probe(slice, direction.into()) {
|
|
|
|
|
1 => { ALPROTO_NFS },
|
|
|
|
|
-1 => { ALPROTO_FAILED },
|
|
|
|
|
_ => { ALPROTO_UNKNOWN },
|
|
|
|
|
@ -1886,7 +1886,7 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_ts(_f: *const Flow,
|
|
|
|
|
-> AppProto
|
|
|
|
|
{
|
|
|
|
|
let slice: &[u8] = build_slice!(input, len as usize);
|
|
|
|
|
match nfs_probe_udp(slice, STREAM_TOSERVER) {
|
|
|
|
|
match nfs_probe_udp(slice, Direction::ToServer) {
|
|
|
|
|
1 => { ALPROTO_NFS },
|
|
|
|
|
-1 => { ALPROTO_FAILED },
|
|
|
|
|
_ => { ALPROTO_UNKNOWN },
|
|
|
|
|
@ -1903,7 +1903,7 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_tc(_f: *const Flow,
|
|
|
|
|
-> AppProto
|
|
|
|
|
{
|
|
|
|
|
let slice: &[u8] = build_slice!(input, len as usize);
|
|
|
|
|
match nfs_probe_udp(slice, STREAM_TOCLIENT) {
|
|
|
|
|
match nfs_probe_udp(slice, Direction::ToClient) {
|
|
|
|
|
1 => { ALPROTO_NFS },
|
|
|
|
|
-1 => { ALPROTO_FAILED },
|
|
|
|
|
_ => { ALPROTO_UNKNOWN },
|
|
|
|
|
@ -1914,14 +1914,14 @@ pub unsafe extern "C" fn rs_nfs_probe_udp_tc(_f: *const Flow,
|
|
|
|
|
pub unsafe extern "C" fn rs_nfs_getfiles(ptr: *mut std::ffi::c_void, direction: u8) -> * mut FileContainer {
|
|
|
|
|
if ptr.is_null() { panic!("NULL ptr"); };
|
|
|
|
|
let parser = cast_pointer!(ptr, NFSState);
|
|
|
|
|
parser.getfiles(direction)
|
|
|
|
|
parser.getfiles(direction.into())
|
|
|
|
|
}
|
|
|
|
|
#[no_mangle]
|
|
|
|
|
pub unsafe extern "C" fn rs_nfs_setfileflags(direction: u8, ptr: *mut NFSState, flags: u16) {
|
|
|
|
|
if ptr.is_null() { panic!("NULL ptr"); };
|
|
|
|
|
let parser = &mut *ptr;
|
|
|
|
|
SCLogDebug!("direction {} flags {}", direction, flags);
|
|
|
|
|
parser.setfileflags(direction, flags)
|
|
|
|
|
parser.setfileflags(direction.into(), flags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parser name as a C style string.
|
|
|
|
|
@ -1984,13 +1984,13 @@ pub unsafe extern "C" fn rs_nfs_register_parser() {
|
|
|
|
|
/* register 'midstream' probing parsers if midstream is enabled. */
|
|
|
|
|
AppLayerProtoDetectPPRegister(IPPROTO_TCP as u8,
|
|
|
|
|
default_port.as_ptr(), ALPROTO_NFS, 0,
|
|
|
|
|
NFS_MIN_FRAME_LEN, STREAM_TOSERVER,
|
|
|
|
|
NFS_MIN_FRAME_LEN, Direction::ToServer.into(),
|
|
|
|
|
rs_nfs_probe_ms, rs_nfs_probe_ms);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
AppLayerProtoDetectPPRegister(IPPROTO_TCP as u8,
|
|
|
|
|
default_port.as_ptr(), ALPROTO_NFS, 0,
|
|
|
|
|
NFS_MIN_FRAME_LEN, STREAM_TOSERVER,
|
|
|
|
|
NFS_MIN_FRAME_LEN, Direction::ToServer.into(),
|
|
|
|
|
rs_nfs_probe, rs_nfs_probe);
|
|
|
|
|
}
|
|
|
|
|
if AppLayerParserConfParserEnabled(
|
|
|
|
|
@ -2060,7 +2060,7 @@ pub unsafe extern "C" fn rs_nfs_udp_register_parser() {
|
|
|
|
|
default_port);
|
|
|
|
|
AppLayerProtoDetectPPRegister(IPPROTO_UDP as u8,
|
|
|
|
|
default_port.as_ptr(), ALPROTO_NFS, 0,
|
|
|
|
|
NFS_MIN_FRAME_LEN, STREAM_TOSERVER,
|
|
|
|
|
NFS_MIN_FRAME_LEN, Direction::ToServer.into(),
|
|
|
|
|
rs_nfs_probe_udp_ts, rs_nfs_probe_udp_tc);
|
|
|
|
|
}
|
|
|
|
|
if AppLayerParserConfParserEnabled(
|
|
|
|
|
|