]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs: convert parser to nom7 functions (NFS v3 and v4 records)
authorPierre Chifflier <chifflier@wzdftpd.net>
Mon, 8 Nov 2021 15:38:17 +0000 (16:38 +0100)
committerVictor Julien <vjulien@oisf.net>
Mon, 22 Nov 2021 10:20:23 +0000 (11:20 +0100)
rust/src/nfs/nfs.rs
rust/src/nfs/nfs3_records.rs
rust/src/nfs/nfs4.rs
rust/src/nfs/nfs4_records.rs
rust/src/nfs/rpc_records.rs

index 444e7856233ced51f21f593d894f8a20c77b93e4..9b6db86a5f2389d4e9d3a8675123f1cb2e2a779c 100644 (file)
 
 use std;
 use std::cmp;
-use std::collections::{HashMap};
+use std::collections::HashMap;
 use std::ffi::{CStr, CString};
 
-use nom;
+use nom7::{Err, Needed};
 
 use crate::applayer;
 use crate::applayer::*;
@@ -250,9 +250,9 @@ pub struct NFSRequestXidMap {
 impl NFSRequestXidMap {
     pub fn new(progver: u32, procedure: u32, chunk_offset: u64) -> NFSRequestXidMap {
         NFSRequestXidMap {
-            progver:progver,
-            procedure:procedure,
-            chunk_offset:chunk_offset,
+            progver,
+            procedure,
+            chunk_offset,
             file_name:Vec::new(),
             file_handle:Vec::new(),
             gssapi_proc: 0,
@@ -1068,7 +1068,7 @@ impl NFSState {
                                             },
                                         }
                                     },
-                                    Err(nom::Err::Incomplete(_)) => {
+                                    Err(Err::Incomplete(_)) => {
                                         // we just size checked for the minimal record size above,
                                         // so if options are used (creds/verifier), we can still
                                         // have Incomplete data. Fall through to the buffer code
@@ -1076,8 +1076,8 @@ impl NFSState {
                                         SCLogDebug!("TS data incomplete");
                                         // fall through to the incomplete below
                                     },
-                                    Err(nom::Err::Error(_e)) |
-                                    Err(nom::Err::Failure(_e)) => {
+                                    Err(Err::Error(_e)) |
+                                    Err(Err::Failure(_e)) => {
                                         self.set_event(NFSEvent::MalformedData);
                                         SCLogDebug!("Parsing failed: {:?}", _e);
                                         return AppLayerResult::err();
@@ -1099,7 +1099,7 @@ impl NFSState {
                             cur_i = &cur_i[rec_size..];
                             self.process_request_record(rpc_record);
                         },
-                        Err(nom::Err::Incomplete(_)) => {
+                        Err(Err::Incomplete(_)) => {
                             cur_i = &cur_i[rec_size..]; // progress input past parsed record
 
                             // we shouldn't get incomplete as we have the full data
@@ -1107,26 +1107,27 @@ impl NFSState {
                             // bad.
                             self.set_event(NFSEvent::MalformedData);
                         },
-                        Err(nom::Err::Error(_e)) |
-                        Err(nom::Err::Failure(_e)) => {
+                        Err(Err::Error(_e)) |
+                        Err(Err::Failure(_e)) => {
                             self.set_event(NFSEvent::MalformedData);
                             SCLogDebug!("Parsing failed: {:?}", _e);
                             return AppLayerResult::err();
                         },
                     }
                 },
-                Err(nom::Err::Incomplete(needed)) => {
-                    if let nom::Needed::Size(n) = needed {
+                Err(Err::Incomplete(needed)) => {
+                    if let Needed::Size(n) = needed {
                         SCLogDebug!("Not enough data for partial RPC header {:?}", needed);
                         // 28 is the partial RPC header size parse_rpc_request_partial
                         // looks for.
+                        let n = usize::from(n);
                         let need = if n > 28 { n } else { 28 };
                         return AppLayerResult::incomplete((i.len() - cur_i.len()) as u32, need as u32);
                     }
                     return AppLayerResult::err();
                 },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                Err(Err::Error(_e)) |
+                Err(Err::Failure(_e)) => {
                     self.set_event(NFSEvent::MalformedData);
                     SCLogDebug!("Parsing failed: {:?}", _e);
                     return AppLayerResult::err();
@@ -1214,23 +1215,23 @@ impl NFSState {
                                                 self.process_partial_read_reply_record(rpc_record, nfs_reply_read);
                                                 cur_i = remaining; // progress input past parsed record
                                             },
-                                            Err(nom::Err::Incomplete(_)) => {
+                                            Err(Err::Incomplete(_)) => {
                                             },
-                                            Err(nom::Err::Error(_e)) |
-                                            Err(nom::Err::Failure(_e)) => {
+                                            Err(Err::Error(_e)) |
+                                            Err(Err::Failure(_e)) => {
                                                 self.set_event(NFSEvent::MalformedData);
                                                 SCLogDebug!("Parsing failed: {:?}", _e);
                                                 return AppLayerResult::err();
                                             }
                                         }
                                     },
-                                    Err(nom::Err::Incomplete(_)) => {
+                                    Err(Err::Incomplete(_)) => {
                                         // size check was done for MINIMAL record size,
                                         // so Incomplete is normal.
                                         SCLogDebug!("TC data incomplete");
                                     },
-                                    Err(nom::Err::Error(_e)) |
-                                    Err(nom::Err::Failure(_e)) => {
+                                    Err(Err::Error(_e)) |
+                                    Err(Err::Failure(_e)) => {
                                         self.set_event(NFSEvent::MalformedData);
                                         SCLogDebug!("Parsing failed: {:?}", _e);
                                         return AppLayerResult::err();
@@ -1251,7 +1252,7 @@ impl NFSState {
                             cur_i = &cur_i[rec_size..]; // progress input past parsed record
                             self.process_reply_record(rpc_record);
                         },
-                        Err(nom::Err::Incomplete(_)) => {
+                        Err(Err::Incomplete(_)) => {
                             cur_i = &cur_i[rec_size..]; // progress input past parsed record
 
                             // we shouldn't get incomplete as we have the full data
@@ -1259,26 +1260,27 @@ impl NFSState {
                             // bad.
                             self.set_event(NFSEvent::MalformedData);
                         },
-                        Err(nom::Err::Error(_e)) |
-                        Err(nom::Err::Failure(_e)) => {
+                        Err(Err::Error(_e)) |
+                        Err(Err::Failure(_e)) => {
                             self.set_event(NFSEvent::MalformedData);
                             SCLogDebug!("Parsing failed: {:?}", _e);
                             return AppLayerResult::err();
                         }
                     }
                 },
-                Err(nom::Err::Incomplete(needed)) => {
-                    if let nom::Needed::Size(n) = needed {
+                Err(Err::Incomplete(needed)) => {
+                    if let Needed::Size(n) = needed {
                         SCLogDebug!("Not enough data for partial RPC header {:?}", needed);
                         // 12 is the partial RPC header size parse_rpc_packet_header
                         // looks for.
+                        let n = usize::from(n);
                         let need = if n > 12 { n } else { 12 };
                         return AppLayerResult::incomplete((i.len() - cur_i.len()) as u32, need as u32);
                     }
                     return AppLayerResult::err();
                 },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                Err(Err::Error(_e)) |
+                Err(Err::Failure(_e)) => {
                     self.set_event(NFSEvent::MalformedData);
                     SCLogDebug!("Parsing failed: {:?}", _e);
                     return AppLayerResult::err();
@@ -1309,10 +1311,10 @@ impl NFSState {
                         _ => { },
                     }
                 },
-                Err(nom::Err::Incomplete(_)) => {
+                Err(Err::Incomplete(_)) => {
                 },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                Err(Err::Error(_e)) |
+                Err(Err::Failure(_e)) => {
                     SCLogDebug!("Parsing failed: {:?}", _e);
                 }
             }
@@ -1329,10 +1331,10 @@ impl NFSState {
                     self.is_udp = true;
                     self.process_reply_record(rpc_record);
                 },
-                Err(nom::Err::Incomplete(_)) => {
+                Err(Err::Incomplete(_)) => {
                 },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                Err(Err::Error(_e)) |
+                Err(Err::Failure(_e)) => {
                     SCLogDebug!("Parsing failed: {:?}", _e);
                 }
             }
@@ -1649,7 +1651,7 @@ fn nfs_probe_dir(i: &[u8], rdir: *mut u8) -> i8 {
             unsafe { *rdir = dir as u8 };
             return 1;
         },
-        Err(nom::Err::Incomplete(_)) => {
+        Err(Err::Incomplete(_)) => {
             return 0;
         },
         Err(_) => {
@@ -1669,7 +1671,7 @@ pub fn nfs_probe(i: &[u8], direction: Direction) -> i32 {
                     return -1;
                 }
             },
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 match parse_rpc_packet_header (i) {
                     Ok((_, ref rpc_hdr)) => {
                         if rpc_hdr.frag_len >= 24 && rpc_hdr.frag_len <= 35000 && rpc_hdr.xid != 0 && rpc_hdr.msgtype == 1 {
@@ -1679,7 +1681,7 @@ pub fn nfs_probe(i: &[u8], direction: Direction) -> i32 {
                             return -1;
                         }
                     },
-                    Err(nom::Err::Incomplete(_)) => {
+                    Err(Err::Incomplete(_)) => {
                         return 0;
                     },
                     Err(_) => {
@@ -1704,7 +1706,7 @@ pub fn nfs_probe(i: &[u8], direction: Direction) -> i32 {
                     return -1;
                 }
             },
-            Err(nom::Err::Incomplete(_)) => {
+            Err(Err::Incomplete(_)) => {
                 return 0;
             },
             Err(_) => {
index 2130063ba1574e4a5405f5c058fd39850a484858..62e6a44ef497e6a174c0afdcfee4517e3d4cc9d8 100644 (file)
 
 //! Nom parsers for RPC & NFSv3
 
-use nom::IResult;
-use nom::combinator::rest;
-use nom::number::streaming::{be_u32, be_u64};
 use crate::nfs::nfs_records::*;
+use nom7::bytes::streaming::take;
+use nom7::combinator::{complete, cond, rest};
+use nom7::multi::{length_data, many0};
+use nom7::number::streaming::{be_u32, be_u64};
+use nom7::IResult;
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3Handle<'a> {
     pub len: u32,
-    pub value: &'a[u8],
+    pub value: &'a [u8],
 }
 
-named!(pub parse_nfs3_handle<Nfs3Handle>,
-    do_parse!(
-        obj_len: be_u32
-        >> obj: take!(obj_len)
-        >> (
-            Nfs3Handle {
-                len:obj_len,
-                value:obj,
-            }
-        ))
-);
+pub fn parse_nfs3_handle(i: &[u8]) -> IResult<&[u8], Nfs3Handle> {
+    let (i, len) = be_u32(i)?;
+    let (i, value) = take(len as usize)(i)?;
+    let handle = Nfs3Handle { len, value };
+    Ok((i, handle))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3ReplyCreate<'a> {
     pub status: u32,
     pub handle: Option<Nfs3Handle<'a>>,
 }
 
-named!(pub parse_nfs3_response_create<Nfs3ReplyCreate>,
-    do_parse!(
-        status: be_u32
-        >> handle_has_value: be_u32
-        >> handle: cond!(handle_has_value == 1, parse_nfs3_handle)
-        >> (
-            Nfs3ReplyCreate {
-               status:status,
-               handle:handle,
-            }
-        ))
-);
+pub fn parse_nfs3_response_create(i: &[u8]) -> IResult<&[u8], Nfs3ReplyCreate> {
+    let (i, status) = be_u32(i)?;
+    let (i, handle_has_value) = be_u32(i)?;
+    let (i, handle) = cond(handle_has_value == 1, parse_nfs3_handle)(i)?;
+    let reply = Nfs3ReplyCreate { status, handle };
+    Ok((i, reply))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3ReplyLookup<'a> {
     pub status: u32,
     pub handle: Nfs3Handle<'a>,
 }
 
-named!(pub parse_nfs3_response_lookup<Nfs3ReplyLookup>,
-    do_parse!(
-        status: be_u32
-        >> handle: parse_nfs3_handle
-        >> (
-            Nfs3ReplyLookup {
-                status:status,
-                handle:handle,
-            }
-        ))
-);
+pub fn parse_nfs3_response_lookup(i: &[u8]) -> IResult<&[u8], Nfs3ReplyLookup> {
+    let (i, status) = be_u32(i)?;
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let reply = Nfs3ReplyLookup { status, handle };
+    Ok((i, reply))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestCreate<'a> {
     pub handle: Nfs3Handle<'a>,
     pub name_len: u32,
     pub create_mode: u32,
-    pub verifier: &'a[u8],
+    pub verifier: &'a [u8],
     pub name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_create<Nfs3RequestCreate>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  name_len: be_u32
-        >>  name: take!(name_len)
-        >>  create_mode: be_u32
-        >>  verifier: rest
-        >> (
-            Nfs3RequestCreate {
-                handle:handle,
-                name_len:name_len,
-                create_mode:create_mode,
-                verifier:verifier,
-                name_vec:name.to_vec(),
-            }
-        ))
-);
+pub fn parse_nfs3_request_create(i: &[u8]) -> IResult<&[u8], Nfs3RequestCreate> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, name_len) = be_u32(i)?;
+    let (i, name) = take(name_len as usize)(i)?;
+    let (i, create_mode) = be_u32(i)?;
+    let (i, verifier) = rest(i)?;
+    let req = Nfs3RequestCreate {
+        handle,
+        name_len,
+        create_mode,
+        verifier,
+        name_vec: name.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestRemove<'a> {
     pub handle: Nfs3Handle<'a>,
     pub name_len: u32,
     pub name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_remove<Nfs3RequestRemove>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  name_len: be_u32
-        >>  name: take!(name_len)
-        >>  _fill_bytes: rest
-        >> (
-            Nfs3RequestRemove {
-                handle:handle,
-                name_len:name_len,
-                name_vec:name.to_vec(),
-            }
-        ))
-);
+pub fn parse_nfs3_request_remove(i: &[u8]) -> IResult<&[u8], Nfs3RequestRemove> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, name_len) = be_u32(i)?;
+    let (i, name) = take(name_len as usize)(i)?;
+    let (i, _fill_bytes) = rest(i)?;
+    let req = Nfs3RequestRemove {
+        handle,
+        name_len,
+        name_vec: name.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestRmdir<'a> {
     pub handle: Nfs3Handle<'a>,
     pub name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_rmdir<Nfs3RequestRmdir>,
-    do_parse!(
-            dir_handle: parse_nfs3_handle
-        >>  name_len: be_u32
-        >>  name: take!(name_len)
-        >>  _fill_bytes: cond!(name_len % 4 != 0, take!(4 - name_len % 4))
-        >> (
-            Nfs3RequestRmdir {
-                handle:dir_handle,
-                name_vec:name.to_vec(),
-            }
-        ))
-);
+pub fn parse_nfs3_request_rmdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestRmdir> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, name_len) = be_u32(i)?;
+    let (i, name) = take(name_len as usize)(i)?;
+    let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
+    let req = Nfs3RequestRmdir {
+        handle,
+        name_vec: name.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestMkdir<'a> {
     pub handle: Nfs3Handle<'a>,
     pub name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_mkdir<Nfs3RequestMkdir>,
-    do_parse!(
-            dir_handle: parse_nfs3_handle
-        >>  name_len: be_u32
-        >>  name: take!(name_len)
-        >>  _fill_bytes: cond!(name_len % 4 != 0, take!(4 - name_len % 4))
-        >>  _attributes: rest
-        >> (
-            Nfs3RequestMkdir {
-                handle:dir_handle,
-                name_vec:name.to_vec(),
-            }
-        ))
-);
+pub fn parse_nfs3_request_mkdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestMkdir> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, name_len) = be_u32(i)?;
+    let (i, name) = take(name_len as usize)(i)?;
+    let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
+    let (i, _attributes) = rest(i)?;
+    let req = Nfs3RequestMkdir {
+        handle,
+        name_vec: name.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestRename<'a> {
     pub from_handle: Nfs3Handle<'a>,
     pub from_name_vec: Vec<u8>,
@@ -175,212 +154,180 @@ pub struct Nfs3RequestRename<'a> {
     pub to_name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_rename<Nfs3RequestRename>,
-    do_parse!(
-            from_handle: parse_nfs3_handle
-        >>  from_name_len: be_u32
-        >>  from_name: take!(from_name_len)
-        >>  _from_fill_bytes: cond!(from_name_len % 4 != 0, take!(4 - from_name_len % 4))
-        >>  to_handle: parse_nfs3_handle
-        >>  to_name_len: be_u32
-        >>  to_name: take!(to_name_len)
-        >>  _to_fill_bytes: rest
-        >> (
-            Nfs3RequestRename {
-                from_handle,
-                from_name_vec:from_name.to_vec(),
-                to_handle,
-                to_name_vec:to_name.to_vec(),
-            }
-        ))
-);
+pub fn parse_nfs3_request_rename(i: &[u8]) -> IResult<&[u8], Nfs3RequestRename> {
+    let (i, from_handle) = parse_nfs3_handle(i)?;
+    let (i, from_name_len) = be_u32(i)?;
+    let (i, from_name) = take(from_name_len as usize)(i)?;
+    let (i, _from_fill_bytes) = cond(from_name_len % 4 != 0, take(4 - (from_name_len % 4)))(i)?;
+
+    let (i, to_handle) = parse_nfs3_handle(i)?;
+    let (i, to_name_len) = be_u32(i)?;
+    let (i, to_name) = take(to_name_len as usize)(i)?;
+    let (i, _from_fill_bytes) = rest(i)?;
+    let req = Nfs3RequestRename {
+        from_handle,
+        from_name_vec: from_name.to_vec(),
+        to_handle,
+        to_name_vec: to_name.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestGetAttr<'a> {
     pub handle: Nfs3Handle<'a>,
 }
 
-named!(pub parse_nfs3_request_getattr<Nfs3RequestGetAttr>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >> (
-            Nfs3RequestGetAttr {
-                handle:handle,
-            }
-        ))
-);
+pub fn parse_nfs3_request_getattr(i: &[u8]) -> IResult<&[u8], Nfs3RequestGetAttr> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    Ok((i, Nfs3RequestGetAttr { handle }))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestAccess<'a> {
     pub handle: Nfs3Handle<'a>,
     pub check_access: u32,
 }
 
-named!(pub parse_nfs3_request_access<Nfs3RequestAccess>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  check_access: be_u32
-        >> (
-            Nfs3RequestAccess {
-                handle:handle,
-                check_access:check_access,
-            }
-        ))
-);
+pub fn parse_nfs3_request_access(i: &[u8]) -> IResult<&[u8], Nfs3RequestAccess> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, check_access) = be_u32(i)?;
+    let req = Nfs3RequestAccess {
+        handle,
+        check_access,
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestCommit<'a> {
     pub handle: Nfs3Handle<'a>,
 }
 
-named!(pub parse_nfs3_request_commit<Nfs3RequestCommit>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  _offset: be_u64
-        >>  _count: be_u32
-        >> (
-            Nfs3RequestCommit {
-                handle
-            }
-        ))
-);
+pub fn parse_nfs3_request_commit(i: &[u8]) -> IResult<&[u8], Nfs3RequestCommit> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, _offset) = be_u64(i)?;
+    let (i, _count) = be_u32(i)?;
+    Ok((i, Nfs3RequestCommit { handle }))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestRead<'a> {
     pub handle: Nfs3Handle<'a>,
     pub offset: u64,
 }
 
-named!(pub parse_nfs3_request_read<Nfs3RequestRead>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  offset: be_u64
-        >>  _count: be_u32
-        >> (
-            Nfs3RequestRead {
-                handle,
-                offset
-            }
-        ))
-);
+pub fn parse_nfs3_request_read(i: &[u8]) -> IResult<&[u8], Nfs3RequestRead> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, offset) = be_u64(i)?;
+    let (i, _count) = be_u32(i)?;
+    Ok((i, Nfs3RequestRead { handle, offset }))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestLookup<'a> {
     pub handle: Nfs3Handle<'a>,
 
     pub name_vec: Vec<u8>,
 }
 
-named!(pub parse_nfs3_request_lookup<Nfs3RequestLookup>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  name_len: be_u32
-        >>  name_contents: take!(name_len)
-        >>  _name_padding: rest
-        >> (
-            Nfs3RequestLookup {
-                handle,
-                name_vec:name_contents.to_vec(),
-            }
-        ))
-);
-
+pub fn parse_nfs3_request_lookup(i: &[u8]) -> IResult<&[u8], Nfs3RequestLookup> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, name_contents) = length_data(be_u32)(i)?;
+    let (i, _name_padding) = rest(i)?;
+    let req = Nfs3RequestLookup {
+        handle,
+        name_vec: name_contents.to_vec(),
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3ResponseReaddirplusEntryC<'a> {
     pub name_vec: Vec<u8>,
     pub handle: Option<Nfs3Handle<'a>>,
 }
 
-named!(pub parse_nfs3_response_readdirplus_entry<Nfs3ResponseReaddirplusEntryC>,
-    do_parse!(
-           _file_id: be_u64
-        >> name_len: be_u32
-        >> name_content: take!(name_len)
-        >> _fill_bytes: cond!(name_len % 4 != 0, take!(4 - name_len % 4))
-        >> _cookie: take!(8)
-        >> attr_value_follows: be_u32
-        >> _attr: cond!(attr_value_follows==1, take!(84))
-        >> handle_value_follows: be_u32
-        >> handle: cond!(handle_value_follows==1, parse_nfs3_handle)
-        >> (
-                Nfs3ResponseReaddirplusEntryC {
-                    name_vec:name_content.to_vec(),
-                    handle,
-                }
-           )
-        )
-);
+pub fn parse_nfs3_response_readdirplus_entry(
+    i: &[u8],
+) -> IResult<&[u8], Nfs3ResponseReaddirplusEntryC> {
+    let (i, _file_id) = be_u64(i)?;
+    let (i, name_len) = be_u32(i)?;
+    let (i, name_contents) = take(name_len as usize)(i)?;
+    let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
+    let (i, _cookie) = take(8_usize)(i)?;
+    let (i, attr_value_follows) = be_u32(i)?;
+    let (i, _attr) = cond(attr_value_follows == 1, take(84_usize))(i)?;
+    let (i, handle_value_follows) = be_u32(i)?;
+    let (i, handle) = cond(handle_value_follows == 1, parse_nfs3_handle)(i)?;
+    let resp = Nfs3ResponseReaddirplusEntryC {
+        name_vec: name_contents.to_vec(),
+        handle,
+    };
+    Ok((i, resp))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3ResponseReaddirplusEntry<'a> {
     pub entry: Option<Nfs3ResponseReaddirplusEntryC<'a>>,
 }
 
-named!(pub parse_nfs3_response_readdirplus_entry_cond<Nfs3ResponseReaddirplusEntry>,
-    do_parse!(
-           value_follows: be_u32
-        >> entry: cond!(value_follows==1, parse_nfs3_response_readdirplus_entry)
-        >> (
-            Nfs3ResponseReaddirplusEntry {
-                entry
-            }
-           ))
-);
+pub fn parse_nfs3_response_readdirplus_entry_cond(
+    i: &[u8],
+) -> IResult<&[u8], Nfs3ResponseReaddirplusEntry> {
+    let (i, value_follows) = be_u32(i)?;
+    let (i, entry) = cond(value_follows == 1, parse_nfs3_response_readdirplus_entry)(i)?;
+    Ok((i, Nfs3ResponseReaddirplusEntry { entry }))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3ResponseReaddirplus<'a> {
     pub status: u32,
-    pub data: &'a[u8],
+    pub data: &'a [u8],
 }
 
-named!(pub parse_nfs3_response_readdirplus<Nfs3ResponseReaddirplus>,
-    do_parse!(
-        status: be_u32
-        >> dir_attr_follows: be_u32
-        >> _dir_attr: cond!(dir_attr_follows == 1, take!(84))
-        >> _verifier: take!(8)
-        >> data: rest
-
-        >> ( Nfs3ResponseReaddirplus {
-                status,
-                data
-        } ))
-);
+pub fn parse_nfs3_response_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3ResponseReaddirplus> {
+    let (i, status) = be_u32(i)?;
+    let (i, dir_attr_follows) = be_u32(i)?;
+    let (i, _dir_attr) = cond(dir_attr_follows == 1, take(84_usize))(i)?;
+    let (i, data) = rest(i)?;
+    let resp = Nfs3ResponseReaddirplus { status, data };
+    Ok((i, resp))
+}
 
-pub(crate) fn many0_nfs3_response_readdirplus_entries<'a>(input: &'a [u8]) -> IResult<&'a[u8], Vec<Nfs3ResponseReaddirplusEntry<'a>>> {
-    many0!(input, complete!(parse_nfs3_response_readdirplus_entry_cond))
+pub(crate) fn many0_nfs3_response_readdirplus_entries<'a>(
+    input: &'a [u8],
+) -> IResult<&'a [u8], Vec<Nfs3ResponseReaddirplusEntry<'a>>> {
+    many0(complete(parse_nfs3_response_readdirplus_entry_cond))(input)
 }
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestReaddirplus<'a> {
     pub handle: Nfs3Handle<'a>,
 
     pub cookie: u32,
-    pub verifier: &'a[u8],
+    pub verifier: &'a [u8],
     pub dircount: u32,
     pub maxcount: u32,
 }
 
-named!(pub parse_nfs3_request_readdirplus<Nfs3RequestReaddirplus>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  cookie: be_u32
-        >>  verifier: take!(8)
-        >>  dircount: be_u32
-        >>  maxcount: be_u32
-        >> (
-            Nfs3RequestReaddirplus {
-                handle:handle,
-                cookie:cookie,
-                verifier:verifier,
-                dircount:dircount,
-                maxcount:maxcount,
-            }
-        ))
-);
+pub fn parse_nfs3_request_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3RequestReaddirplus> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, cookie) = be_u32(i)?;
+    let (i, verifier) = take(8_usize)(i)?;
+    let (i, dircount) = be_u32(i)?;
+    let (i, maxcount) = be_u32(i)?;
+    let req = Nfs3RequestReaddirplus {
+        handle,
+        cookie,
+        verifier,
+        dircount,
+        maxcount,
+    };
+    Ok((i, req))
+}
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct Nfs3RequestWrite<'a> {
     pub handle: Nfs3Handle<'a>,
 
