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