]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs4: Add NFSPROC4_GETDEVINFO op parsers
authorSam Muhammed <ghostinthehive.vx@gmail.com>
Sun, 20 Feb 2022 16:40:11 +0000 (18:40 +0200)
committerVictor Julien <vjulien@oisf.net>
Fri, 4 Mar 2022 15:50:55 +0000 (16:50 +0100)
Also add respective response/request unittests
test_nfs4_response_getdevinfo()
test_nfs4_request_getdevinfo()

rust/src/nfs/nfs4_records.rs
rust/src/nfs/types.rs

index b2c80a3128697e43fb5dbc321c25a1a7eb407872..0a69c48a7c26facac75d2e48cb4df0ebde7bcbe2 100644 (file)
@@ -66,6 +66,7 @@ pub enum Nfs4RequestContent<'a> {
     ReclaimComplete(u32),
     SecInfoNoName(u32),
     LayoutGet(Nfs4RequestLayoutGet<'a>),
+    GetDevInfo(Nfs4RequestGetDevInfo<'a>),
 }
 
 #[derive(Debug,PartialEq)]
@@ -135,6 +136,29 @@ fn nfs4_parse_nfsstring(i: &[u8]) -> IResult<&[u8], &[u8]> {
     Ok((i, data))
 }
 
+#[derive(Debug, PartialEq)]
+pub struct Nfs4RequestGetDevInfo<'a> {
+    pub device_id: &'a[u8],
+    pub layout_type: u32,
+    pub maxcount: u32,
+    pub notify_mask: u32,
+}
+
+fn nfs4_req_getdevinfo(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent> {
+    let (i, device_id) = take(16_usize)(i)?;
+    let (i, layout_type) = be_u32(i)?;
+    let (i, maxcount) = be_u32(i)?;
+    let (i, _) = be_u32(i)?;
+    let (i, notify_mask) = be_u32(i)?;
+    let req = Nfs4RequestContent::GetDevInfo(Nfs4RequestGetDevInfo {
+        device_id,
+        layout_type,
+        maxcount,
+        notify_mask,
+    });
+    Ok((i, req))
+}
+
 #[derive(Debug, PartialEq)]
 pub struct Nfs4RequestCreateSession<'a> {
     pub client_id: &'a[u8],
@@ -529,6 +553,7 @@ fn parse_request_compound_command(i: &[u8]) -> IResult<&[u8], Nfs4RequestContent
         NFSPROC4_RECLAIM_COMPLETE => nfs4_req_reclaim_complete(i)?,
         NFSPROC4_SECINFO_NO_NAME => nfs4_req_secinfo_no_name(i)?,
         NFSPROC4_LAYOUTGET => nfs4_req_layoutget(i)?,
+        NFSPROC4_GETDEVINFO => nfs4_req_getdevinfo(i)?,
         _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
     };
     Ok((i, cmd_data))
@@ -581,6 +606,7 @@ pub enum Nfs4ResponseContent<'a> {
     ReclaimComplete(u32),
     SecInfoNoName(u32),
     LayoutGet(u32, Option<Nfs4ResponseLayoutGet<'a>>),
+    GetDevInfo(u32, Option<Nfs4ResponseGetDevInfo<'a>>),
 }
 
 #[derive(Debug, PartialEq)]
@@ -776,6 +802,36 @@ fn nfs4_res_open(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
     Ok((i, Nfs4ResponseContent::Open(status, open_data)))
 }
 
+#[derive(Debug, PartialEq)]
+pub struct Nfs4ResponseGetDevInfo<'a> {
+    pub layout_type: u32,
+    pub r_netid: &'a[u8],
+    pub r_addr: &'a[u8],
+    pub notify_mask: u32,
+}
+
+fn nfs4_parse_res_getdevinfo(i: &[u8]) -> IResult<&[u8], Nfs4ResponseGetDevInfo> {
+    let (i, layout_type) = be_u32(i)?;
+    let (i, _) = be_u64(i)?;
+    let (i, _device_index) = be_u32(i)?;
+    let (i, _) = be_u64(i)?;
+    let (i, r_netid) = nfs4_parse_nfsstring(i)?;
+    let (i, r_addr) = nfs4_parse_nfsstring(i)?;
+    let (i, notify_mask) = be_u32(i)?;
+    Ok((i, Nfs4ResponseGetDevInfo {
+        layout_type,
+        r_netid,
+        r_addr,
+        notify_mask,
+    }))
+}
+
+fn nfs4_res_getdevinfo(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
+    let (i, status) = be_u32(i)?;
+    let (i, getdevinfo) = cond(status == 0, nfs4_parse_res_getdevinfo)(i)?;
+    Ok((i, Nfs4ResponseContent::GetDevInfo( status, getdevinfo )))
+}
+
 /*https://datatracker.ietf.org/doc/html/rfc5661#section-13.1*/
 // in case of multiple file handles, return handles in a vector
 #[derive(Debug, PartialEq)]