@@ -388,28 +335,26 @@ pub struct Nfs3RequestWrite<'a> {
     pub count: u32,
     pub stable: u32,
     pub file_len: u32,
-    pub file_data: &'a[u8],
-}
-
-named!(pub parse_nfs3_request_write<Nfs3RequestWrite>,
-    do_parse!(
-            handle: parse_nfs3_handle
-        >>  offset: be_u64
-        >>  count: be_u32
-        >>  stable: be_u32
-        >>  file_len: be_u32
-        >>  file_data: rest // likely partial
-        >> (
-            Nfs3RequestWrite {
-                handle:handle,
-                offset:offset,
-                count:count,
-                stable:stable,
-                file_len:file_len,
-                file_data:file_data,
-            }
-        ))
-);
+    pub file_data: &'a [u8],
+}
+
+pub fn parse_nfs3_request_write(i: &[u8]) -> IResult<&[u8], Nfs3RequestWrite> {
+    let (i, handle) = parse_nfs3_handle(i)?;
+    let (i, offset) = be_u64(i)?;
+    let (i, count) = be_u32(i)?;
+    let (i, stable) = be_u32(i)?;
+    let (i, file_len) = be_u32(i)?;
+    let (i, file_data) = rest(i)?;
+    let req = Nfs3RequestWrite {
+        handle,
+        offset,
+        count,
+        stable,
+        file_len,
+        file_data,
+    };
+    Ok((i, req))
+}
 /*
 #[derive(Debug,PartialEq)]
 pub struct Nfs3ReplyRead<'a> {
@@ -422,24 +367,22 @@ pub struct Nfs3ReplyRead<'a> {
     pub data: &'a[u8], // likely partial
 }
 */
-named!(pub parse_nfs3_reply_read<NfsReplyRead>,
-    do_parse!(
-            status: be_u32
-        >>  attr_follows: be_u32
-        >>  attr_blob: take!(84) // fixed size?
-        >>  count: be_u32
-        >>  eof: be_u32
-        >>  data_len: be_u32
-        >>  data_contents: rest
-        >> (
-            NfsReplyRead {
-                status:status,
-                attr_follows:attr_follows,
-                attr_blob:attr_blob,
-                count:count,
-                eof:eof != 0,
-                data_len:data_len,
-                data:data_contents,
-            }
-        ))
-);
+pub fn parse_nfs3_reply_read(i: &[u8]) -> IResult<&[u8], NfsReplyRead> {
+    let (i, status) = be_u32(i)?;
+    let (i, attr_follows) = be_u32(i)?;
+    let (i, attr_blob) = take(84_usize)(i)?; // fixed size?
+    let (i, count) = be_u32(i)?;
+    let (i, eof) = be_u32(i)?;
+    let (i, data_len) = be_u32(i)?;
+    let (i, data) = rest(i)?;
+    let reply = NfsReplyRead {
+        status,
+        attr_follows,
+        attr_blob,
+        count,
+        eof: eof != 0,
+        data_len,
+        data,
+    };
+    Ok((i, reply))
+}
index aec2ef8988dfa56d26ec315d9d044c20c822817e..95924df98a89b17ca5842bf30ab22367084ae6e2 100644 (file)
 
 // written by Victor Julien
 
