use crate::nfs::types::*;
+/*https://datatracker.ietf.org/doc/html/rfc7530 - section 16.16 File Delegation Types */
+const OPEN_DELEGATE_NONE: u32 = 0;
+const OPEN_DELEGATE_READ: u32 = 1;
+const OPEN_DELEGATE_WRITE: u32 = 2;
+
// Maximum number of operations per compound
// Linux defines NFSD_MAX_OPS_PER_COMPOUND to 16 (tested in Linux 5.15.1).
const NFSD_MAX_OPS_PER_COMPOUND: usize = 64;
pub struct Nfs4ResponseOpen<'a> {
pub stateid: Nfs4StateId<'a>,
pub result_flags: u32,
- pub delegation_type: u32,
- pub delegate_read: Option<Nfs4ResponseOpenDelegateRead<'a>>,
+ pub delegate: Nfs4ResponseFileDelegation<'a>,
+}
+
+#[derive(Debug, PartialEq)]
+pub enum Nfs4ResponseFileDelegation<'a> {
+ DelegateRead(Nfs4ResponseOpenDelegateRead<'a>),
+ DelegateWrite(Nfs4ResponseOpenDelegateWrite<'a>),
+ DelegateNone(u32),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Nfs4ResponseOpenDelegateWrite<'a> {
+ pub stateid: Nfs4StateId<'a>,
+ pub who: &'a[u8],
+}
+
+fn nfs4_res_open_ok_delegate_write(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> {
+ let (i, stateid) = nfs4_parse_stateid(i)?;
+ let (i, _recall) = be_u32(i)?;
+ let (i, _space_limit) = be_u32(i)?;
+ let (i, _filesize) = be_u32(i)?;
+ let (i, _access_type) = be_u32(i)?;
+ let (i, _ace_flags) = be_u32(i)?;
+ let (i, _ace_mask) = be_u32(i)?;
+ let (i, who) = nfs4_parse_nfsstring(i)?;
+ Ok((i, Nfs4ResponseFileDelegation::DelegateWrite(Nfs4ResponseOpenDelegateWrite {
+ stateid,
+ who,
+ })))
}
#[derive(Debug,PartialEq)]
pub stateid: Nfs4StateId<'a>,
}
-fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpenDelegateRead> {
+fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> {
let (i, stateid) = nfs4_parse_stateid(i)?;
let (i, _recall) = be_u32(i)?;
let (i, _ace_type) = 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 }))
+ Ok((i, Nfs4ResponseFileDelegation::DelegateRead(Nfs4ResponseOpenDelegateRead {
+ stateid,
+ })))
+}
+
+fn nfs4_parse_file_delegation(i: &[u8]) -> IResult<&[u8], Nfs4ResponseFileDelegation> {
+ let (i, delegation_type) = be_u32(i)?;
+ let (i, file_delegation) = match delegation_type {
+ OPEN_DELEGATE_READ => nfs4_res_open_ok_delegate_read(i)?,
+ OPEN_DELEGATE_WRITE => nfs4_res_open_ok_delegate_write(i)?,
+ OPEN_DELEGATE_NONE => (i, Nfs4ResponseFileDelegation::DelegateNone(OPEN_DELEGATE_NONE)),
+ _ => { return Err(Err::Error(make_error(i, ErrorKind::Switch))); }
+ };
+ Ok((i, file_delegation))
}
fn nfs4_res_open_ok(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpen> {
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 (i, delegate) = nfs4_parse_file_delegation(i)?;
let resp = Nfs4ResponseOpen {
stateid,
result_flags,
- delegation_type,
- delegate_read
+ delegate,
};
Ok((i, resp))
}
0x5b, 0x00, 0x88, 0xd9, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x16, 0xf8, 0x2f, 0xd5, /*_change_info*/
0xdb, 0xb7, 0xfe, 0x38, 0x16, 0xf8, 0x2f, 0xdf,
- 0x21, 0xa8, 0x2a, 0x48,
- 0x00, 0x00, 0x00, 0x04, /*result_flags*/
- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, /*_attrs*/
+ 0x21, 0xa8, 0x2a, 0x48, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, /*_attrs*/
+ 0x00, 0x00, 0x00, 0x00,
+ // delegate_write
0x00, 0x00, 0x00, 0x02, /*delegation_type*/
- // delegate_read
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x01, 0x02, 0x82, 0x14, 0xe0,
0x5b, 0x00, 0x89, 0xd9, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
];
let stateid_buf = &buf[8..24];
let (_, res_stateid) = nfs4_parse_stateid(stateid_buf).unwrap();
+ let delegate_buf = &buf[64..];
+ let (_, delegate) = nfs4_parse_file_delegation(delegate_buf).unwrap();
+
let open_data_buf = &buf[8..];
let (_, res_open_data) = nfs4_res_open_ok(open_data_buf).unwrap();
assert_eq!(res_open_data.stateid, res_stateid);
assert_eq!(res_open_data.result_flags, 4);
- assert_eq!(res_open_data.delegation_type, 2);
- assert_eq!(res_open_data.delegate_read, None);
+ assert_eq!(res_open_data.delegate, delegate);
let (_, response) = nfs4_res_open(&buf[4..]).unwrap();
match response {