1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::radius_attr::*;
use nom::bytes::streaming::take;
use nom::combinator::{complete, cond, map, map_parser};
use nom::multi::many1;
use nom::number::streaming::{be_u16, be_u8};
use nom::IResult;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RadiusCode(pub u8);
#[allow(non_upper_case_globals)]
impl RadiusCode {
pub const AccessRequest: RadiusCode = RadiusCode(1);
pub const AccessAccept: RadiusCode = RadiusCode(2);
pub const AccessReject: RadiusCode = RadiusCode(3);
pub const AccountingRequest: RadiusCode = RadiusCode(4);
pub const AccountingResponse: RadiusCode = RadiusCode(5);
pub const AccessChallenge: RadiusCode = RadiusCode(11);
pub const StatusServer: RadiusCode = RadiusCode(12);
pub const StatusClient: RadiusCode = RadiusCode(13);
pub const Reserved: RadiusCode = RadiusCode(255);
}
#[derive(Clone, Debug, PartialEq)]
pub struct RadiusData<'a> {
pub code: RadiusCode,
pub identifier: u8,
pub length: u16,
pub authenticator: &'a [u8],
pub attributes: Option<Vec<RadiusAttribute<'a>>>,
}
pub fn parse_radius_data(i: &[u8]) -> IResult<&[u8], RadiusData> {
let (i, code) = map(be_u8, RadiusCode)(i)?;
let (i, identifier) = be_u8(i)?;
let (i, length) = be_u16(i)?;
let (i, authenticator) = take(16usize)(i)?;
let (i, attributes) = cond(
length > 20,
map_parser(
|d| take(length - 20)(d),
many1(complete(parse_radius_attribute)),
),
)(i)?;
let data = RadiusData {
code,
identifier,
length,
authenticator,
attributes,
};
Ok((i, data))
}