-use nom;
+use nom::bytes::streaming::take;
 use nom::number::streaming::be_u32;
+use nom7::Err;
 
 use crate::core::*;
 use crate::nfs::nfs::*;
-use crate::nfs::types::*;
-use crate::nfs::rpc_records::*;
-use crate::nfs::nfs_records::*;
 use crate::nfs::nfs4_records::*;
+use crate::nfs::nfs_records::*;
+use crate::nfs::rpc_records::*;
+use crate::nfs::types::*;
 
 use crate::kerberos::{parse_kerberos5_request, Kerberos5Ticket, SecBlobError};
 
-named!(parse_req_gssapi<&[u8], Kerberos5Ticket, SecBlobError>,
-   do_parse!(
-        len: be_u32
-    >>  ap: flat_map!(take!(len), parse_kerberos5_request)
-    >> ( ap )
-));
+// use the old nom type until both SMB and NFS are migrated to nom 7
+fn parse_req_gssapi(i: &[u8]) -> nom::IResult<&[u8], Kerberos5Ticket, SecBlobError> {
+    let (i, len) = be_u32(i)?;
+    let (i, buf) = take(len as usize)(i)?;
+    let (_, ap) = parse_kerberos5_request(buf)?;
+    Ok((i, ap))
+}
 
 impl NFSState {
     /* normal write: PUTFH (file handle), WRITE (write opts/data). File handle
      * is not part of the write record itself so we pass it in here. */
-    fn write_v4<'b>(&mut self, r: &RpcPacket<'b>, w: &Nfs4RequestWrite<'b>, fh: &'b[u8])
-    {
+    fn write_v4<'b>(&mut self, r: &RpcPacket<'b>, w: &Nfs4RequestWrite<'b>, fh: &'b [u8]) {
         // for now assume that stable FILE_SYNC flags means a single chunk
         let is_last = if w.stable == 2 { true } else { false };
         SCLogDebug!("is_last {}", is_last);
@@ -63,9 +64,18 @@ impl NFSState {
         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,
-                            &file_name, w.data, w.offset,
-                            w.write_len, fill_bytes as u8, is_last, &r.hdr.xid);
+                    filetracker_newchunk(
+                        &mut tdf.file_tracker,
+                        files,
+                        flags,
+                        &file_name,
+                        w.data,
+                        w.offset,
+                        w.write_len,
+                        fill_bytes as u8,
+                        is_last,
+                        &r.hdr.xid,
+                    );
                     tdf.chunk_count += 1;
                     if is_last {
                         tdf.file_last_xid = r.hdr.xid;
@@ -74,15 +84,24 @@ impl NFSState {
                     }
                 }
                 true
-            },
+            }
             None => false,
         };
         if !found {
             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.data, w.offset,
-                        w.write_len, fill_bytes as u8, is_last, &r.hdr.xid);
+                filetracker_newchunk(
+                    &mut tdf.file_tracker,
+                    files,
+                    flags,
+                    &file_name,
+                    w.data,
+                    w.offset,
+                    w.write_len,
+                    fill_bytes as u8,
+                    is_last,
+                    &r.hdr.xid,
+                );
                 tx.procedure = NFSPROC4_WRITE;
                 tx.xid = r.hdr.xid;
                 tx.is_first = true;
@@ -100,17 +119,16 @@ impl NFSState {
         self.ts_chunk_left = w.write_len as u32 - file_data_len as u32;
     }
 
-    fn close_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b[u8])
-    {
+    fn close_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b [u8]) {
         self.commit_v4(r, fh)
     }
 
-    fn commit_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b[u8])
-    {
+    fn commit_v4<'b>(&mut self, r: &RpcPacket<'b>, fh: &'b [u8]) {
         SCLogDebug!("COMMIT, closing shop");
 
         let file_handle = fh.to_vec();
-        if let Some((tx, files, flags)) = self.get_file_tx_by_handle(&file_handle, Direction::ToServer) {
+        if let Some((tx, files, flags)) = self.get_file_tx_by_handle(&file_handle, Direction::ToServer)
+        {
             if let Some(NFSTransactionTypeData::FILE(ref mut tdf)) = tx.type_data {
                 tdf.file_tracker.close(files, flags);
                 tdf.file_last_xid = r.hdr.xid;
@@ -121,10 +139,10 @@ impl NFSState {
         }
     }
 
-    fn new_tx_v4<'b>(&mut self, r: &RpcPacket<'b>,
-            xidmap: &NFSRequestXidMap, procedure: u32,
-            _aux_opcodes: &Vec<u32>)
-    {
+    fn new_tx_v4<'b>(
+        &mut self, r: &RpcPacket<'b>, xidmap: &NFSRequestXidMap, procedure: u32,
+        _aux_opcodes: &Vec<u32>,
+    {
         let mut tx = self.new_tx();
         tx.xid = r.hdr.xid;
         tx.procedure = procedure;
@@ -139,24 +157,28 @@ impl NFSState {
                 tx.request_machine_name = u.machine_name_buf.to_vec();
                 tx.request_uid = u.uid;
                 tx.request_gid = u.gid;
-            },
-            _ => { },
+            }
+            _ => {}
         }
-        SCLogDebug!("NFSv4: TX created: ID {} XID {} PROCEDURE {}",
-                tx.id, tx.xid, tx.procedure);
+        SCLogDebug!(
+            "NFSv4: TX created: ID {} XID {} PROCEDURE {}",
+            tx.id,
+            tx.xid,
+            tx.procedure
+        );
         self.transactions.push(tx);
     }
 
     /* A normal READ request looks like: PUTFH (file handle) READ (read opts).
      * We need the file handle for the READ.
      */
-    fn compound_request<'b>(&mut self, r: &RpcPacket<'b>,
-            cr: &Nfs4RequestCompoundRecord<'b>,
-            xidmap: &mut NFSRequestXidMap)
-    {
-        let mut last_putfh : Option<&'b[u8]> = None;
-        let mut main_opcode : u32 = 0;
-        let mut aux_opcodes : Vec<u32> = Vec::new();
+    fn compound_request<'b>(
+        &mut self, r: &RpcPacket<'b>, cr: &Nfs4RequestCompoundRecord<'b>,
+        xidmap: &mut NFSRequestXidMap,
+    {
+        let mut last_putfh: Option<&'b [u8]> = None;
+        let mut main_opcode: u32 = 0;
+        let mut aux_opcodes: Vec<u32> = Vec::new();
 
         for c in &cr.commands {
             SCLogDebug!("c {:?}", c);
@@ -213,12 +235,14 @@ impl NFSState {
                     main_opcode = NFSPROC4_REMOVE;
                 }
                 &Nfs4RequestContent::SetClientId(ref _rd) => {
-                    SCLogDebug!("SETCLIENTIDv4: client id {} r_netid {} r_addr {}",
-                            String::from_utf8_lossy(&_rd.client_id),
-                            String::from_utf8_lossy(&_rd.r_netid),
-                            String::from_utf8_lossy(&_rd.r_addr));
+                    SCLogDebug!(
+                        "SETCLIENTIDv4: client id {} r_netid {} r_addr {}",
+                        String::from_utf8_lossy(&_rd.client_id),
+                        String::from_utf8_lossy(&_rd.r_netid),
+                        String::from_utf8_lossy(&_rd.r_addr)
+                    );
                 }
-                &_ => { },
+                &_ => {}
             }
         }
 
@@ -229,8 +253,13 @@ impl NFSState {
 
     /// complete request record
     pub fn process_request_record_v4<'b>(&mut self, r: &RpcPacket<'b>) {
-        SCLogDebug!("NFSv4 REQUEST {} procedure {} ({}) blob size {}",
-                r.hdr.xid, r.procedure, self.requestmap.len(), r.prog_data.len());
+        SCLogDebug!(
+            "NFSv4 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);
 
@@ -245,7 +274,7 @@ impl NFSState {
             let mut data = r.prog_data;
 
             if let RpcRequestCreds::GssApi(ref creds) = r.creds {
-                if creds.procedure == 0  && creds.service == 2 {
+                if creds.procedure == 0 && creds.service == 2 {
                     SCLogDebug!("GSS INTEGRITIY: {:?}", creds);
                     match parse_rpc_gssapi_integrity(r.prog_data) {
                         Ok((_rem, rec)) => {
@@ -254,18 +283,20 @@ impl NFSState {
                             // store proc and serv for the reply
                             xidmap.gssapi_proc = creds.procedure;
                             xidmap.gssapi_service = creds.service;
-                        },
-                        Err(nom::Err::Incomplete(_n)) => {
+                        }
+                        Err(Err::Incomplete(_n)) => {
                             SCLogDebug!("NFSPROC4_COMPOUND/GSS INTEGRITIY: INCOMPLETE {:?}", _n);
                             self.set_event(NFSEvent::MalformedData);
                             return;
-                        },
-                        Err(nom::Err::Error(_e)) |
-                        Err(nom::Err::Failure(_e)) => {
-                            SCLogDebug!("NFSPROC4_COMPOUND/GSS INTEGRITIY: Parsing failed: {:?}", _e);
+                        }
+                        Err(Err::Error(_e)) | Err(Err::Failure(_e)) => {
+                            SCLogDebug!(
+                                "NFSPROC4_COMPOUND/GSS INTEGRITIY: Parsing failed: {:?}",
+                                _e
+                            );
                             self.set_event(NFSEvent::MalformedData);
                             return;
-                        },
+                        }
                     }
                 }
             }
@@ -274,29 +305,28 @@ impl NFSState {
                 Ok((_, rd)) => {
                     SCLogDebug!("NFSPROC4_COMPOUND: {:?}", rd);
                     self.compound_request(r, &rd, &mut xidmap);
-                },
-                Err(nom::Err::Incomplete(_n)) => {
+                }
+                Err(Err::Incomplete(_n)) => {
                     SCLogDebug!("NFSPROC4_COMPOUND: INCOMPLETE {:?}", _n);
                     self.set_event(NFSEvent::MalformedData);
-                },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                }
+                Err(Err::Error(_e)) | Err(Err::Failure(_e)) => {
                     SCLogDebug!("NFSPROC4_COMPOUND: Parsing failed: {:?}", _e);
                     self.set_event(NFSEvent::MalformedData);
-                },
+                }
             };
         }
 
         self.requestmap.insert(r.hdr.xid, xidmap);
     }
 
-    fn compound_response<'b>(&mut self, r: &RpcReplyPacket<'b>,
-            cr: &Nfs4ResponseCompoundRecord<'b>,
-            xidmap: &mut NFSRequestXidMap)
-    {
+    fn compound_response<'b>(
+        &mut self, r: &RpcReplyPacket<'b>, cr: &Nfs4ResponseCompoundRecord<'b>,
+        xidmap: &mut NFSRequestXidMap,
+    {
         let mut insert_filename_with_getfh = false;
-        let mut main_opcode_status : u32 = 0;
-        let mut main_opcode_status_set : bool = false;
+        let mut main_opcode_status: u32 = 0;
+        let mut main_opcode_status_set: bool = false;
 
         for c in &cr.commands {
             SCLogDebug!("c {:?}", c);
@@ -310,22 +340,26 @@ impl NFSState {
                                 SCLogDebug!("READDIRv4: dir {}", String::from_utf8_lossy(&_d.name));
                             }
                         }
-
                     }
                 }
                 &Nfs4ResponseContent::Remove(s) => {
                     SCLogDebug!("REMOVE4: status {}", s);
                     main_opcode_status = s;
                     main_opcode_status_set = true;
-                },
+                }
                 &Nfs4ResponseContent::Create(s) => {
                     SCLogDebug!("CREATE4: status {}", s);
                     main_opcode_status = s;
                     main_opcode_status_set = true;
-                },
+                }
                 &Nfs4ResponseContent::Read(s, ref rd) => {
                     if let &Some(ref rd) = rd {
-                        SCLogDebug!("READ4: xidmap {:?} status {} data {}", xidmap, s, rd.data.len());
+                        SCLogDebug!(
+                            "READ4: xidmap {:?} status {} data {}",
+                            xidmap,
+                            s,
+                            rd.data.len()
+                        );
                         // convert record to generic read reply
                         let reply = NfsReplyRead {
                             status: s,
@@ -338,28 +372,28 @@ impl NFSState {
                         };
                         self.process_read_record(r, &reply, Some(xidmap));
                     }
-                },
+                }
                 &Nfs4ResponseContent::Open(_s, ref rd) => {
                     if let &Some(ref _rd) = rd {
                         SCLogDebug!("OPENv4: status {} opendata {:?}", _s, _rd);
                         insert_filename_with_getfh = true;
                     }
-                },
+                }
                 &Nfs4ResponseContent::GetFH(_s, ref rd) => {
                     if let &Some(ref rd) = rd {
                         if insert_filename_with_getfh {
-                            self.namemap.insert(rd.value.to_vec(),
-                                    xidmap.file_name.to_vec());
+                            self.namemap
+                                .insert(rd.value.to_vec(), xidmap.file_name.to_vec());
                         }
                     }
-                },
+                }
                 &Nfs4ResponseContent::PutRootFH(s) => {
                     if s == NFS4_OK && xidmap.file_name.len() == 0 {
                         xidmap.file_name = b"<mount_root>".to_vec();
                         SCLogDebug!("filename {:?}", xidmap.file_name);
                     }
-                },
-                &_ => { },
+                }
+                &_ => {}
             }
         }
 
@@ -369,45 +403,43 @@ impl NFSState {
         }
     }
 
