]> git.ipfire.org Git - people/ms/suricata.git/blame - rust/src/nfs/nfs3_records.rs
rust/nfs: convert parser to nom7 functions (NFS v3 and v4 records)
[people/ms/suricata.git] / rust / src / nfs / nfs3_records.rs
CommitLineData
d6592211
VJ
1/* Copyright (C) 2017 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18//! Nom parsers for RPC & NFSv3
19
42e5065a 20use crate::nfs::nfs_records::*;
0ffe1233
PC
21use nom7::bytes::streaming::take;
22use nom7::combinator::{complete, cond, rest};
23use nom7::multi::{length_data, many0};
24use nom7::number::streaming::{be_u32, be_u64};
25use nom7::IResult;
d6592211 26
0ffe1233 27#[derive(Debug, PartialEq)]
d6592211
VJ
28pub struct Nfs3Handle<'a> {
29 pub len: u32,
0ffe1233 30 pub value: &'a [u8],
d6592211
VJ
31}
32
0ffe1233
PC
33pub fn parse_nfs3_handle(i: &[u8]) -> IResult<&[u8], Nfs3Handle> {
34 let (i, len) = be_u32(i)?;
35 let (i, value) = take(len as usize)(i)?;
36 let handle = Nfs3Handle { len, value };
37 Ok((i, handle))
38}
d6592211 39
0ffe1233 40#[derive(Debug, PartialEq)]
d6592211
VJ
41pub struct Nfs3ReplyCreate<'a> {
42 pub status: u32,
43 pub handle: Option<Nfs3Handle<'a>>,
44}
45
0ffe1233
PC
46pub fn parse_nfs3_response_create(i: &[u8]) -> IResult<&[u8], Nfs3ReplyCreate> {
47 let (i, status) = be_u32(i)?;
48 let (i, handle_has_value) = be_u32(i)?;
49 let (i, handle) = cond(handle_has_value == 1, parse_nfs3_handle)(i)?;
50 let reply = Nfs3ReplyCreate { status, handle };
51 Ok((i, reply))
52}
d6592211 53
0ffe1233 54#[derive(Debug, PartialEq)]
d6592211
VJ
55pub struct Nfs3ReplyLookup<'a> {
56 pub status: u32,
57 pub handle: Nfs3Handle<'a>,
58}
59
0ffe1233
PC
60pub fn parse_nfs3_response_lookup(i: &[u8]) -> IResult<&[u8], Nfs3ReplyLookup> {
61 let (i, status) = be_u32(i)?;
62 let (i, handle) = parse_nfs3_handle(i)?;
63 let reply = Nfs3ReplyLookup { status, handle };
64 Ok((i, reply))
65}
d6592211 66
0ffe1233 67#[derive(Debug, PartialEq)]
d6592211
VJ
68pub struct Nfs3RequestCreate<'a> {
69 pub handle: Nfs3Handle<'a>,
70 pub name_len: u32,
71 pub create_mode: u32,
0ffe1233 72 pub verifier: &'a [u8],
d6592211
VJ
73 pub name_vec: Vec<u8>,
74}
75
0ffe1233
PC
76pub fn parse_nfs3_request_create(i: &[u8]) -> IResult<&[u8], Nfs3RequestCreate> {
77 let (i, handle) = parse_nfs3_handle(i)?;
78 let (i, name_len) = be_u32(i)?;
79 let (i, name) = take(name_len as usize)(i)?;
80 let (i, create_mode) = be_u32(i)?;
81 let (i, verifier) = rest(i)?;
82 let req = Nfs3RequestCreate {
83 handle,
84 name_len,
85 create_mode,
86 verifier,
87 name_vec: name.to_vec(),
88 };
89 Ok((i, req))
90}
d6592211 91
0ffe1233 92#[derive(Debug, PartialEq)]
de7e0614
VJ
93pub struct Nfs3RequestRemove<'a> {
94 pub handle: Nfs3Handle<'a>,
95 pub name_len: u32,
96 pub name_vec: Vec<u8>,
97}
98
0ffe1233
PC
99pub fn parse_nfs3_request_remove(i: &[u8]) -> IResult<&[u8], Nfs3RequestRemove> {
100 let (i, handle) = parse_nfs3_handle(i)?;
101 let (i, name_len) = be_u32(i)?;
102 let (i, name) = take(name_len as usize)(i)?;
103 let (i, _fill_bytes) = rest(i)?;
104 let req = Nfs3RequestRemove {
105 handle,
106 name_len,
107 name_vec: name.to_vec(),
108 };
109 Ok((i, req))
110}
de7e0614 111
0ffe1233 112#[derive(Debug, PartialEq)]
a116c160
VJ
113pub struct Nfs3RequestRmdir<'a> {
114 pub handle: Nfs3Handle<'a>,
115 pub name_vec: Vec<u8>,
116}
117
0ffe1233
PC
118pub fn parse_nfs3_request_rmdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestRmdir> {
119 let (i, handle) = parse_nfs3_handle(i)?;
120 let (i, name_len) = be_u32(i)?;
121 let (i, name) = take(name_len as usize)(i)?;
122 let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
123 let req = Nfs3RequestRmdir {
124 handle,
125 name_vec: name.to_vec(),
126 };
127 Ok((i, req))
128}
a116c160 129
0ffe1233 130#[derive(Debug, PartialEq)]
a116c160
VJ
131pub struct Nfs3RequestMkdir<'a> {
132 pub handle: Nfs3Handle<'a>,
133 pub name_vec: Vec<u8>,
134}
135
0ffe1233
PC
136pub fn parse_nfs3_request_mkdir(i: &[u8]) -> IResult<&[u8], Nfs3RequestMkdir> {
137 let (i, handle) = parse_nfs3_handle(i)?;
138 let (i, name_len) = be_u32(i)?;
139 let (i, name) = take(name_len as usize)(i)?;
140 let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
141 let (i, _attributes) = rest(i)?;
142 let req = Nfs3RequestMkdir {
143 handle,
144 name_vec: name.to_vec(),
145 };
146 Ok((i, req))
147}
a116c160 148
0ffe1233 149#[derive(Debug, PartialEq)]
de7e0614
VJ
150pub struct Nfs3RequestRename<'a> {
151 pub from_handle: Nfs3Handle<'a>,
152 pub from_name_vec: Vec<u8>,
153 pub to_handle: Nfs3Handle<'a>,
154 pub to_name_vec: Vec<u8>,
155}
156
0ffe1233
PC
157pub fn parse_nfs3_request_rename(i: &[u8]) -> IResult<&[u8], Nfs3RequestRename> {
158 let (i, from_handle) = parse_nfs3_handle(i)?;
159 let (i, from_name_len) = be_u32(i)?;
160 let (i, from_name) = take(from_name_len as usize)(i)?;
161 let (i, _from_fill_bytes) = cond(from_name_len % 4 != 0, take(4 - (from_name_len % 4)))(i)?;
162
163 let (i, to_handle) = parse_nfs3_handle(i)?;
164 let (i, to_name_len) = be_u32(i)?;
165 let (i, to_name) = take(to_name_len as usize)(i)?;
166 let (i, _from_fill_bytes) = rest(i)?;
167 let req = Nfs3RequestRename {
168 from_handle,
169 from_name_vec: from_name.to_vec(),
170 to_handle,
171 to_name_vec: to_name.to_vec(),
172 };
173 Ok((i, req))
174}
de7e0614 175
0ffe1233 176#[derive(Debug, PartialEq)]
de7e0614
VJ
177pub struct Nfs3RequestGetAttr<'a> {
178 pub handle: Nfs3Handle<'a>,
179}
180
0ffe1233
PC
181pub fn parse_nfs3_request_getattr(i: &[u8]) -> IResult<&[u8], Nfs3RequestGetAttr> {
182 let (i, handle) = parse_nfs3_handle(i)?;
183 Ok((i, Nfs3RequestGetAttr { handle }))
184}
de7e0614 185
0ffe1233 186#[derive(Debug, PartialEq)]
d6592211
VJ
187pub struct Nfs3RequestAccess<'a> {
188 pub handle: Nfs3Handle<'a>,
189 pub check_access: u32,
190}
191
0ffe1233
PC
192pub fn parse_nfs3_request_access(i: &[u8]) -> IResult<&[u8], Nfs3RequestAccess> {
193 let (i, handle) = parse_nfs3_handle(i)?;
194 let (i, check_access) = be_u32(i)?;
195 let req = Nfs3RequestAccess {
196 handle,
197 check_access,
198 };
199 Ok((i, req))
200}
d6592211 201
0ffe1233 202#[derive(Debug, PartialEq)]
d6592211
VJ
203pub struct Nfs3RequestCommit<'a> {
204 pub handle: Nfs3Handle<'a>,
205}
206
0ffe1233
PC
207pub fn parse_nfs3_request_commit(i: &[u8]) -> IResult<&[u8], Nfs3RequestCommit> {
208 let (i, handle) = parse_nfs3_handle(i)?;
209 let (i, _offset) = be_u64(i)?;
210 let (i, _count) = be_u32(i)?;
211 Ok((i, Nfs3RequestCommit { handle }))
212}
d6592211 213
0ffe1233 214#[derive(Debug, PartialEq)]
d6592211
VJ
215pub struct Nfs3RequestRead<'a> {
216 pub handle: Nfs3Handle<'a>,
217 pub offset: u64,
218}
219
0ffe1233
PC
220pub fn parse_nfs3_request_read(i: &[u8]) -> IResult<&[u8], Nfs3RequestRead> {
221 let (i, handle) = parse_nfs3_handle(i)?;
222 let (i, offset) = be_u64(i)?;
223 let (i, _count) = be_u32(i)?;
224 Ok((i, Nfs3RequestRead { handle, offset }))
225}
d6592211 226
0ffe1233 227#[derive(Debug, PartialEq)]
d6592211
VJ
228pub struct Nfs3RequestLookup<'a> {
229 pub handle: Nfs3Handle<'a>,
230
231 pub name_vec: Vec<u8>,
232}
233
0ffe1233
PC
234pub fn parse_nfs3_request_lookup(i: &[u8]) -> IResult<&[u8], Nfs3RequestLookup> {
235 let (i, handle) = parse_nfs3_handle(i)?;
236 let (i, name_contents) = length_data(be_u32)(i)?;
237 let (i, _name_padding) = rest(i)?;
238 let req = Nfs3RequestLookup {
239 handle,
240 name_vec: name_contents.to_vec(),
241 };
242 Ok((i, req))
243}
d6592211 244
0ffe1233 245#[derive(Debug, PartialEq)]
d6592211
VJ
246pub struct Nfs3ResponseReaddirplusEntryC<'a> {
247 pub name_vec: Vec<u8>,
248 pub handle: Option<Nfs3Handle<'a>>,
249}
250
0ffe1233
PC
251pub fn parse_nfs3_response_readdirplus_entry(
252 i: &[u8],
253) -> IResult<&[u8], Nfs3ResponseReaddirplusEntryC> {
254 let (i, _file_id) = be_u64(i)?;
255 let (i, name_len) = be_u32(i)?;
256 let (i, name_contents) = take(name_len as usize)(i)?;
257 let (i, _fill_bytes) = cond(name_len % 4 != 0, take(4 - (name_len % 4)))(i)?;
258 let (i, _cookie) = take(8_usize)(i)?;
259 let (i, attr_value_follows) = be_u32(i)?;
260 let (i, _attr) = cond(attr_value_follows == 1, take(84_usize))(i)?;
261 let (i, handle_value_follows) = be_u32(i)?;
262 let (i, handle) = cond(handle_value_follows == 1, parse_nfs3_handle)(i)?;
263 let resp = Nfs3ResponseReaddirplusEntryC {
264 name_vec: name_contents.to_vec(),
265 handle,
266 };
267 Ok((i, resp))
268}
d6592211 269
0ffe1233 270#[derive(Debug, PartialEq)]
d6592211
VJ
271pub struct Nfs3ResponseReaddirplusEntry<'a> {
272 pub entry: Option<Nfs3ResponseReaddirplusEntryC<'a>>,
273}
274
0ffe1233
PC
275pub fn parse_nfs3_response_readdirplus_entry_cond(
276 i: &[u8],
277) -> IResult<&[u8], Nfs3ResponseReaddirplusEntry> {
278 let (i, value_follows) = be_u32(i)?;
279 let (i, entry) = cond(value_follows == 1, parse_nfs3_response_readdirplus_entry)(i)?;
280 Ok((i, Nfs3ResponseReaddirplusEntry { entry }))
281}
d6592211 282
0ffe1233 283#[derive(Debug, PartialEq)]
d6592211
VJ
284pub struct Nfs3ResponseReaddirplus<'a> {
285 pub status: u32,
0ffe1233 286 pub data: &'a [u8],
d6592211
VJ
287}
288
0ffe1233
PC
289pub fn parse_nfs3_response_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3ResponseReaddirplus> {
290 let (i, status) = be_u32(i)?;
291 let (i, dir_attr_follows) = be_u32(i)?;
292 let (i, _dir_attr) = cond(dir_attr_follows == 1, take(84_usize))(i)?;
293 let (i, data) = rest(i)?;
294 let resp = Nfs3ResponseReaddirplus { status, data };
295 Ok((i, resp))
296}
d6592211 297
0ffe1233
PC
298pub(crate) fn many0_nfs3_response_readdirplus_entries<'a>(
299 input: &'a [u8],
300) -> IResult<&'a [u8], Vec<Nfs3ResponseReaddirplusEntry<'a>>> {
301 many0(complete(parse_nfs3_response_readdirplus_entry_cond))(input)
2f08b3ea
PC
302}
303
0ffe1233 304#[derive(Debug, PartialEq)]
d6592211
VJ
305pub struct Nfs3RequestReaddirplus<'a> {
306 pub handle: Nfs3Handle<'a>,
307
308 pub cookie: u32,
0ffe1233 309 pub verifier: &'a [u8],
d6592211
VJ
310 pub dircount: u32,
311 pub maxcount: u32,
312}
313
0ffe1233
PC
314pub fn parse_nfs3_request_readdirplus(i: &[u8]) -> IResult<&[u8], Nfs3RequestReaddirplus> {
315 let (i, handle) = parse_nfs3_handle(i)?;
316 let (i, cookie) = be_u32(i)?;
317 let (i, verifier) = take(8_usize)(i)?;
318 let (i, dircount) = be_u32(i)?;
319 let (i, maxcount) = be_u32(i)?;
320 let req = Nfs3RequestReaddirplus {
321 handle,
322 cookie,
323 verifier,
324 dircount,
325 maxcount,
326 };
327 Ok((i, req))
328}
d6592211 329
0ffe1233 330#[derive(Debug, PartialEq)]
d6592211
VJ
331pub struct Nfs3RequestWrite<'a> {
332 pub handle: Nfs3Handle<'a>,
333
334 pub offset: u64,
335 pub count: u32,
336 pub stable: u32,
337 pub file_len: u32,
0ffe1233
PC
338 pub file_data: &'a [u8],
339}
340
341pub fn parse_nfs3_request_write(i: &[u8]) -> IResult<&[u8], Nfs3RequestWrite> {
342 let (i, handle) = parse_nfs3_handle(i)?;
343 let (i, offset) = be_u64(i)?;
344 let (i, count) = be_u32(i)?;
345 let (i, stable) = be_u32(i)?;
346 let (i, file_len) = be_u32(i)?;
347 let (i, file_data) = rest(i)?;
348 let req = Nfs3RequestWrite {
349 handle,
350 offset,
351 count,
352 stable,
353 file_len,
354 file_data,
355 };
356 Ok((i, req))
357}
9edbb6f2 358/*
d6592211
VJ
359#[derive(Debug,PartialEq)]
360pub struct Nfs3ReplyRead<'a> {
361 pub status: u32,
362 pub attr_follows: u32,
363 pub attr_blob: &'a[u8],
364 pub count: u32,
365 pub eof: bool,
366 pub data_len: u32,
367 pub data: &'a[u8], // likely partial
368}
9edbb6f2 369*/
0ffe1233
PC
370pub fn parse_nfs3_reply_read(i: &[u8]) -> IResult<&[u8], NfsReplyRead> {
371 let (i, status) = be_u32(i)?;
372 let (i, attr_follows) = be_u32(i)?;
373 let (i, attr_blob) = take(84_usize)(i)?; // fixed size?
374 let (i, count) = be_u32(i)?;
375 let (i, eof) = be_u32(i)?;
376 let (i, data_len) = be_u32(i)?;
377 let (i, data) = rest(i)?;
378 let reply = NfsReplyRead {
379 status,
380 attr_follows,
381 attr_blob,
382 count,
383 eof: eof != 0,
384 data_len,
385 data,
386 };
387 Ok((i, reply))
388}