rust/nfs4: improve NFSPROC4_OPEN op parser

Improve nfs4_res_open() parser to reflect other file-delegation types
Reflect the changes on test_nfs4_response_open() unittest
pull/7112/head
Sam Muhammed 4 years ago committed by Victor Julien
parent df83f7899d
commit fe7a49b737

@ -25,6 +25,11 @@ use nom7::{Err, IResult};
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;
@ -550,8 +555,35 @@ fn nfs4_res_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseContent> {
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)]
@ -559,7 +591,7 @@ pub struct Nfs4ResponseOpenDelegateRead<'a> {
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)?;
@ -567,7 +599,20 @@ fn nfs4_res_open_ok_delegate_read(i: &[u8]) -> IResult<&[u8], Nfs4ResponseOpenDe
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> {
@ -575,13 +620,11 @@ 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))
}
@ -1185,29 +1228,31 @@ mod tests {
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 {

Loading…
Cancel
Save