-    pub fn process_reply_record_v4<'b>(&mut self, r: &RpcReplyPacket<'b>,
-            xidmap: &mut NFSRequestXidMap) {
+    pub fn process_reply_record_v4<'b>(
+        &mut self, r: &RpcReplyPacket<'b>, xidmap: &mut NFSRequestXidMap,
+    ) {
         if xidmap.procedure == NFSPROC4_COMPOUND {
             let mut data = r.prog_data;
 
             if xidmap.gssapi_proc == 0 && xidmap.gssapi_service == 2 {
-
                 SCLogDebug!("GSS INTEGRITIY as set by call: {:?}", xidmap);
                 match parse_rpc_gssapi_integrity(r.prog_data) {
                     Ok((_rem, rec)) => {
                         SCLogDebug!("GSS INTEGRITIY wrapper: {:?}", rec);
                         data = rec.data;
-                    },
-                    Err(nom::Err::Incomplete(_n)) => {
+                    }
+                    Err(Err::Incomplete(_n)) => {
                         SCLogDebug!("NFSPROC4_COMPOUND/GSS INTEGRITIY: INCOMPLETE {:?}", _n);
                         self.set_event(NFSEvent::MalformedData);
                         return;
-                    },
-                    Err(nom::Err::Error(_e)) |
-                    Err(nom::Err::Failure(_e)) => {
+                    }
+                    Err(Err::Error(_e)) | Err(Err::Failure(_e)) => {
                         SCLogDebug!("NFSPROC4_COMPOUND/GSS INTEGRITIY: Parsing failed: {:?}", _e);
                         self.set_event(NFSEvent::MalformedData);
                         return;
-                    },
+                    }
                 }
             }
             match parse_nfs4_response_compound(data) {
                 Ok((_, rd)) => {
                     SCLogDebug!("COMPOUNDv4: {:?}", rd);
                     self.compound_response(r, &rd, xidmap);
-                },
-                Err(nom::Err::Incomplete(_)) => {
+                }
+                Err(Err::Incomplete(_)) => {
                     self.set_event(NFSEvent::MalformedData);
-                },
-                Err(nom::Err::Error(_e)) |
-                Err(nom::Err::Failure(_e)) => {
+                }
+                Err(Err::Error(_e)) | Err(Err::Failure(_e)) => {
                     SCLogDebug!("Parsing failed: {:?}", _e);
                     self.set_event(NFSEvent::MalformedData);
-                },
+                }
             };
         }
     }
index e4f391f1e8eadea0361da96b861e1ac7d37efa44..94248db01fe39c71d1d090ebc975e2f119522457 100644 (file)
  */
 
 //! Nom parsers for NFSv4 records
-use nom::number::streaming::{be_u32, be_u64};
+use nom7::bytes::streaming::{tag, take};
+use nom7::combinator::{complete, cond, map, peek};
+use nom7::error::{make_error, ErrorKind};
+use nom7::multi::{count, many_till};
+use nom7::number::streaming::{be_u32, be_u64};
+use nom7::{Err, IResult};
 
 use crate::nfs::types::*;
 
@@ -53,35 +58,34 @@ pub struct Nfs4Attr {
     attr_mask: u64,
 }
 
-named!(nfs4_parse_attr_fields<u32>,
-    do_parse!(
-        len: be_u32
-    >>  take!(len)
-    >> (len)
-));
-
-named!(nfs4_parse_attrs<Nfs4Attr>,
-    do_parse!(
-        attr_cnt: be_u32
-    >>  attr_mask1: be_u32
-    >>  attr_mask2: cond!(attr_cnt >= 2, be_u32)
-    >>  cond!(attr_cnt == 3, be_u32)
-    >>  nfs4_parse_attr_fields
-    >> ( Nfs4Attr {
-            attr_mask: ((attr_mask1 as u64) << 32) | attr_mask2.unwrap_or(0) as u64,
-        } )
-));
-
-named!(nfs4_parse_attrbits<Nfs4Attr>,
-    do_parse!(
-        attr_cnt: be_u32
-    >>  attr_mask1: be_u32
-    >>  attr_mask2: cond!(attr_cnt >= 2, be_u32)
-    >>  cond!(attr_cnt == 3, be_u32)
-    >> ( Nfs4Attr {
-            attr_mask: ((attr_mask1 as u64) << 32) | attr_mask2.unwrap_or(0) as u64,
-        } )
-));
+fn nfs4_parse_attr_fields(i: &[u8]) -> IResult<&[u8], u32> {
+    let (i, len) = be_u32(i)?;
+    let (i, _) = take(len as usize)(i)?;
+    Ok((i, len))
+}
+
+fn nfs4_parse_attrs(i: &[u8]) -> IResult<&[u8], Nfs4Attr> {
+    let (i, attr_cnt) = be_u32(i)?;
+    let (i, attr_mask1) = be_u32(i)?;
+    let (i, attr_mask2) = cond(attr_cnt >= 2, be_u32)(i)?;
+    let (i, _) = cond(attr_cnt == 3, be_u32)(i)?;
+    let (i, _) = nfs4_parse_attr_fields(i)?;
+    let attr = Nfs4Attr {
+        attr_mask: ((attr_mask1 as u64) << 32) | attr_mask2.unwrap_or(0) as u64,
+    };
+    Ok((i, attr))
+}
+
+fn nfs4_parse_attrbits(i: &[u8]) -> IResult<&[u8], Nfs4Attr> {
+    let (i, attr_cnt) = be_u32(i)?;
+    let (i, attr_mask1) = be_u32(i)?;
+    let (i, attr_mask2) = cond(attr_cnt >= 2, be_u32)(i)?;
+    let (i, _) = cond(attr_cnt == 3, be_u32)(i)?;
+    let attr = Nfs4Attr {
+        attr_mask: ((attr_mask1 as u64) << 32) | attr_mask2.unwrap_or(0) as u64,
+    };
+    Ok((i, attr))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4StateId<'a> {
@@ -89,16 +93,12 @@ pub struct Nfs4StateId<'a> {
     pub data: &'a[u8],
 }
 
-named!(nfs4_parse_stateid<Nfs4StateId>,
-    do_parse!(
-            seqid: be_u32
-        >>  data: take!(12)
-        >> ( Nfs4StateId {
-                seqid: seqid,
-                data: data,
-            })
-        )
-);
+fn nfs4_parse_stateid(i: &[u8]) -> IResult<&[u8], Nfs4StateId> {
+    let (i, seqid) = be_u32(i)?;
+    let (i, data) = take(12_usize)(i)?;
+    let state = Nfs4StateId { seqid, data };
+    Ok((i, state))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4Handle<'a> {
@@ -106,29 +106,23 @@ pub struct Nfs4Handle<'a> {
     pub value: &'a[u8],
 }
 
-named!(nfs4_parse_handle<Nfs4Handle>,
-    do_parse!(
-            obj_len: be_u32
-        >>  obj: take!(obj_len)
-        >> ( Nfs4Handle {
-                len: obj_len,
-                value: obj,
-            })
-));
-
-named!(nfs4_parse_nfsstring<&[u8]>,
-    do_parse!(
-            len: be_u32
-        >>  data: take!(len)
-        >>  _fill_bytes: cond!(len % 4 != 0, take!(4 - len % 4))
-        >> ( data )
-));
-
-named!(nfs4_req_putfh<Nfs4RequestContent>,
-    do_parse!(
-            h: nfs4_parse_handle
-        >> ( Nfs4RequestContent::PutFH(h) )
-));
+fn nfs4_parse_handle(i: &[u8]) -> IResult<&[u8], Nfs4Handle> {
+    let (i, len) = be_u32(i)?;
+    let (i, value) = take(len as usize)(i)?;
+    let handle = Nfs4Handle { len, value };
+    Ok((i, handle))
+}
+
+fn nfs4_parse_nfsstring(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    let (i, len) = be_u32(i)?;
+    let (i, data) = take(len as usize)(i)?;
+    let (i, _fill_bytes) = cond(len % 4 != 0, take(4 - (len % 4)))(i)?;
+    Ok((i, data))
+}
+
+fn nfs4_req_putfh(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(nfs4_parse_handle, Nfs4RequestContent::PutFH)(i)
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestSetClientId<'a> {
@@ -137,27 +131,26 @@ pub struct Nfs4RequestSetClientId<'a> {
     pub r_addr: &'a[u8],
 }
 
-named!(nfs4_req_setclientid<Nfs4RequestContent>,
-    do_parse!(
-            _client_verifier: take!(8)
-        >>  client_id: nfs4_parse_nfsstring
-        >>  _cb_program: be_u32
-        >>  r_netid: nfs4_parse_nfsstring
-        >>  r_addr: nfs4_parse_nfsstring
-        >>  _cb_id: be_u32
-        >> (Nfs4RequestContent::SetClientId(Nfs4RequestSetClientId {
-                client_id,
-                r_netid,
-                r_addr
-            }))
-));
-
-named!(nfs4_req_setclientid_confirm<Nfs4RequestContent>,
-    do_parse!(
-            _client_id: take!(8)
-        >>  _verifier: take!(8)
-        >> (Nfs4RequestContent::SetClientIdConfirm)
-));
+fn nfs4_req_setclientid(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _client_verifier) = take(8_usize)(i)?;
+    let (i, client_id) = nfs4_parse_nfsstring(i)?;
+    let (i, _cb_program) = be_u32(i)?;
+    let (i, r_netid) = nfs4_parse_nfsstring(i)?;
+    let (i, r_addr) = nfs4_parse_nfsstring(i)?;
+    let (i, _cb_id) = be_u32(i)?;
+    let req = Nfs4RequestContent::SetClientId(Nfs4RequestSetClientId {
+        client_id,
+        r_netid,
+        r_addr
+    });
+    Ok((i, req))
+}
+
+fn nfs4_req_setclientid_confirm(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _client_id) = take(8_usize)(i)?;
+    let (i, _verifier) = take(8_usize)(i)?;
+    Ok((i, Nfs4RequestContent::SetClientIdConfirm))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestCreate<'a> {
@@ -166,19 +159,18 @@ pub struct Nfs4RequestCreate<'a> {
     pub link_content: &'a[u8],
 }
 
-named!(nfs4_req_create<Nfs4RequestContent>,
-    do_parse!(
-            ftype4: be_u32
-        >>  link_content: cond!(ftype4 == 5, nfs4_parse_nfsstring)
-        >>  filename: nfs4_parse_nfsstring
-        >>  _attrs: nfs4_parse_attrs
-        >> ( Nfs4RequestContent::Create(Nfs4RequestCreate {
-                ftype4: ftype4,
-                filename: filename,
-                link_content: link_content.unwrap_or(&[]),
-            })
-        ))
-);
+fn nfs4_req_create(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, ftype4) = be_u32(i)?;
+    let (i, link_content) = cond(ftype4 == 5, nfs4_parse_nfsstring)(i)?;
+    let (i, filename) = nfs4_parse_nfsstring(i)?;
+    let (i, _attrs) = nfs4_parse_attrs(i)?;
+    let req = Nfs4RequestContent::Create(Nfs4RequestCreate {
+        ftype4,
+        filename,
+        link_content: link_content.unwrap_or(&[]),
+    });
+    Ok((i, req))
+}
 
 #[derive(Debug,PartialEq)]
 pub enum Nfs4OpenRequestContent<'a> {
@@ -187,34 +179,29 @@ pub enum Nfs4OpenRequestContent<'a> {
     Guarded4(Nfs4Attr),
 }
 
-named!(nfs4_req_open_unchecked4<Nfs4OpenRequestContent>,
-    do_parse!(
-            attrs: nfs4_parse_attrs
-        >> ( Nfs4OpenRequestContent::Unchecked4(attrs) )
-));
+fn nfs4_req_open_unchecked4(i: &[u8]) -> IResult<&[u8], Nfs4OpenRequestContent> {
+    map(nfs4_parse_attrs, Nfs4OpenRequestContent::Unchecked4)(i)
+}
 
-named!(nfs4_req_open_guarded4<Nfs4OpenRequestContent>,
-    do_parse!(
-            attrs: nfs4_parse_attrs
-        >> ( Nfs4OpenRequestContent::Guarded4(attrs) )
-));
+fn nfs4_req_open_guarded4(i: &[u8]) -> IResult<&[u8], Nfs4OpenRequestContent> {
+    map(nfs4_parse_attrs, Nfs4OpenRequestContent::Guarded4)(i)
+}
 
-named!(nfs4_req_open_exclusive4<Nfs4OpenRequestContent>,
-    do_parse!(
-            ver: take!(8)
-        >> ( Nfs4OpenRequestContent::Exclusive4(ver) )
-));
+fn nfs4_req_open_exclusive4(i: &[u8]) -> IResult<&[u8], Nfs4OpenRequestContent> {
+    map(take(8_usize), Nfs4OpenRequestContent::Exclusive4)(i)
+}
 
 
-named!(nfs4_req_open_type<Nfs4OpenRequestContent>,
-    do_parse!(
-            mode: be_u32
-        >>  data: switch!(value!(mode),
-                0 => call!(nfs4_req_open_unchecked4)  |
-                1 => call!(nfs4_req_open_guarded4)    |
-                2 => call!(nfs4_req_open_exclusive4))
-        >> ( data )
-));
+fn nfs4_req_open_type(i: &[u8]) -> IResult<&[u8], Nfs4OpenRequestContent> {
+    let (i, mode) = be_u32(i)?;
+    let (i, data) = match mode {
+        0 => nfs4_req_open_unchecked4(i)?,
+        1 => nfs4_req_open_guarded4(i)?,
+        2 => nfs4_req_open_exclusive4(i)?,
+        _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
+    };
+    Ok((i, data))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestOpen<'a> {
@@ -223,36 +210,33 @@ pub struct Nfs4RequestOpen<'a> {
     pub open_data: Option<Nfs4OpenRequestContent<'a>>,
 }
 
