diff --git a/rust/src/nfs/mod.rs b/rust/src/nfs/mod.rs index 5638b0c8cb..b9922eee5d 100644 --- a/rust/src/nfs/mod.rs +++ b/rust/src/nfs/mod.rs @@ -21,8 +21,9 @@ pub mod nfs_records; pub mod nfs2_records; pub mod nfs3_records; pub mod nfs4_records; -pub mod nfs4; pub mod nfs; +pub mod nfs3; +pub mod nfs4; pub mod log; //#[cfg(feature = "lua")] diff --git a/rust/src/nfs/nfs.rs b/rust/src/nfs/nfs.rs index 19c1f7317d..7cbcf31f08 100644 --- a/rust/src/nfs/nfs.rs +++ b/rust/src/nfs/nfs.rs @@ -40,14 +40,6 @@ use nfs::nfs_records::*; use nfs::nfs2_records::*; use nfs::nfs3_records::*; -/// nom bug leads to this wrappers being necessary -/// TODO for some reason putting these in parser.rs and making them public -/// leads to a compile error wrt an unknown lifetime identifier 'a -//named!(many0_nfs3_request_objects>>, many0!(parse_nfs3_request_object)); -//named!(many0_nfs3_reply_objects>>, many0!(parse_nfs3_reply_object)); -named!(many0_nfs3_response_readdirplus_entries>>, - many0!(parse_nfs3_response_readdirplus_entry_cond)); - pub static mut SURICATA_NFS3_FILE_CONFIG: Option<&'static SuricataFileContext> = None; /* @@ -455,7 +447,7 @@ impl NFSState { } // TODO maybe not enough users to justify a func - fn mark_response_tx_done(&mut self, xid: u32, rpc_status: u32, nfs_status: u32, resp_handle: &Vec) + pub fn mark_response_tx_done(&mut self, xid: u32, rpc_status: u32, nfs_status: u32, resp_handle: &Vec) { match self.get_tx_by_xid(xid) { Some(mytx) => { @@ -475,7 +467,7 @@ impl NFSState { } } - fn process_request_record_lookup<'b>(&mut self, r: &RpcPacket<'b>, xidmap: &mut NFSRequestXidMap) { + pub fn process_request_record_lookup<'b>(&mut self, r: &RpcPacket<'b>, xidmap: &mut NFSRequestXidMap) { match parse_nfs3_request_lookup(r.prog_data) { IResult::Done(_, lookup) => { SCLogDebug!("LOOKUP {:?}", lookup); @@ -519,208 +511,6 @@ impl NFSState { } } - /// complete NFS3 request record - fn process_request_record_v3<'b>(&mut self, r: &RpcPacket<'b>) -> u32 { - SCLogDebug!("REQUEST {} procedure {} ({}) blob size {}", - r.hdr.xid, r.procedure, self.requestmap.len(), r.prog_data.len()); - - let mut xidmap = NFSRequestXidMap::new(r.progver, r.procedure, 0); - let mut aux_file_name = Vec::new(); - - if self.nfs_version == 0 { - self.nfs_version = r.progver as u16; - } - - if r.procedure == NFSPROC3_LOOKUP { - self.process_request_record_lookup(r, &mut xidmap); - - } else if r.procedure == NFSPROC3_ACCESS { - match parse_nfs3_request_access(r.prog_data) { - IResult::Done(_, ar) => { - xidmap.file_handle = ar.handle.value.to_vec(); - self.xidmap_handle2name(&mut xidmap); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_GETATTR { - match parse_nfs3_request_getattr(r.prog_data) { - IResult::Done(_, gar) => { - xidmap.file_handle = gar.handle.value.to_vec(); - self.xidmap_handle2name(&mut xidmap); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_READDIRPLUS { - match parse_nfs3_request_readdirplus(r.prog_data) { - IResult::Done(_, rdp) => { - xidmap.file_handle = rdp.handle.value.to_vec(); - self.xidmap_handle2name(&mut xidmap); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_READ { - match parse_nfs3_request_read(r.prog_data) { - IResult::Done(_, nfs3_read_record) => { - xidmap.chunk_offset = nfs3_read_record.offset; - xidmap.file_handle = nfs3_read_record.handle.value.to_vec(); - self.xidmap_handle2name(&mut xidmap); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_WRITE { - match parse_nfs3_request_write(r.prog_data) { - IResult::Done(_, w) => { - self.process_write_record(r, &w); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - } - } else if r.procedure == NFSPROC3_CREATE { - match parse_nfs3_request_create(r.prog_data) { - IResult::Done(_, nfs3_create_record) => { - xidmap.file_handle = nfs3_create_record.handle.value.to_vec(); - xidmap.file_name = nfs3_create_record.name_vec; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - - } else if r.procedure == NFSPROC3_REMOVE { - match parse_nfs3_request_remove(r.prog_data) { - IResult::Done(_, rr) => { - xidmap.file_handle = rr.handle.value.to_vec(); - xidmap.file_name = rr.name_vec; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - - } else if r.procedure == NFSPROC3_RENAME { - match parse_nfs3_request_rename(r.prog_data) { - IResult::Done(_, rr) => { - xidmap.file_handle = rr.from_handle.value.to_vec(); - xidmap.file_name = rr.from_name_vec; - aux_file_name = rr.to_name_vec; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_MKDIR { - match parse_nfs3_request_mkdir(r.prog_data) { - IResult::Done(_, mr) => { - xidmap.file_handle = mr.handle.value.to_vec(); - xidmap.file_name = mr.name_vec; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_RMDIR { - match parse_nfs3_request_rmdir(r.prog_data) { - IResult::Done(_, rr) => { - xidmap.file_handle = rr.handle.value.to_vec(); - xidmap.file_name = rr.name_vec; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if r.procedure == NFSPROC3_COMMIT { - SCLogDebug!("COMMIT, closing shop"); - - match parse_nfs3_request_commit(r.prog_data) { - IResult::Done(_, cr) => { - let file_handle = cr.handle.value.to_vec(); - match self.get_file_tx_by_handle(&file_handle, STREAM_TOSERVER) { - Some((tx, files, flags)) => { - if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { - tdf.chunk_count += 1; - tdf.file_additional_procs.push(NFSPROC3_COMMIT); - tdf.file_tracker.close(files, flags); - tdf.file_last_xid = r.hdr.xid; - tx.is_last = true; - tx.request_done = true; - } - }, - None => { }, - } - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } - - if !(r.procedure == NFSPROC3_COMMIT || // commit handled separately - r.procedure == NFSPROC3_WRITE || // write handled in file tx - r.procedure == NFSPROC3_READ) // read handled in file tx at reply - { - let mut tx = self.new_tx(); - tx.xid = r.hdr.xid; - tx.procedure = r.procedure; - tx.request_done = true; - tx.file_name = xidmap.file_name.to_vec(); - tx.nfs_version = r.progver as u16; - tx.file_handle = xidmap.file_handle.to_vec(); - - if r.procedure == NFSPROC3_RENAME { - tx.type_data = Some(NFSTransactionTypeData::RENAME(aux_file_name)); - } - - tx.auth_type = r.creds_flavor; - match r.creds { - RpcRequestCreds::Unix(ref u) => { - tx.request_machine_name = u.machine_name_buf.to_vec(); - tx.request_uid = u.uid; - tx.request_gid = u.gid; - }, - _ => { }, - } - SCLogDebug!("TX created: ID {} XID {} PROCEDURE {}", - tx.id, tx.xid, tx.procedure); - self.transactions.push(tx); - - } else if r.procedure == NFSPROC3_READ { - - let found = match self.get_file_tx_by_handle(&xidmap.file_handle, STREAM_TOCLIENT) { - Some((_, _, _)) => true, - None => false, - }; - if !found { - let (tx, _, _) = self.new_file_tx(&xidmap.file_handle, &xidmap.file_name, STREAM_TOCLIENT); - tx.procedure = NFSPROC3_READ; - tx.xid = r.hdr.xid; - tx.is_first = true; - tx.nfs_version = r.progver as u16; - - tx.auth_type = r.creds_flavor; - match r.creds { - RpcRequestCreds::Unix(ref u) => { - tx.request_machine_name = u.machine_name_buf.to_vec(); - tx.request_uid = u.uid; - tx.request_gid = u.gid; - }, - _ => { }, - } - } - } - - self.requestmap.insert(r.hdr.xid, xidmap); - 0 - } - /// complete request record fn process_request_record_v2<'b>(&mut self, r: &RpcPacket<'b>) -> u32 { SCLogDebug!("NFSv2 REQUEST {} procedure {} ({}) blob size {}", @@ -826,7 +616,7 @@ impl NFSState { return None; } - fn process_write_record<'b>(&mut self, r: &RpcPacket<'b>, w: &Nfs3RequestWrite<'b>) -> u32 { + pub fn process_write_record<'b>(&mut self, r: &RpcPacket<'b>, w: &Nfs3RequestWrite<'b>) -> u32 { // for now assume that stable FILE_SYNC flags means a single chunk let is_last = if w.stable == 2 { true } else { false }; @@ -902,117 +692,6 @@ impl NFSState { return self.process_write_record(r, w); } - fn process_reply_record_v3<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &mut NFSRequestXidMap) -> u32 { - let mut nfs_status = 0; - let mut resp_handle = Vec::new(); - - if xidmap.procedure == NFSPROC3_LOOKUP { - match parse_nfs3_response_lookup(r.prog_data) { - IResult::Done(_, lookup) => { - SCLogDebug!("LOOKUP: {:?}", lookup); - SCLogDebug!("RESPONSE LOOKUP file_name {:?}", xidmap.file_name); - - nfs_status = lookup.status; - - SCLogDebug!("LOOKUP handle {:?}", lookup.handle); - self.namemap.insert(lookup.handle.value.to_vec(), xidmap.file_name.to_vec()); - resp_handle = lookup.handle.value.to_vec(); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if xidmap.procedure == NFSPROC3_CREATE { - match parse_nfs3_response_create(r.prog_data) { - IResult::Done(_, nfs3_create_record) => { - SCLogDebug!("nfs3_create_record: {:?}", nfs3_create_record); - - SCLogDebug!("RESPONSE CREATE file_name {:?}", xidmap.file_name); - nfs_status = nfs3_create_record.status; - - if let Some(h) = nfs3_create_record.handle { - SCLogDebug!("handle {:?}", h); - self.namemap.insert(h.value.to_vec(), xidmap.file_name.to_vec()); - resp_handle = h.value.to_vec(); - } - - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - }; - } else if xidmap.procedure == NFSPROC3_READ { - match parse_nfs3_reply_read(r.prog_data) { - IResult::Done(_, ref reply) => { - self.process_read_record(r, reply, Some(&xidmap)); - nfs_status = reply.status; - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - } - } else if xidmap.procedure == NFSPROC3_READDIRPLUS { - match parse_nfs3_response_readdirplus(r.prog_data) { - IResult::Done(_, ref reply) => { - //SCLogDebug!("READDIRPLUS reply {:?}", reply); - - nfs_status = reply.status; - - // cut off final eof field - let d = &reply.data[..reply.data.len()-4 as usize]; - - // store all handle/filename mappings - match many0_nfs3_response_readdirplus_entries(d) { - IResult::Done(_, ref entries) => { - for ce in entries { - SCLogDebug!("ce {:?}", ce); - match ce.entry { - Some(ref e) => { - SCLogDebug!("e {:?}", e); - match e.handle { - Some(ref h) => { - SCLogDebug!("h {:?}", h); - self.namemap.insert(h.value.to_vec(), e.name_vec.to_vec()); - }, - _ => { }, - } - }, - _ => { }, - } - } - - SCLogDebug!("READDIRPLUS ENTRIES reply {:?}", entries); - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - } - }, - _ => { - self.set_event(NFSEvent::MalformedData); - }, - } - } - // for all other record types only parse the status - else { - let stat = match nom::be_u32(&r.prog_data) { - nom::IResult::Done(_, stat) => { - stat as u32 - } - _ => 0 as u32 - }; - nfs_status = stat; - } - SCLogDebug!("REPLY {} to procedure {} blob size {}", - r.hdr.xid, xidmap.procedure, r.prog_data.len()); - - if xidmap.procedure != NFSPROC3_READ { - self.mark_response_tx_done(r.hdr.xid, r.reply_state, nfs_status, &resp_handle); - } - - 0 - } - fn process_reply_record_v2<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &NFSRequestXidMap) -> u32 { let mut nfs_status = 0; let resp_handle = Vec::new(); diff --git a/rust/src/nfs/nfs3.rs b/rust/src/nfs/nfs3.rs new file mode 100644 index 0000000000..a76b0a3f2c --- /dev/null +++ b/rust/src/nfs/nfs3.rs @@ -0,0 +1,353 @@ +/* Copyright (C) 2017-2018 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 + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +// written by Victor Julien + +use nom; +use nom::IResult; +use log::*; +use core::*; + +use nfs::nfs::*; +use nfs::types::*; +use nfs::rpc_records::*; +use nfs::nfs3_records::*; + +/// nom bug leads to this wrappers being necessary +/// TODO for some reason putting these in parser.rs and making them public +/// leads to a compile error wrt an unknown lifetime identifier 'a +//named!(many0_nfs3_request_objects>>, many0!(parse_nfs3_request_object)); +//named!(many0_nfs3_reply_objects>>, many0!(parse_nfs3_reply_object)); +named!(many0_nfs3_response_readdirplus_entries>>, + many0!(parse_nfs3_response_readdirplus_entry_cond)); + +impl NFSState { + /// complete NFS3 request record + pub fn process_request_record_v3<'b>(&mut self, r: &RpcPacket<'b>) -> u32 { + SCLogDebug!("REQUEST {} procedure {} ({}) blob size {}", + r.hdr.xid, r.procedure, self.requestmap.len(), r.prog_data.len()); + + let mut xidmap = NFSRequestXidMap::new(r.progver, r.procedure, 0); + let mut aux_file_name = Vec::new(); + + if self.nfs_version == 0 { + self.nfs_version = r.progver as u16; + } + + if r.procedure == NFSPROC3_LOOKUP { + self.process_request_record_lookup(r, &mut xidmap); + + } else if r.procedure == NFSPROC3_ACCESS { + match parse_nfs3_request_access(r.prog_data) { + IResult::Done(_, ar) => { + xidmap.file_handle = ar.handle.value.to_vec(); + self.xidmap_handle2name(&mut xidmap); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_GETATTR { + match parse_nfs3_request_getattr(r.prog_data) { + IResult::Done(_, gar) => { + xidmap.file_handle = gar.handle.value.to_vec(); + self.xidmap_handle2name(&mut xidmap); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_READDIRPLUS { + match parse_nfs3_request_readdirplus(r.prog_data) { + IResult::Done(_, rdp) => { + xidmap.file_handle = rdp.handle.value.to_vec(); + self.xidmap_handle2name(&mut xidmap); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_READ { + match parse_nfs3_request_read(r.prog_data) { + IResult::Done(_, nfs3_read_record) => { + xidmap.chunk_offset = nfs3_read_record.offset; + xidmap.file_handle = nfs3_read_record.handle.value.to_vec(); + self.xidmap_handle2name(&mut xidmap); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_WRITE { + match parse_nfs3_request_write(r.prog_data) { + IResult::Done(_, w) => { + self.process_write_record(r, &w); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + } + } else if r.procedure == NFSPROC3_CREATE { + match parse_nfs3_request_create(r.prog_data) { + IResult::Done(_, nfs3_create_record) => { + xidmap.file_handle = nfs3_create_record.handle.value.to_vec(); + xidmap.file_name = nfs3_create_record.name_vec; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + + } else if r.procedure == NFSPROC3_REMOVE { + match parse_nfs3_request_remove(r.prog_data) { + IResult::Done(_, rr) => { + xidmap.file_handle = rr.handle.value.to_vec(); + xidmap.file_name = rr.name_vec; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + + } else if r.procedure == NFSPROC3_RENAME { + match parse_nfs3_request_rename(r.prog_data) { + IResult::Done(_, rr) => { + xidmap.file_handle = rr.from_handle.value.to_vec(); + xidmap.file_name = rr.from_name_vec; + aux_file_name = rr.to_name_vec; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_MKDIR { + match parse_nfs3_request_mkdir(r.prog_data) { + IResult::Done(_, mr) => { + xidmap.file_handle = mr.handle.value.to_vec(); + xidmap.file_name = mr.name_vec; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_RMDIR { + match parse_nfs3_request_rmdir(r.prog_data) { + IResult::Done(_, rr) => { + xidmap.file_handle = rr.handle.value.to_vec(); + xidmap.file_name = rr.name_vec; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if r.procedure == NFSPROC3_COMMIT { + SCLogDebug!("COMMIT, closing shop"); + + match parse_nfs3_request_commit(r.prog_data) { + IResult::Done(_, cr) => { + let file_handle = cr.handle.value.to_vec(); + match self.get_file_tx_by_handle(&file_handle, STREAM_TOSERVER) { + Some((tx, files, flags)) => { + if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data { + tdf.chunk_count += 1; + tdf.file_additional_procs.push(NFSPROC3_COMMIT); + tdf.file_tracker.close(files, flags); + tdf.file_last_xid = r.hdr.xid; + tx.is_last = true; + tx.request_done = true; + } + }, + None => { }, + } + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } + + if !(r.procedure == NFSPROC3_COMMIT || // commit handled separately + r.procedure == NFSPROC3_WRITE || // write handled in file tx + r.procedure == NFSPROC3_READ) // read handled in file tx at reply + { + let mut tx = self.new_tx(); + tx.xid = r.hdr.xid; + tx.procedure = r.procedure; + tx.request_done = true; + tx.file_name = xidmap.file_name.to_vec(); + tx.nfs_version = r.progver as u16; + tx.file_handle = xidmap.file_handle.to_vec(); + + if r.procedure == NFSPROC3_RENAME { + tx.type_data = Some(NFSTransactionTypeData::RENAME(aux_file_name)); + } + + tx.auth_type = r.creds_flavor; + match r.creds { + RpcRequestCreds::Unix(ref u) => { + tx.request_machine_name = u.machine_name_buf.to_vec(); + tx.request_uid = u.uid; + tx.request_gid = u.gid; + }, + _ => { }, + } + SCLogDebug!("TX created: ID {} XID {} PROCEDURE {}", + tx.id, tx.xid, tx.procedure); + self.transactions.push(tx); + + } else if r.procedure == NFSPROC3_READ { + + let found = match self.get_file_tx_by_handle(&xidmap.file_handle, STREAM_TOCLIENT) { + Some((_, _, _)) => true, + None => false, + }; + if !found { + let (tx, _, _) = self.new_file_tx(&xidmap.file_handle, &xidmap.file_name, STREAM_TOCLIENT); + tx.procedure = NFSPROC3_READ; + tx.xid = r.hdr.xid; + tx.is_first = true; + tx.nfs_version = r.progver as u16; + + tx.auth_type = r.creds_flavor; + match r.creds { + RpcRequestCreds::Unix(ref u) => { + tx.request_machine_name = u.machine_name_buf.to_vec(); + tx.request_uid = u.uid; + tx.request_gid = u.gid; + }, + _ => { }, + } + } + } + + self.requestmap.insert(r.hdr.xid, xidmap); + 0 + } + + pub fn process_reply_record_v3<'b>(&mut self, r: &RpcReplyPacket<'b>, xidmap: &mut NFSRequestXidMap) -> u32 { + let mut nfs_status = 0; + let mut resp_handle = Vec::new(); + + if xidmap.procedure == NFSPROC3_LOOKUP { + match parse_nfs3_response_lookup(r.prog_data) { + IResult::Done(_, lookup) => { + SCLogDebug!("LOOKUP: {:?}", lookup); + SCLogDebug!("RESPONSE LOOKUP file_name {:?}", xidmap.file_name); + + nfs_status = lookup.status; + + SCLogDebug!("LOOKUP handle {:?}", lookup.handle); + self.namemap.insert(lookup.handle.value.to_vec(), xidmap.file_name.to_vec()); + resp_handle = lookup.handle.value.to_vec(); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if xidmap.procedure == NFSPROC3_CREATE { + match parse_nfs3_response_create(r.prog_data) { + IResult::Done(_, nfs3_create_record) => { + SCLogDebug!("nfs3_create_record: {:?}", nfs3_create_record); + + SCLogDebug!("RESPONSE CREATE file_name {:?}", xidmap.file_name); + nfs_status = nfs3_create_record.status; + + if let Some(h) = nfs3_create_record.handle { + SCLogDebug!("handle {:?}", h); + self.namemap.insert(h.value.to_vec(), xidmap.file_name.to_vec()); + resp_handle = h.value.to_vec(); + } + + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + }; + } else if xidmap.procedure == NFSPROC3_READ { + match parse_nfs3_reply_read(r.prog_data) { + IResult::Done(_, ref reply) => { + self.process_read_record(r, reply, Some(&xidmap)); + nfs_status = reply.status; + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + } + } else if xidmap.procedure == NFSPROC3_READDIRPLUS { + match parse_nfs3_response_readdirplus(r.prog_data) { + IResult::Done(_, ref reply) => { + //SCLogDebug!("READDIRPLUS reply {:?}", reply); + + nfs_status = reply.status; + + // cut off final eof field + let d = &reply.data[..reply.data.len()-4 as usize]; + + // store all handle/filename mappings + match many0_nfs3_response_readdirplus_entries(d) { + IResult::Done(_, ref entries) => { + for ce in entries { + SCLogDebug!("ce {:?}", ce); + match ce.entry { + Some(ref e) => { + SCLogDebug!("e {:?}", e); + match e.handle { + Some(ref h) => { + SCLogDebug!("h {:?}", h); + self.namemap.insert(h.value.to_vec(), e.name_vec.to_vec()); + }, + _ => { }, + } + }, + _ => { }, + } + } + + SCLogDebug!("READDIRPLUS ENTRIES reply {:?}", entries); + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + } + }, + _ => { + self.set_event(NFSEvent::MalformedData); + }, + } + } + // for all other record types only parse the status + else { + let stat = match nom::be_u32(&r.prog_data) { + nom::IResult::Done(_, stat) => { + stat as u32 + } + _ => 0 as u32 + }; + nfs_status = stat; + } + SCLogDebug!("REPLY {} to procedure {} blob size {}", + r.hdr.xid, xidmap.procedure, r.prog_data.len()); + + if xidmap.procedure != NFSPROC3_READ { + self.mark_response_tx_done(r.hdr.xid, r.reply_state, nfs_status, &resp_handle); + } + + 0 + } + +} +