smb_msg/
oplock.rs

1use crate::FileId;
2use binrw::prelude::*;
3use modular_bitfield::prelude::*;
4use smb_dtyp::Guid;
5
6#[binrw::binrw]
7#[derive(Debug, PartialEq, Eq)]
8pub struct OplockBreakMsg {
9    #[bw(calc = 24)]
10    #[br(assert(_structure_size == 24))]
11    _structure_size: u16,
12    oplock_level: u8,
13    #[bw(calc = 0)]
14    _reserved: u8,
15    #[bw(calc = 0)]
16    reserved2: u32,
17    file_id: FileId,
18}
19
20#[binrw::binrw]
21#[derive(Debug, PartialEq, Eq)]
22pub struct LeaseBreakNotify {
23    #[bw(calc = 44)]
24    #[br(assert(_structure_size == 44))]
25    _structure_size: u16,
26    new_epoch: u16,
27    ack_required: u32,
28    lease_key: Guid,
29    current_lease_state: LeaseState,
30    new_lease_state: LeaseState,
31    #[bw(calc = 0)]
32    #[br(assert(break_reason == 0))]
33    break_reason: u32,
34    #[bw(calc = 0)]
35    #[br(assert(access_mask_hint == 0))]
36    access_mask_hint: u32,
37    #[bw(calc = 0)]
38    #[br(assert(share_mask_hint == 0))]
39    share_mask_hint: u32,
40}
41
42#[binrw::binrw]
43#[derive(Debug, PartialEq, Eq)]
44#[brw(repr(u8))]
45pub enum OplockLevel {
46    None = 0,
47    II = 1,
48    Exclusive = 2,
49}
50
51#[bitfield]
52#[derive(BinWrite, BinRead, Debug, Default, Clone, Copy, PartialEq, Eq)]
53#[bw(map = |&x| Self::into_bytes(x))]
54#[br(map = Self::from_bytes)]
55pub struct LeaseState {
56    pub read_caching: bool,
57    pub handle_caching: bool,
58    pub write_caching: bool,
59    #[skip]
60    __: B29,
61}
62
63// Those are all the same.
64pub type OplockBreakNotify = OplockBreakMsg;
65pub type OplockBreakAck = OplockBreakMsg;
66pub type OplockBreakResponse = OplockBreakMsg;
67
68#[binrw::binrw]
69#[derive(Debug, PartialEq, Eq)]
70pub struct LeaseBreakAckResponse {
71    #[bw(calc = 36)]
72    #[br(assert(_structure_size == 36))]
73    _structure_size: u16,
74    #[bw(calc = 0)]
75    _reserved: u16,
76    #[bw(calc = 0)] // reserved
77    #[br(assert(flags == 0))]
78    flags: u32,
79    lease_key: Guid,
80    lease_state: LeaseState,
81    #[bw(calc = 0)] // reserved
82    #[br(assert(lease_duration == 0))]
83    lease_duration: u64,
84}
85
86// Those are the same.
87pub type LeaseBreakAck = LeaseBreakAckResponse;
88pub type LeaseBreakResponse = LeaseBreakAckResponse;
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    use smb_tests::*;
94
95    test_binrw! {
96        struct LeaseBreakNotify {
97            new_epoch: 2,
98            ack_required: 1,
99            lease_key: "70c8619e-165d-315e-d492-a01b0cbb3af2".parse().unwrap(),
100            current_lease_state: LeaseState::new()
101                .with_read_caching(true)
102                .with_handle_caching(true),
103            new_lease_state: LeaseState::new(),
104        } => "2c000200010000009e61c8705d165e31d492a01b0cbb3af20300000000000000000000000000000000000000"
105    }
106
107    test_binrw! {
108        struct LeaseBreakAck {
109            lease_key: "70c8619e-165d-315e-d492-a01b0cbb3af2".parse().unwrap(),
110            lease_state: LeaseState::new(),
111        } => "24000000000000009e61c8705d165e31d492a01b0cbb3af2000000000000000000000000"
112    }
113
114    test_binrw! {
115        struct LeaseBreakAckResponse {
116            lease_key: "70c8619e-165d-315e-d492-a01b0cbb3af2".parse().unwrap(),
117            lease_state: LeaseState::new(),
118        } => "24000000000000009e61c8705d165e31d492a01b0cbb3af2000000000000000000000000"
119    }
120}