-named!(nfs4_req_open<Nfs4RequestContent>,
-    do_parse!(
-            _seqid: be_u32
-        >>  _share_access: be_u32
-        >>  _share_deny: be_u32
-        >>  _client_id: be_u64
-        >>  owner_len: be_u32
-        >>  cond!(owner_len > 0, take!(owner_len))
-        >>  open_type: be_u32
-        >>  open_data: cond!(open_type == 1, nfs4_req_open_type)
-        >>  _claim_type: be_u32
-        >>  filename: nfs4_parse_nfsstring
-        >> ( Nfs4RequestContent::Open(Nfs4RequestOpen {
-                open_type,
-                filename,
-                open_data
-            })
-        ))
-);
-
-named!(nfs4_req_readdir<Nfs4RequestContent>,
-    do_parse!(
-            _cookie: be_u64
-        >>  _cookie_verf: be_u64
-        >>  _dir_cnt: be_u32
-        >>  _max_cnt: be_u32
-        >>  _attr: nfs4_parse_attrbits
-        >> ( Nfs4RequestContent::ReadDir )
-    )
-);
+fn nfs4_req_open(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _seq_id) = be_u32(i)?;
+    let (i, _share_access) = be_u32(i)?;
+    let (i, _share_deny) = be_u32(i)?;
+    let (i, _client_id) = be_u64(i)?;
+    let (i, owner_len) = be_u32(i)?;
+    let (i, _) = cond(owner_len > 0, take(owner_len as usize))(i)?;
+    let (i, open_type) = be_u32(i)?;
+    let (i, open_data) = cond(open_type == 1, nfs4_req_open_type)(i)?;
+    let (i, _claim_type) = be_u32(i)?;
+    let (i, filename) = nfs4_parse_nfsstring(i)?;
+    let req = Nfs4RequestContent::Open(Nfs4RequestOpen {
+        open_type,
+        filename,
+        open_data
+    });
+    Ok((i, req))
+}
+
+fn nfs4_req_readdir(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _cookie) = be_u64(i)?;
+    let (i, _cookie_verf) = be_u64(i)?;
+    let (i, _dir_cnt) = be_u32(i)?;
+    let (i, _max_cnt) = be_u32(i)?;
+    let (i, _attr) = nfs4_parse_attrbits(i)?;
+    Ok((i, Nfs4RequestContent::ReadDir))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestRename<'a> {
@@ -260,57 +244,46 @@ pub struct Nfs4RequestRename<'a> {
     pub newname: &'a[u8],
 }
 
-named!(nfs4_req_rename<Nfs4RequestContent>,
-    do_parse!(
-            oldname: nfs4_parse_nfsstring
-        >>  newname: nfs4_parse_nfsstring
-        >> ( Nfs4RequestContent::Rename(Nfs4RequestRename {
-                oldname,
-                newname
-            })
-        ))
-);
+fn nfs4_req_rename(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, oldname) = nfs4_parse_nfsstring(i)?;
+    let (i, newname) = nfs4_parse_nfsstring(i)?;
+    let req = Nfs4RequestContent::Rename(Nfs4RequestRename {
+        oldname,
+        newname
+    });
+    Ok((i, req))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestLookup<'a> {
     pub filename: &'a[u8],
 }
 
-named!(nfs4_req_lookup<Nfs4RequestContent>,
-    do_parse!(
-            filename: nfs4_parse_nfsstring
-        >> ( Nfs4RequestContent::Lookup(Nfs4RequestLookup {
-                filename
-            })
-        ))
-);
+fn nfs4_req_lookup(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(nfs4_parse_nfsstring, |filename| {
+        Nfs4RequestContent::Lookup(Nfs4RequestLookup { filename })
+    })(i)
+}
 
-named!(nfs4_req_remove<Nfs4RequestContent>,
-    do_parse!(
-            filename: nfs4_parse_nfsstring
-        >> ( Nfs4RequestContent::Remove(filename) )
-));
+fn nfs4_req_remove(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(nfs4_parse_nfsstring, Nfs4RequestContent::Remove)(i)
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestSetAttr<'a> {
     pub stateid: Nfs4StateId<'a>,
 }
 
-named!(nfs4_req_setattr<Nfs4RequestContent>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  _attrs: nfs4_parse_attrs
-        >> (Nfs4RequestContent::SetAttr(Nfs4RequestSetAttr {
-                stateid
-            }))
-));
+fn nfs4_req_setattr(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let (i, _attrs) = nfs4_parse_attrs(i)?;
+    let req = Nfs4RequestContent::SetAttr(Nfs4RequestSetAttr { stateid });
+    Ok((i, req))
+}
 
-named!(nfs4_req_getattr<Nfs4RequestContent>,
-    do_parse!(
-            attrs: nfs4_parse_attrbits
-        >> ( Nfs4RequestContent::GetAttr(attrs) )
-    )
-);
+fn nfs4_req_getattr(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(nfs4_parse_attrbits, Nfs4RequestContent::GetAttr)(i)
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestWrite<'a> {
@@ -321,22 +294,22 @@ pub struct Nfs4RequestWrite<'a> {
     pub data: &'a[u8],
 }
 
-named!(nfs4_req_write<Nfs4RequestContent>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  offset: be_u64
-        >>  stable: be_u32
-        >>  write_len: be_u32
-        >>  data: take!(write_len)
-        >>  _padding: cond!(write_len % 4 != 0, take!(4 - write_len % 4))
-        >> (Nfs4RequestContent::Write(Nfs4RequestWrite {
-                stateid: stateid,
-                offset: offset,
-                stable: stable,
-                write_len: write_len,
-                data: data,
-            }))
-));
+fn nfs4_req_write(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let (i, offset) = be_u64(i)?;
+    let (i, stable) = be_u32(i)?;
+    let (i, write_len) = be_u32(i)?;
+    let (i, data) = take(write_len as usize)(i)?;
+    let (i, _padding) = cond(write_len % 4 != 0, take(4 - (write_len % 4)))(i)?;
+    let req = Nfs4RequestContent::Write(Nfs4RequestWrite {
+        stateid,
+        offset,
+        stable,
+        write_len,
+        data,
+    });
+    Ok((i, req))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestRead<'a> {
@@ -345,78 +318,67 @@ pub struct Nfs4RequestRead<'a> {
     pub count: u32,
 }
 
-named!(nfs4_req_read<Nfs4RequestContent>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  offset: be_u64
-        >>  count: be_u32
-        >> ( Nfs4RequestContent::Read(Nfs4RequestRead {
-                stateid: stateid,
-                offset: offset,
-                count: count,
-            })
-        ))
-);
-
-named!(nfs4_req_close<Nfs4RequestContent>,
-    do_parse!(
-            _seqid: be_u32
-        >>  stateid: nfs4_parse_stateid
-        >> ( Nfs4RequestContent::Close(stateid) )
-));
+fn nfs4_req_read(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let (i, offset) = be_u64(i)?;
+    let (i, count) = be_u32(i)?;
+    let req = Nfs4RequestContent::Read(Nfs4RequestRead {
+        stateid,
+        offset,
+        count,
+    });
+    Ok((i, req))
+}
+
+fn nfs4_req_close(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _seq_id) = be_u32(i)?;
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    Ok((i, Nfs4RequestContent::Close(stateid)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestOpenConfirm<'a> {
     pub stateid: Nfs4StateId<'a>,
 }
 
-named!(nfs4_req_open_confirm<Nfs4RequestContent>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  _seqid: be_u32
-        >> ( Nfs4RequestContent::OpenConfirm(Nfs4RequestOpenConfirm {
-                stateid
-            })
-        ))
-);
-
-named!(nfs4_req_delegreturn<Nfs4RequestContent>,
-    do_parse!(
-            a: nfs4_parse_stateid
-        >> ( Nfs4RequestContent::DelegReturn(a) )
-    )
-);
-
-named!(nfs4_req_renew<Nfs4RequestContent>,
-    do_parse!(
-            a: be_u64
-        >> ( Nfs4RequestContent::Renew(a) )
-    )
-);
-
-named!(nfs4_req_getfh<Nfs4RequestContent>,
-    do_parse!( ( Nfs4RequestContent::GetFH ) ));
-
-named!(nfs4_req_savefh<Nfs4RequestContent>,
-    do_parse!( ( Nfs4RequestContent::SaveFH ) ));
-
-named!(nfs4_req_putrootfh<Nfs4RequestContent>,
-    do_parse!( ( Nfs4RequestContent::PutRootFH ) ));
-
-named!(nfs4_req_access<Nfs4RequestContent>,
-    do_parse!(
-            a: be_u32
-        >> ( Nfs4RequestContent::Access(a) )
-    )
-);
-
-named!(nfs4_req_commit<Nfs4RequestContent>,
-    do_parse!(
-            _offset: be_u64
-        >>  _count: be_u32
-        >> ( Nfs4RequestContent::Commit )
-    )
-);
+fn nfs4_req_open_confirm(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _seq_id) = be_u32(i)?;
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let req = Nfs4RequestContent::OpenConfirm(Nfs4RequestOpenConfirm {
+        stateid
+    });
+    Ok((i, req))
+}
+
+fn nfs4_req_delegreturn(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(nfs4_parse_stateid, Nfs4RequestContent::DelegReturn)(i)
+}
+
+fn nfs4_req_renew(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(be_u64, Nfs4RequestContent::Renew)(i)
+}
+
+fn nfs4_req_getfh(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    Ok((i, Nfs4RequestContent::GetFH))
+}
+
+fn nfs4_req_savefh(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    Ok((i, Nfs4RequestContent::SaveFH))
+}
+
+fn nfs4_req_putrootfh(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    Ok((i, Nfs4RequestContent::PutRootFH))
+}
+
+fn nfs4_req_access(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    map(be_u32, Nfs4RequestContent::Access)(i)
+}
+
+fn nfs4_req_commit(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _offset) = be_u64(i)?;
+    let (i, _count) = be_u32(i)?;
+    Ok((i, Nfs4RequestContent::Commit))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestExchangeId<'a> {
@@ -425,93 +387,86 @@ pub struct Nfs4RequestExchangeId<'a> {
     pub nii_name: &'a[u8],
 }
 
-named!(nfs4_req_exchangeid<Nfs4RequestContent>,
-    do_parse!(
-        _verifier: take!(8)
-    >>  eia_clientstring: nfs4_parse_nfsstring
-    >>  _eia_clientflags: be_u32
-    >>  _eia_state_protect: be_u32
-    >>  _eia_client_impl_id: be_u32
-    >>  nii_domain: nfs4_parse_nfsstring
-    >>  nii_name: nfs4_parse_nfsstring
-    >>  _nii_data_sec: be_u64
-    >>  _nii_data_nsec: be_u32
-    >> (Nfs4RequestContent::ExchangeId(
-            Nfs4RequestExchangeId {
-                client_string: eia_clientstring,
-                nii_domain,
-                nii_name
-            }
-        ))
-));
+fn nfs4_req_exchangeid(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, _verifier) = take(8_usize)(i)?;
+    let (i, eia_clientstring) = nfs4_parse_nfsstring(i)?;
+    let (i, _eia_clientflags) = be_u32(i)?;
+    let (i, _eia_state_protect) = be_u32(i)?;
+    let (i, _eia_client_impl_id) = be_u32(i)?;
+    let (i, nii_domain) = nfs4_parse_nfsstring(i)?;
+    let (i, nii_name) = nfs4_parse_nfsstring(i)?;
+    let (i, _nii_data_sec) = be_u64(i)?;
+    let (i, _nii_data_nsec) = be_u32(i)?;
+    let req = Nfs4RequestContent::ExchangeId(Nfs4RequestExchangeId {
+        client_string: eia_clientstring,
+        nii_domain,
+        nii_name
+    });
+    Ok((i, req))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestSequence<'a> {
     pub ssn_id: &'a[u8],
 }
 
-named!(nfs4_req_sequence<Nfs4RequestContent>,
-    do_parse!(
-        ssn_id: take!(16)
-    >>  _seq_id: be_u32
-    >>  _slot_id: be_u32
-    >>  _high_slot_id: be_u32
-    >>  _cache_this: be_u32
-    >> (Nfs4RequestContent::Sequence(
-            Nfs4RequestSequence {
-                ssn_id
-            }
-        ))
-));
-
-named!(parse_request_compound_command<Nfs4RequestContent>,
-    do_parse!(
-        cmd: be_u32
-    >>  cmd_data: switch!(value!(cmd),
-            NFSPROC4_PUTFH                  => call!(nfs4_req_putfh)                |
-            NFSPROC4_READ                   => call!(nfs4_req_read)                 |
-            NFSPROC4_WRITE                  => call!(nfs4_req_write)                |
-            NFSPROC4_GETFH                  => call!(nfs4_req_getfh)                |
-            NFSPROC4_SAVEFH                 => call!(nfs4_req_savefh)               |
-            NFSPROC4_OPEN                   => call!(nfs4_req_open)                 |
-            NFSPROC4_CLOSE                  => call!(nfs4_req_close)                |
-            NFSPROC4_LOOKUP                 => call!(nfs4_req_lookup)               |
-            NFSPROC4_ACCESS                 => call!(nfs4_req_access)               |
-            NFSPROC4_COMMIT                 => call!(nfs4_req_commit)               |
-            NFSPROC4_GETATTR                => call!(nfs4_req_getattr)              |
-            NFSPROC4_READDIR                => call!(nfs4_req_readdir)              |
-            NFSPROC4_RENEW                  => call!(nfs4_req_renew)                |
-            NFSPROC4_OPEN_CONFIRM           => call!(nfs4_req_open_confirm)         |
-            NFSPROC4_REMOVE                 => call!(nfs4_req_remove)               |
-            NFSPROC4_RENAME                 => call!(nfs4_req_rename)               |
-            NFSPROC4_CREATE                 => call!(nfs4_req_create)               |
-            NFSPROC4_DELEGRETURN            => call!(nfs4_req_delegreturn)          |
-            NFSPROC4_SETATTR                => call!(nfs4_req_setattr)              |
-            NFSPROC4_PUTROOTFH              => call!(nfs4_req_putrootfh)            |
-            NFSPROC4_SETCLIENTID            => call!(nfs4_req_setclientid)          |
-            NFSPROC4_SETCLIENTID_CONFIRM    => call!(nfs4_req_setclientid_confirm)  |
-            NFSPROC4_SEQUENCE               => call!(nfs4_req_sequence)             |
-            NFSPROC4_EXCHANGE_ID            => call!(nfs4_req_exchangeid)
-            )
-        >> ( cmd_data )
-));
+fn nfs4_req_sequence(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, ssn_id) = take(16_usize)(i)?;
+    let (i, _seq_id) = be_u32(i)?;
+    let (i, _slot_id) = be_u32(i)?;
+    let (i, _high_slot_id) = be_u32(i)?;
+    let (i, _cache_this) = be_u32(i)?;
+    let req = Nfs4RequestContent::Sequence(Nfs4RequestSequence {
+        ssn_id
+    });
+    Ok((i, req))
+}
+
+fn parse_request_compound_command(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, cmd) = be_u32(i)?;
+    let (i, cmd_data) = match cmd {
+        NFSPROC4_PUTFH => nfs4_req_putfh(i)?,
+        NFSPROC4_READ => nfs4_req_read(i)?,
+        NFSPROC4_WRITE => nfs4_req_write(i)?,
+        NFSPROC4_GETFH => nfs4_req_getfh(i)?,
+        NFSPROC4_SAVEFH => nfs4_req_savefh(i)?,
+        NFSPROC4_OPEN => nfs4_req_open(i)?,
+        NFSPROC4_CLOSE => nfs4_req_close(i)?,
+        NFSPROC4_LOOKUP => nfs4_req_lookup(i)?,
+        NFSPROC4_ACCESS => nfs4_req_access(i)?,
+        NFSPROC4_COMMIT => nfs4_req_commit(i)?,
+        NFSPROC4_GETATTR => nfs4_req_getattr(i)?,
+        NFSPROC4_READDIR => nfs4_req_readdir(i)?,
+        NFSPROC4_RENEW => nfs4_req_renew(i)?,
+        NFSPROC4_OPEN_CONFIRM => nfs4_req_open_confirm(i)?,
+        NFSPROC4_REMOVE => nfs4_req_remove(i)?,
+        NFSPROC4_RENAME => nfs4_req_rename(i)?,
+        NFSPROC4_CREATE => nfs4_req_create(i)?,
+        NFSPROC4_DELEGRETURN => nfs4_req_delegreturn(i)?,
+        NFSPROC4_SETATTR => nfs4_req_setattr(i)?,
+        NFSPROC4_PUTROOTFH => nfs4_req_putrootfh(i)?,
+        NFSPROC4_SETCLIENTID => nfs4_req_setclientid(i)?,
+        NFSPROC4_SETCLIENTID_CONFIRM => nfs4_req_setclientid_confirm(i)?,
+        NFSPROC4_SEQUENCE => nfs4_req_sequence(i)?,
+        NFSPROC4_EXCHANGE_ID => nfs4_req_exchangeid(i)?,
+        _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
+    };
+    Ok((i, cmd_data))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4RequestCompoundRecord<'a> {
     pub commands: Vec<Nfs4RequestContent<'a>>,
 }
 