@@ -1065,6 +1121,7 @@ fn nfs4_res_compound_command(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
         NFSPROC4_RECLAIM_COMPLETE => nfs4_res_reclaim_complete(i)?,
         NFSPROC4_SECINFO_NO_NAME => nfs4_res_secinfo_no_name(i)?,
         NFSPROC4_LAYOUTGET => nfs4_res_layoutget(i)?,
+        NFSPROC4_GETDEVINFO => nfs4_res_getdevinfo(i)?,
         _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
     };
     Ok((i, cmd_data))
@@ -1433,6 +1490,28 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_nfs4_request_getdevinfo() {
+        let buf: &[u8] = &[
+            0x00, 0x00, 0x00, 0x2f, /*opcode*/
+            0x01, 0x01, 0x00, 0x00, 0x00, 0xf2, 0xfa, 0x80, // getdevinfo
+            0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x3e, 0x20,
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
+        ];
+
+        let (_, request) = nfs4_req_getdevinfo(&buf[4..]).unwrap();
+        match request {
+            Nfs4RequestContent::GetDevInfo( getdevifo ) => {
+                assert_eq!(getdevifo.device_id, &buf[4..20]);
+                assert_eq!(getdevifo.layout_type, 1);
+                assert_eq!(getdevifo.maxcount, 81440);
+                assert_eq!(getdevifo.notify_mask, 6);
+            }
+            _ => { panic!("Failure"); }
+        }
+    }
+
     #[test]
     fn test_nfs4_attrs() {
         #[rustfmt::skip]
@@ -1843,4 +1922,35 @@ mod tests {
             _ => { panic!("Failure"); }
         }
     }
+
+    #[test]
+    fn test_nfs4_response_getdevinfo() {
+        let buf: &[u8] = &[
+            0x00, 0x00, 0x00, 0x2f, /*opcode*/
+            0x00, 0x00, 0x00, 0x00, /*status*/
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, // getdevinfo
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+            0x00, 0x00, 0x00, 0x03, 0x74, 0x63, 0x70, 0x00,
+            0x00, 0x00, 0x00, 0x10, 0x31, 0x39, 0x32, 0x2e,
+            0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x36, 0x31,
+            0x2e, 0x38, 0x2e, 0x31, 0x00, 0x00, 0x00, 0x00,
+        ];
+
+        let (_, getdevinfo) = nfs4_parse_res_getdevinfo(&buf[8..]).unwrap();
+        assert_eq!(getdevinfo.layout_type, 1);
+        assert_eq!(getdevinfo.r_netid, b"tcp");
+        assert_eq!(getdevinfo.r_addr, b"192.168.0.61.8.1");
+
+        let (_, response) = nfs4_res_getdevinfo(&buf[4..]).unwrap();
+        match response {
+            Nfs4ResponseContent::GetDevInfo(status, getdevinfo_data) => {
+                assert_eq!(status, 0);
+                assert_eq!(getdevinfo_data, Some(getdevinfo))
+            }
+            _ => { panic!("Failure"); }
+        }
+
+
+    }
 }
index d2f4c0707d478bf47695e77da322307a8c5b84e4..feb7b70a2d99e841de3782a441c290f3934d44fa 100644 (file)
@@ -275,6 +275,7 @@ pub const NFSPROC4_WRITE:               u32 = 38;
 pub const NFSPROC4_RELEASE_LOCKOWNER:   u32 = 39;
 pub const NFSPROC4_EXCHANGE_ID:         u32 = 42;
 pub const NFSPROC4_CREATE_SESSION:      u32 = 43;
+pub const NFSPROC4_GETDEVINFO:          u32 = 47;
 pub const NFSPROC4_LAYOUTGET:           u32 = 50;
 pub const NFSPROC4_SECINFO_NO_NAME:     u32 = 52;
 pub const NFSPROC4_SEQUENCE:            u32 = 53;