-named!(pub parse_nfs4_request_compound<Nfs4RequestCompoundRecord>,
-    do_parse!(
-            tag_len: be_u32
-        >>  _tag: cond!(tag_len > 0, take!(tag_len))
-        >>  _min_ver: be_u32
-        >>  ops_cnt: be_u32
-        >>  commands: count!(parse_request_compound_command, ops_cnt as usize)
-        >> (Nfs4RequestCompoundRecord {
-                commands
-            })
-));
+pub fn parse_nfs4_request_compound(i: &[u8]) -> IResult<&[u8], Nfs4RequestCompoundRecord> {
+    let (i, tag_len) = be_u32(i)?;
+    let (i, _tag) = cond(tag_len > 0, take(tag_len as usize))(i)?;
+    let (i, _min_ver) = be_u32(i)?;
+    let (i, ops_cnt) = be_u32(i)?;
+    let (i, commands) = count(parse_request_compound_command, ops_cnt as usize)(i)?;
+    Ok((i, Nfs4RequestCompoundRecord { commands }))
+}
 
 #[derive(Debug,PartialEq)]
 pub enum Nfs4ResponseContent<'a> {
@@ -546,23 +501,18 @@ pub struct Nfs4ResponseWrite {
     pub committed: u32,
 }
 
-named!(nfs4_res_write_ok<Nfs4ResponseWrite>,
-    do_parse!(
-            count: be_u32
-        >>  committed: be_u32
-        >>  _verifier: be_u64
-        >> (Nfs4ResponseWrite {
-                count,
-                committed
-           })
-));
-
-named!(nfs4_res_write<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  wd: cond!(status == 0, nfs4_res_write_ok)
-        >> (Nfs4ResponseContent::Write(status, wd) )
-));
+fn nfs4_res_write_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseWrite> {
+    let (i, count) = be_u32(i)?;
+    let (i, committed) = be_u32(i)?;
+    let (i, _verifier) = be_u64(i)?;
+    Ok((i, Nfs4ResponseWrite { count, committed }))
+}
+
+fn nfs4_res_write(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, wd) = cond(status == 0, nfs4_res_write_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Write(status, wd)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseRead<'a> {
@@ -571,24 +521,23 @@ pub struct Nfs4ResponseRead<'a> {
     pub data: &'a[u8],
 }
 
-named!(nfs4_res_read_ok<Nfs4ResponseRead>,
-    do_parse!(
-            eof: be_u32
-        >>  read_len: be_u32
-        >>  read_data: take!(read_len)
-        >> (Nfs4ResponseRead {
-                eof: eof==1,
-                count: read_len,
-                data: read_data,
-            })
-));
-
-named!(nfs4_res_read<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  rd: cond!(status == 0, nfs4_res_read_ok)
-        >> (Nfs4ResponseContent::Read(status, rd) )
-));
+fn nfs4_res_read_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseRead> {
+    let (i, eof) = be_u32(i)?;
+    let (i, read_len) = be_u32(i)?;
+    let (i, read_data) = take(read_len as usize)(i)?;
+    let resp = Nfs4ResponseRead {
+        eof: eof==1,
+        count: read_len,
+        data: read_data,
+    };
+    Ok((i, resp))
+}
+
+fn nfs4_res_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, rd) = cond(status == 0, nfs4_res_read_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Read(status, rd)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseOpen<'a> {
@@ -603,42 +552,38 @@ pub struct Nfs4ResponseOpenDelegateRead<'a> {
     pub stateid: Nfs4StateId<'a>,
 }
 
-named!(nfs4_res_open_ok_delegate_read<Nfs4ResponseOpenDelegateRead>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  _recall: be_u32
-        >>  _ace_type: be_u32
-        >>  _ace_flags: be_u32
-        >>  _ace_mask: be_u32
-        >>  who_len: be_u32
-        >>  _who: take!(who_len)
-        >> (Nfs4ResponseOpenDelegateRead {
-                stateid
-            })
-));
-
-named!(nfs4_res_open_ok<Nfs4ResponseOpen>,
-    do_parse!(
-            stateid: nfs4_parse_stateid
-        >>  _change_info: take!(20)
-        >>  result_flags: be_u32
-        >>  _attrs: nfs4_parse_attrbits
-        >>  delegation_type: be_u32
-        >>  delegate_read: cond!(delegation_type == 1, nfs4_res_open_ok_delegate_read)
-        >> ( Nfs4ResponseOpen {
-                 stateid,
-                 result_flags,
-                 delegation_type,
-                 delegate_read
-             } )
-));
-
-named!(nfs4_res_open<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  open_data: cond!(status == 0, nfs4_res_open_ok)
-        >> ( Nfs4ResponseContent::Open(status, open_data) )
-));
+fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpenDelegateRead> {
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let (i, _recall) = be_u32(i)?;
+    let (i, _ace_type) = be_u32(i)?;
+    let (i, _ace_flags) = be_u32(i)?;
+    let (i, _ace_mask) = be_u32(i)?;
+    let (i, who_len) = be_u32(i)?;
+    let (i, _who) = take(who_len as usize)(i)?;
+    Ok((i, Nfs4ResponseOpenDelegateRead { stateid }))
+}
+
+fn nfs4_res_open_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpen> {
+    let (i, stateid) = nfs4_parse_stateid(i)?;
+    let (i, _change_info) = take(20_usize)(i)?;
+    let (i, result_flags) = be_u32(i)?;
+    let (i, _attrs) = nfs4_parse_attrbits(i)?;
+    let (i, delegation_type) = be_u32(i)?;
+    let (i, delegate_read) = cond(delegation_type == 1, nfs4_res_open_ok_delegate_read)(i)?;
+    let resp = Nfs4ResponseOpen {
+        stateid,
+        result_flags,
+        delegation_type,
+        delegate_read
+    };
+    Ok((i, resp))
+}
+
+fn nfs4_res_open(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, open_data) = cond(status == 0, nfs4_res_open_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Open(status, open_data)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseReaddirEntry<'a> {
@@ -651,171 +596,143 @@ pub struct Nfs4ResponseReaddir<'a> {
     pub listing: Vec<Option<Nfs4ResponseReaddirEntry<'a>>>,
 }
 
-named!(nfs4_res_readdir_entry_do<Nfs4ResponseReaddirEntry>,
-    do_parse!(
-            _cookie: be_u64
-        >>  name: nfs4_parse_nfsstring
-        >>  _attrs: nfs4_parse_attrs
-        >> ( Nfs4ResponseReaddirEntry {
-                name: name,
-            })
-));
-
-named!(nfs4_res_readdir_entry<Option<Nfs4ResponseReaddirEntry>>,
-    do_parse!(
-            value_follows: be_u32
-        >>  entry: cond!(value_follows == 1, nfs4_res_readdir_entry_do)
-        >> (entry)
-));
-
-named!(nfs4_res_readdir_ok<Nfs4ResponseReaddir>,
-    do_parse!(
-            _verifier: be_u64
-        // run parser until we find a 'value follows == 0'
-        >>  listing: many_till!(complete!(call!(nfs4_res_readdir_entry)), peek!(tag!(b"\x00\x00\x00\x00")))
-        // value follows == 0 checked by line above
-        >>  _value_follows: be_u32
-        >>  eof: be_u32
-        >> ( Nfs4ResponseReaddir { eof: eof==1, listing: listing.0 })
-));
-
-named!(nfs4_res_readdir<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  rd: cond!(status == 0, nfs4_res_readdir_ok)
-        >> ( Nfs4ResponseContent::ReadDir(status, rd) )
-));
-
-named!(nfs4_res_create_ok<Nfs4Attr>,
-    do_parse!(
-            _change_info: take!(20)
-        >>  attrs: nfs4_parse_attrbits
-        >> ( attrs )
-));
-
-named!(nfs4_res_create<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  _attrs: cond!(status == 0, nfs4_res_create_ok)
-        >> ( Nfs4ResponseContent::Create(status) )
-));
-
-named!(nfs4_res_setattr_ok<Nfs4Attr>,
-    do_parse!(
-            attrs: nfs4_parse_attrbits
-        >> ( attrs )
-));
-
-named!(nfs4_res_setattr<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  _attrs: cond!(status == 0, nfs4_res_setattr_ok)
-        >> ( Nfs4ResponseContent::SetAttr(status) )
-));
-
-named!(nfs4_res_getattr_ok<Nfs4Attr>,
-    do_parse!(
-            attrs: nfs4_parse_attrs
-        >> ( attrs )
-));
-
-named!(nfs4_res_getattr<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  attrs: cond!(status == 0, nfs4_res_getattr_ok)
-        >> ( Nfs4ResponseContent::GetAttr(status, attrs) )
-));
-
-named!(nfs4_res_openconfirm<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  stateid: cond!(status == 0, nfs4_parse_stateid)
-        >> ( Nfs4ResponseContent::OpenConfirm(status, stateid) )
-));
-
-named!(nfs4_res_close<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  stateid: cond!(status == 0, nfs4_parse_stateid)
-        >> ( Nfs4ResponseContent::Close(status, stateid) )
-));
-
-named!(nfs4_res_remove<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  cond!(status == 0, take!(20))   // change_info
-        >> ( Nfs4ResponseContent::Remove(status) )
-));
-
-named!(nfs4_res_rename<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::Rename(status) )
-));
-
-named!(nfs4_res_savefh<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::SaveFH(status) )
-));
-
-named!(nfs4_res_lookup<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::Lookup(status) )
-));
-
-named!(nfs4_res_renew<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::Renew(status) )
-));
-
-named!(nfs4_res_getfh<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  fh: cond!(status == 0, nfs4_parse_handle)
-        >> ( Nfs4ResponseContent::GetFH(status, fh) )
-));
-
-named!(nfs4_res_putfh<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::PutFH(status) )
-));
-
-named!(nfs4_res_putrootfh<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::PutRootFH(status) )
-));
-
-named!(nfs4_res_delegreturn<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::DelegReturn(status) )
-));
-
-named!(nfs4_res_setclientid<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  _client_id: be_u64
-        >>  _verifier: be_u32
-        >> ( Nfs4ResponseContent::SetClientId(status) )
-));
-
-named!(nfs4_res_setclientid_confirm<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >> ( Nfs4ResponseContent::SetClientIdConfirm(status) )
-));
-
-named!(nfs4_res_commit<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  _verifier: cond!(status == 0, take!(8))
-        >> ( Nfs4ResponseContent::Commit(status))
-));
+fn nfs4_res_readdir_entry_do(i: &[u8]) -> IResult<&[u8], Nfs4ResponseReaddirEntry> {
+    let (i, _cookie) = be_u64(i)?;
+    let (i, name) = nfs4_parse_nfsstring(i)?;
+    let (i, _attrs) = nfs4_parse_attrs(i)?;
+    Ok((i, Nfs4ResponseReaddirEntry { name }))
+}
+
+fn nfs4_res_readdir_entry(i: &[u8]) -> IResult<&[u8], Option<Nfs4ResponseReaddirEntry>> {
+    let (i, value_follows) = be_u32(i)?;
+    let (i, entry) = cond(value_follows == 1, nfs4_res_readdir_entry_do)(i)?;
+    Ok((i, entry))
+}
+
+fn nfs4_res_readdir_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseReaddir> {
+    let (i, _verifier) = be_u64(i)?;
+    // run parser until we find a 'value follows == 0'
+    let (i, listing) = many_till(
+        complete(nfs4_res_readdir_entry),
+        peek(tag(b"\x00\x00\x00\x00")),
+    )(i)?;
+    // value follows == 0 checked by line above
+    let (i, _value_follows) = be_u32(i)?;
+    let (i, eof) = be_u32(i)?;
+    Ok((
+        i,
+        Nfs4ResponseReaddir {
+            eof: eof == 1,
+            listing: listing.0,
+        },
+    ))
+}
+
+fn nfs4_res_readdir(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, rd) = cond(status == 0, nfs4_res_readdir_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::ReadDir(status, rd)))
+}
+
+fn nfs4_res_create_ok(i: &[u8]) -> IResult<&[u8], Nfs4Attr> {
+    let (i, _change_info) = take(20_usize)(i)?;
+    nfs4_parse_attrbits(i)
+}
+
+fn nfs4_res_create(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, _attrs) = cond(status == 0, nfs4_res_create_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Create(status)))
+}
+
+fn nfs4_res_setattr_ok(i: &[u8]) -> IResult<&[u8], Nfs4Attr> {
+    nfs4_parse_attrbits(i)
+}
+
+fn nfs4_res_setattr(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, _attrs) = cond(status == 0, nfs4_res_setattr_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::SetAttr(status)))
+}
+
+fn nfs4_res_getattr_ok(i: &[u8]) -> IResult<&[u8], Nfs4Attr> {
+    nfs4_parse_attrs(i)
+}
+
+fn nfs4_res_getattr(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, attrs) = cond(status == 0, nfs4_res_getattr_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::GetAttr(status, attrs)))
+}
+
+fn nfs4_res_openconfirm(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, stateid) = cond(status == 0, nfs4_parse_stateid)(i)?;
+    Ok((i, Nfs4ResponseContent::OpenConfirm(status, stateid)))
+}
+
+fn nfs4_res_close(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, stateid) = cond(status == 0, nfs4_parse_stateid)(i)?;
+    Ok((i, Nfs4ResponseContent::Close(status, stateid)))
+}
+
+fn nfs4_res_remove(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, _) = cond(status == 0, take(20_usize))(i)?;
+    Ok((i, Nfs4ResponseContent::Remove(status)))
+}
+
+fn nfs4_res_rename(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::Rename)(i)
+}
+
+fn nfs4_res_savefh(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::SaveFH)(i)
+}
+
+fn nfs4_res_lookup(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::Lookup)(i)
+}
+
+fn nfs4_res_renew(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::Renew)(i)
+}
+
+fn nfs4_res_getfh(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, fh) = cond(status == 0, nfs4_parse_handle)(i)?;
+    Ok((i, Nfs4ResponseContent::GetFH(status, fh)))
+}
+
+fn nfs4_res_putfh(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::PutFH)(i)
+}
+
+fn nfs4_res_putrootfh(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::PutRootFH)(i)
+}
+
+fn nfs4_res_delegreturn(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::DelegReturn)(i)
+}
+
+fn nfs4_res_setclientid(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, _client_id) = be_u64(i)?;
+    let (i, _verifier) = be_u32(i)?;
+    Ok((i, Nfs4ResponseContent::SetClientId(status)))
+}
+
+fn nfs4_res_setclientid_confirm(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    map(be_u32, Nfs4ResponseContent::SetClientIdConfirm)(i)
+}
+
+fn nfs4_res_commit(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, _verifier) = cond(status == 0, take(8_usize))(i)?;
+    Ok((i, Nfs4ResponseContent::Commit(status)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseAccess {
@@ -823,76 +740,70 @@ pub struct Nfs4ResponseAccess {
     pub access_rights: u32,
 }
 
-named!(nfs4_res_access_ok<Nfs4ResponseAccess>,
-    do_parse!(
-            s: be_u32
-        >>  a: be_u32
-        >> (Nfs4ResponseAccess {
-                supported_types: s,
-                access_rights: a,
-            })
-));
-
-named!(nfs4_res_access<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  ad: cond!(status == 0, nfs4_res_access_ok)
-        >> ( Nfs4ResponseContent::Access(
-                status, ad, ))
-));
+fn nfs4_res_access_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseAccess> {
+    let (i, supported_types) = be_u32(i)?;
+    let (i, access_rights) = be_u32(i)?;
+    let resp = Nfs4ResponseAccess {
+        supported_types,
+        access_rights
+    };
+    Ok((i, resp))
+}
 
+fn nfs4_res_access(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, ad) = cond(status == 0, nfs4_res_access_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Access(status, ad)))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseSequence<'a> {
     pub ssn_id: &'a[u8],
 }
 
-named!(nfs4_res_sequence_ok<Nfs4ResponseSequence>,
-    do_parse!(
-            ssn_id: take!(16)
-        >>  _slots: take!(12)
-        >>  _flags: be_u32
-        >> ( Nfs4ResponseSequence {
-                ssn_id: ssn_id,
-            })
-));
-
-named!(nfs4_res_sequence<Nfs4ResponseContent>,
-    do_parse!(
-            status: be_u32
-        >>  seq: cond!(status == 0, nfs4_res_sequence_ok)
-        >> ( Nfs4ResponseContent::Sequence(status, seq) )
-));
-
-named!(nfs4_res_compound_command<Nfs4ResponseContent>,
-    do_parse!(
-        cmd: be_u32
-    >>  cmd_data: switch!(value!(cmd),
-            NFSPROC4_READ                   => call!(nfs4_res_read)                |
-            NFSPROC4_WRITE                  => call!(nfs4_res_write)               |
-            NFSPROC4_ACCESS                 => call!(nfs4_res_access)              |
-            NFSPROC4_COMMIT                 => call!(nfs4_res_commit)              |
-            NFSPROC4_GETFH                  => call!(nfs4_res_getfh)               |
-            NFSPROC4_PUTFH                  => call!(nfs4_res_putfh)               |
-            NFSPROC4_SAVEFH                 => call!(nfs4_res_savefh)              |
-            NFSPROC4_RENAME                 => call!(nfs4_res_rename)              |
-            NFSPROC4_READDIR                => call!(nfs4_res_readdir)             |
-            NFSPROC4_GETATTR                => call!(nfs4_res_getattr)             |
-            NFSPROC4_SETATTR                => call!(nfs4_res_setattr)             |
-            NFSPROC4_LOOKUP                 => call!(nfs4_res_lookup)              |
-            NFSPROC4_OPEN                   => call!(nfs4_res_open)                |
-            NFSPROC4_OPEN_CONFIRM           => call!(nfs4_res_openconfirm)         |
-            NFSPROC4_CLOSE                  => call!(nfs4_res_close)               |
-            NFSPROC4_REMOVE                 => call!(nfs4_res_remove)              |
-            NFSPROC4_CREATE                 => call!(nfs4_res_create)              |
-            NFSPROC4_DELEGRETURN            => call!(nfs4_res_delegreturn)         |
-            NFSPROC4_SETCLIENTID            => call!(nfs4_res_setclientid)         |
-            NFSPROC4_SETCLIENTID_CONFIRM    => call!(nfs4_res_setclientid_confirm) |
-            NFSPROC4_PUTROOTFH              => call!(nfs4_res_putrootfh)           |
-            NFSPROC4_SEQUENCE               => call!(nfs4_res_sequence)            |
-            NFSPROC4_RENEW                  => call!(nfs4_res_renew))
-    >> (cmd_data)
-));
+fn nfs4_res_sequence_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseSequence> {
+    let (i, ssn_id) = take(16_usize)(i)?;
+    let (i, _slots) = take(12_usize)(i)?;
+    let (i, _flags) = be_u32(i)?;
+    Ok((i, Nfs4ResponseSequence { ssn_id }))
+}
+
+fn nfs4_res_sequence(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, seq) = cond(status == 0, nfs4_res_sequence_ok)(i)?;
+    Ok((i, Nfs4ResponseContent::Sequence(status, seq)))
+}
+
+fn nfs4_res_compound_command(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, cmd) = be_u32(i)?;
+    let (i, cmd_data) = match cmd {
+        NFSPROC4_READ => nfs4_res_read(i)?,
+        NFSPROC4_WRITE => nfs4_res_write(i)?,
+        NFSPROC4_ACCESS => nfs4_res_access(i)?,
+        NFSPROC4_COMMIT => nfs4_res_commit(i)?,
+        NFSPROC4_GETFH => nfs4_res_getfh(i)?,
+        NFSPROC4_PUTFH => nfs4_res_putfh(i)?,
+        NFSPROC4_SAVEFH => nfs4_res_savefh(i)?,
+        NFSPROC4_RENAME => nfs4_res_rename(i)?,
+        NFSPROC4_READDIR => nfs4_res_readdir(i)?,
+        NFSPROC4_GETATTR => nfs4_res_getattr(i)?,
+        NFSPROC4_SETATTR => nfs4_res_setattr(i)?,
+        NFSPROC4_LOOKUP => nfs4_res_lookup(i)?,
+        NFSPROC4_OPEN => nfs4_res_open(i)?,
+        NFSPROC4_OPEN_CONFIRM => nfs4_res_openconfirm(i)?,
+        NFSPROC4_CLOSE => nfs4_res_close(i)?,
+        NFSPROC4_REMOVE => nfs4_res_remove(i)?,
+        NFSPROC4_CREATE => nfs4_res_create(i)?,
+        NFSPROC4_DELEGRETURN => nfs4_res_delegreturn(i)?,
+        NFSPROC4_SETCLIENTID => nfs4_res_setclientid(i)?,
+        NFSPROC4_SETCLIENTID_CONFIRM => nfs4_res_setclientid_confirm(i)?,
+        NFSPROC4_PUTROOTFH => nfs4_res_putrootfh(i)?,
+        NFSPROC4_SEQUENCE => nfs4_res_sequence(i)?,
+        NFSPROC4_RENEW => nfs4_res_renew(i)?,
+        _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
+    };
+    Ok((i, cmd_data))
+}
 
 #[derive(Debug,PartialEq)]
 pub struct Nfs4ResponseCompoundRecord<'a> {
@@ -900,15 +811,11 @@ pub struct Nfs4ResponseCompoundRecord<'a> {
     pub commands: Vec<Nfs4ResponseContent<'a>>,
 }
 
-named!(pub parse_nfs4_response_compound<Nfs4ResponseCompoundRecord>,
-    do_parse!(
-            status: be_u32
-        >>  tag_len: be_u32
-        >>  _tag: cond!(tag_len > 0, take!(tag_len))
-        >>  ops_cnt: be_u32
-        >>  commands: count!(nfs4_res_compound_command, ops_cnt as usize)
-        >> (Nfs4ResponseCompoundRecord {
-                status: status,
-                commands: commands,
-            })
-));
+pub fn parse_nfs4_response_compound(i: &[u8]) -> IResult<&[u8], Nfs4ResponseCompoundRecord> {
+    let (i, status) = be_u32(i)?;
+    let (i, tag_len) = be_u32(i)?;
+    let (i, _tag) = cond(tag_len > 0, take(tag_len as usize))(i)?;
+    let (i, ops_cnt) = be_u32(i)?;
+    let (i, commands) = count(nfs4_res_compound_command, ops_cnt as usize)(i)?;
+    Ok((i, Nfs4ResponseCompoundRecord { status, commands }))
+}
index 2341be109af1436096cc703ea9e6c3f8a2269781..933d2e0146239bd0cbda0b4e0526c48711791bf3 100644 (file)
 
 //! Nom parsers for RPCv2
 
-use nom::IResult;
-use nom::combinator::rest;
-use nom::number::streaming::be_u32;
-
-#[derive(Debug,PartialEq)]
+use nom7::bits::{bits, streaming::take as take_bits};
+use nom7::bytes::streaming::take;
+use nom7::combinator::cond;
+use nom7::error::Error;
+use nom7::multi::length_data;
+use nom7::number::streaming::be_u32;
+use nom7::sequence::tuple;
+use nom7::IResult;
+
+#[derive(Debug, PartialEq)]
 pub enum RpcRequestCreds<'a> {
     Unix(RpcRequestCredsUnix<'a>),
     GssApi(RpcRequestCredsGssApi<'a>),
-    Unknown(&'a[u8]),
+    Unknown(&'a [u8]),
 }
 
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct RpcRequestCredsUnix<'a> {
     pub stamp: u32,
     pub machine_name_len: u32,
-    pub machine_name_buf: &'a[u8],
+    pub machine_name_buf: &'a [u8],
     pub uid: u32,
     pub gid: u32,
     pub aux_gids: Option<Vec<u32>>,
@@ -43,122 +48,114 @@ pub struct RpcRequestCredsUnix<'a> {
 //    many0!(be_u32)
 //);
 
-named!(parse_rpc_request_creds_unix<RpcRequestCreds>,
-    do_parse!(
-        stamp: be_u32
-    >>  machine_name_len: be_u32
-    >>  machine_name_buf: take!(machine_name_len)
-    >>  uid: be_u32
-    >>  gid: be_u32
-    //>>aux_gids: parse_rpc_creds_unix_aux_gids
-    >> (RpcRequestCreds::Unix(RpcRequestCredsUnix {
-            stamp:stamp,
-            machine_name_len:machine_name_len,
-            machine_name_buf:machine_name_buf,
-            uid:uid,
-            gid:gid,
-            aux_gids:None,
-        }))
-));
-
-#[derive(Debug,PartialEq)]
+fn parse_rpc_request_creds_unix(i: &[u8]) -> IResult<&[u8], RpcRequestCreds> {
+    let (i, stamp) = be_u32(i)?;
+    let (i, machine_name_len) = be_u32(i)?;
+    let (i, machine_name_buf) = take(machine_name_len as usize)(i)?;
+    let (i, uid) = be_u32(i)?;
+    let (i, gid) = be_u32(i)?;
+    // let (i, aux_gids) = parse_rpc_creds_unix_aux_gids(i)?;
+    let creds = RpcRequestCreds::Unix(RpcRequestCredsUnix {
+        stamp,
+        machine_name_len,
+        machine_name_buf,
+        uid,
+        gid,
+        aux_gids: None,
+    });
+    Ok((i, creds))
+}
+
+#[derive(Debug, PartialEq)]
 pub struct RpcRequestCredsGssApi<'a> {
     pub version: u32,
     pub procedure: u32,
     pub seq_num: u32,
     pub service: u32,
 
-    pub ctx: &'a[u8],
+    pub ctx: &'a [u8],
 }
 
-named!(parse_rpc_request_creds_gssapi<RpcRequestCreds>,
-    do_parse!(
-        version: be_u32
-    >>  procedure: be_u32
-    >>  seq_num: be_u32
-    >>  service: be_u32
-    >>  ctx_len: be_u32
-    >>  ctx: take!(ctx_len)
-    >> (RpcRequestCreds::GssApi(RpcRequestCredsGssApi {
-            version: version,
-            procedure: procedure,
-            seq_num: seq_num,
-            service: service,
-            ctx: ctx,
-        }))
-));
-
-named!(parse_rpc_request_creds_unknown<RpcRequestCreds>,
-    do_parse!(
-        blob: rest
-    >> (RpcRequestCreds::Unknown(blob) )
-));
-
-#[derive(Debug,PartialEq)]
+fn parse_rpc_request_creds_gssapi(i: &[u8]) -> IResult<&[u8], RpcRequestCreds> {
+    let (i, version) = be_u32(i)?;
+    let (i, procedure) = be_u32(i)?;
+    let (i, seq_num) = be_u32(i)?;
+    let (i, service) = be_u32(i)?;
+    let (i, ctx) = length_data(be_u32)(i)?;
+    let creds = RpcRequestCreds::GssApi(RpcRequestCredsGssApi {
+        version,
+        procedure,
+        seq_num,
+        service,
+        ctx,
+    });
+    Ok((i, creds))
+}
+
+fn parse_rpc_request_creds_unknown(i: &[u8]) -> IResult<&[u8], RpcRequestCreds> {
+    Ok((&[], RpcRequestCreds::Unknown(i)))
+}
+
+#[derive(Debug, PartialEq)]
 pub struct RpcGssApiIntegrity<'a> {
     pub seq_num: u32,
-    pub data: &'a[u8],
+    pub data: &'a [u8],
 }
 
 // Parse the GSSAPI Integrity envelope to get to the
 // data we care about.
-named!(pub parse_rpc_gssapi_integrity<RpcGssApiIntegrity>,
-    do_parse!(
-        len: be_u32
-    >>  seq_num: be_u32
-    >>  data: take!(len)
-    >> (RpcGssApiIntegrity {
-            seq_num: seq_num,
-            data: data,
-        })
-));
-
-#[derive(Debug,PartialEq)]
-pub struct RpcPacketHeader<> {
+pub fn parse_rpc_gssapi_integrity(i: &[u8]) -> IResult<&[u8], RpcGssApiIntegrity> {
+    let (i, len) = be_u32(i)?;
+    let (i, seq_num) = be_u32(i)?;
+    let (i, data) = take(len as usize)(i)?;
+    let res = RpcGssApiIntegrity { seq_num, data };
+    Ok((i, res))
+}
+
+#[derive(Debug, PartialEq)]
+pub struct RpcPacketHeader {
     pub frag_is_last: bool,
     pub frag_len: u32,
     pub xid: u32,
     pub msgtype: u32,
 }
 
-fn parse_bits(i:&[u8]) -> IResult<&[u8],(u8,u32)> {
-    bits!(i,
-        tuple!(
-            take_bits!(1u8),       // is_last
-            take_bits!(31u32)))    // len
+fn parse_bits(i: &[u8]) -> IResult<&[u8], (u8, u32)> {
+    bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((
+        take_bits(1u8),   // is_last
+        take_bits(31u32), // len
+    )))(i)
+}
+
+pub fn parse_rpc_packet_header(i: &[u8]) -> IResult<&[u8], RpcPacketHeader> {
+    let (i, fraghdr) = parse_bits(i)?;
+    let (i, xid) = be_u32(i)?;
+    let (i, msgtype) = be_u32(i)?;
+    let hdr = RpcPacketHeader {
+        frag_is_last: fraghdr.0 == 1,
+        frag_len: fraghdr.1,
+        xid,
+        msgtype,
+    };
+    Ok((i, hdr))
 }
 
-named!(pub parse_rpc_packet_header<RpcPacketHeader>,
-    do_parse!(
-        fraghdr: parse_bits
-        >> xid: be_u32
-        >> msgtype: be_u32
-        >> (
-            RpcPacketHeader {
-                frag_is_last:fraghdr.0 == 1,
-                frag_len:fraghdr.1,
-                xid:xid,
-                msgtype:msgtype,
-            }
-        ))
-);
-
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct RpcReplyPacket<'a> {
-    pub hdr: RpcPacketHeader<>,
+    pub hdr: RpcPacketHeader,
 
     pub verifier_flavor: u32,
     pub verifier_len: u32,
-    pub verifier: Option<&'a[u8]>,
+    pub verifier: Option<&'a [u8]>,
 
     pub reply_state: u32,
     pub accept_state: u32,
 
-    pub prog_data: &'a[u8],
+    pub prog_data: &'a [u8],
 }
 
 // top of request packet, just to get to procedure
-#[derive(Debug,PartialEq)]
+#[derive(Debug, PartialEq)]
 pub struct RpcRequestPacketPartial {
     pub hdr: RpcPacketHeader,
 
@@ -168,27 +165,25 @@ pub struct RpcRequestPacketPartial {
     pub procedure: u32,
 }
 
-named!(pub parse_rpc_request_partial<RpcRequestPacketPartial>,
-   do_parse!(
-       hdr: parse_rpc_packet_header
-       >> rpcver: be_u32
-       >> program: be_u32
-       >> progver: be_u32
-       >> procedure: be_u32
-       >> (
-            RpcRequestPacketPartial {
-                hdr:hdr,
-                rpcver:rpcver,
-                program:program,
-                progver:progver,
-                procedure:procedure,
-            }
-          ))
-);
-
-#[derive(Debug,PartialEq)]
+pub fn parse_rpc_request_partial(i: &[u8]) -> IResult<&[u8], RpcRequestPacketPartial> {
+    let (i, hdr) = parse_rpc_packet_header(i)?;
+    let (i, rpcver) = be_u32(i)?;
+    let (i, program) = be_u32(i)?;
+    let (i, progver) = be_u32(i)?;
+    let (i, procedure) = be_u32(i)?;
+    let req = RpcRequestPacketPartial {
+        hdr,
+        rpcver,
+        program,
+        progver,
+        procedure,
+    };
+    Ok((i, req))
+}
+
+#[derive(Debug, PartialEq)]
 pub struct RpcPacket<'a> {
-    pub hdr: RpcPacketHeader<>,
+    pub hdr: RpcPacketHeader,
 
     pub rpcver: u32,
     pub program: u32,
@@ -200,177 +195,165 @@ pub struct RpcPacket<'a> {
 
     pub verifier_flavor: u32,
     pub verifier_len: u32,
-    pub verifier: &'a[u8],
+    pub verifier: &'a [u8],
 
-    pub prog_data: &'a[u8],
+    pub prog_data: &'a [u8],
 }
 
-named!(pub parse_rpc<RpcPacket>,
-   do_parse!(
-       hdr: parse_rpc_packet_header
-
-       >> rpcver: be_u32
-       >> program: be_u32
-       >> progver: be_u32
-       >> procedure: be_u32
-
-       >> creds_flavor: be_u32
-       >> creds_len: be_u32
-       >> creds: flat_map!(take!(creds_len), switch!(value!(creds_flavor),
-            1 => call!(parse_rpc_request_creds_unix)    |
-            6 => call!(parse_rpc_request_creds_gssapi)  |
-            _ => call!(parse_rpc_request_creds_unknown) ))
-
-       >> verifier_flavor: be_u32
-       >> verifier_len: be_u32
-       >> verifier: take!(verifier_len as usize)
-
-       >> pl: rest
-
-       >> (
-           RpcPacket {
-                hdr:hdr,
-
-                rpcver:rpcver,
-                program:program,
-                progver:progver,
-                procedure:procedure,
-
-                creds_flavor:creds_flavor,
-                creds:creds,
-
-                verifier_flavor:verifier_flavor,
-                verifier_len:verifier_len,
-                verifier:verifier,
-
-                prog_data:pl,
-           }
-   ))
-);
+pub fn parse_rpc(i: &[u8]) -> IResult<&[u8], RpcPacket> {
+    let (i, hdr) = parse_rpc_packet_header(i)?;
+
+    let (i, rpcver) = be_u32(i)?;
+    let (i, program) = be_u32(i)?;
+    let (i, progver) = be_u32(i)?;
+    let (i, procedure) = be_u32(i)?;
+
+    let (i, creds_flavor) = be_u32(i)?;
+    let (i, creds_len) = be_u32(i)?;
+    let (i, creds_buf) = take(creds_len as usize)(i)?;
+    let (_, creds) = match creds_flavor {
+        1 => parse_rpc_request_creds_unix(creds_buf)?,
+        6 => parse_rpc_request_creds_gssapi(creds_buf)?,
+        _ => parse_rpc_request_creds_unknown(creds_buf)?,
+    };
+
+    let (i, verifier_flavor) = be_u32(i)?;
+    let (i, verifier_len) = be_u32(i)?;
+    let (i, verifier) = take(verifier_len as usize)(i)?;
+
+    let (i, prog_data) = (&[], i);
+    let packet = RpcPacket {
+        hdr,
+
+        rpcver,
+        program,
+        progver,
+        procedure,
+
+        creds_flavor,
+        creds,
+
+        verifier_flavor,
+        verifier_len,
+        verifier,
+
+        prog_data,
+    };
+    Ok((i, packet))
+}
 
 // to be called with data <= hdr.frag_len + 4. Sending more data is undefined.
-named!(pub parse_rpc_reply<RpcReplyPacket>,
-   do_parse!(
-       hdr: parse_rpc_packet_header
-
-       >> reply_state: be_u32
-
-       >> verifier_flavor: be_u32
-       >> verifier_len: be_u32
-       >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize))
-
-       >> accept_state: be_u32
-
-       >> pl: rest
-
-       >> (
-           RpcReplyPacket {
-                hdr:hdr,
-
-                verifier_flavor:verifier_flavor,
-                verifier_len:verifier_len,
-                verifier:verifier,
-
-                reply_state:reply_state,
-                accept_state:accept_state,
-
-                prog_data:pl,
-           }
-   ))
-);
+pub fn parse_rpc_reply(i: &[u8]) -> IResult<&[u8], RpcReplyPacket> {
+    let (i, hdr) = parse_rpc_packet_header(i)?;
 
-named!(pub parse_rpc_udp_packet_header<RpcPacketHeader>,
-    do_parse!(
-        xid: be_u32
-        >> msgtype: be_u32
-        >> (
-            RpcPacketHeader {
-                frag_is_last:false,
-                frag_len:0,
+    let (i, reply_state) = be_u32(i)?;
 
-                xid:xid,
-                msgtype:msgtype,
-            }
-        ))
-);
+    let (i, verifier_flavor) = be_u32(i)?;
+    let (i, verifier_len) = be_u32(i)?;
+    let (i, verifier) = cond(verifier_len > 0, take(verifier_len as usize))(i)?;
 
-named!(pub parse_rpc_udp_request<RpcPacket>,
-   do_parse!(
-       hdr: parse_rpc_udp_packet_header
+    let (i, accept_state) = be_u32(i)?;
+    let (i, prog_data) = (&[], i);
+    let packet = RpcReplyPacket {
+        hdr,
 
-       >> rpcver: be_u32
-       >> program: be_u32
-       >> progver: be_u32
-       >> procedure: be_u32
+        verifier_flavor,
+        verifier_len,
+        verifier,
 
-       >> creds_flavor: be_u32
-       >> creds_len: be_u32
-       >> creds: flat_map!(take!(creds_len), switch!(value!(creds_flavor),
-            1 => call!(parse_rpc_request_creds_unix)    |
-            6 => call!(parse_rpc_request_creds_gssapi)  |
-            _ => call!(parse_rpc_request_creds_unknown) ))
+        reply_state,
+        accept_state,
 
-       >> verifier_flavor: be_u32
-       >> verifier_len: be_u32
-       >> verifier: take!(verifier_len as usize)
-
-       >> pl: rest
-
-       >> (
-           RpcPacket {
-                hdr:hdr,
-
-                rpcver:rpcver,
-                program:program,
-                progver:progver,
-                procedure:procedure,
-
-                creds_flavor:creds_flavor,
-                creds:creds,
-
-                verifier_flavor:verifier_flavor,
-                verifier_len:verifier_len,
-                verifier:verifier,
-
-                prog_data:pl,
-           }
-   ))
-);
+        prog_data,
+    };
+    Ok((i, packet))
+}
 
-named!(pub parse_rpc_udp_reply<RpcReplyPacket>,
-   do_parse!(
-       hdr: parse_rpc_udp_packet_header
+pub fn parse_rpc_udp_packet_header(i: &[u8]) -> IResult<&[u8], RpcPacketHeader> {
+    let (i, xid) = be_u32(i)?;
+    let (i, msgtype) = be_u32(i)?;
+    let hdr = RpcPacketHeader {
+        frag_is_last: false,
+        frag_len: 0,
+
+        xid,
+        msgtype,
+    };
+    Ok((i, hdr))
+}
 
-       >> verifier_flavor: be_u32
-       >> verifier_len: be_u32
-       >> verifier: cond!(verifier_len > 0, take!(verifier_len as usize))
+pub fn parse_rpc_udp_request(i: &[u8]) -> IResult<&[u8], RpcPacket> {
+    let (i, hdr) = parse_rpc_udp_packet_header(i)?;
+
+    let (i, rpcver) = be_u32(i)?;
+    let (i, program) = be_u32(i)?;
+    let (i, progver) = be_u32(i)?;
+    let (i, procedure) = be_u32(i)?;
+
+    let (i, creds_flavor) = be_u32(i)?;
+    let (i, creds_len) = be_u32(i)?;
+    let (i, creds_buf) = take(creds_len as usize)(i)?;
+    let (_, creds) = match creds_flavor {
+        1 => parse_rpc_request_creds_unix(creds_buf)?,
+        6 => parse_rpc_request_creds_gssapi(creds_buf)?,
+        _ => parse_rpc_request_creds_unknown(creds_buf)?,
+    };
+
+    let (i, verifier_flavor) = be_u32(i)?;
+    let (i, verifier_len) = be_u32(i)?;
+    let (i, verifier) = take(verifier_len as usize)(i)?;
+
+    let (i, prog_data) = (&[], i);
+    let packet = RpcPacket {
+        hdr,
+
+        rpcver,
+        program,
+        progver,
+        procedure,
+
+        creds_flavor,
+        creds,
+
+        verifier_flavor,
+        verifier_len,
+        verifier,
+
+        prog_data,
+    };
+    Ok((i, packet))
+}
 
-       >> reply_state: be_u32
-       >> accept_state: be_u32
+pub fn parse_rpc_udp_reply(i: &[u8]) -> IResult<&[u8], RpcReplyPacket> {
+    let (i, hdr) = parse_rpc_udp_packet_header(i)?;
 
-       >> pl: rest
+    let (i, verifier_flavor) = be_u32(i)?;
+    let (i, verifier_len) = be_u32(i)?;
+    let (i, verifier) = cond(verifier_len > 0, take(verifier_len as usize))(i)?;
 
-       >> (
-           RpcReplyPacket {
-                hdr:hdr,
+    let (i, reply_state) = be_u32(i)?;
+    let (i, accept_state) = be_u32(i)?;
+    let (i, prog_data) = (&[], i);
+    let packet = RpcReplyPacket {
+        hdr,
 
-                verifier_flavor:verifier_flavor,
-                verifier_len:verifier_len,
-                verifier:verifier,
+        verifier_flavor,
+        verifier_len,
+        verifier,
 
-                reply_state:reply_state,
-                accept_state:accept_state,
+        reply_state,
+        accept_state,
 
-                prog_data:pl,
-           }
-   ))
-);
+        prog_data,
+    };
+    Ok((i, packet))
+}
 
 #[cfg(test)]
 mod tests {
     use crate::nfs::rpc_records::*;
-    use nom::Err::Incomplete;
-    use nom::Needed::Size;
+    use nom7::Err::Incomplete;
+    use nom7::Needed;
 
     #[test]
     fn test_partial_input_too_short() {
@@ -381,7 +364,7 @@ mod tests {
 
         let r = parse_rpc_request_partial(buf);
         match r {
-            Err(Incomplete(s)) => { assert_eq!(s, Size(4)); },
+            Err(Incomplete(s)) => { assert_eq!(s, Needed::new(4)); },
             _ => { panic!("failed {:?}",r); }
         }
     }