mirror of
https://github.com/cubixle/radius-rs.git
synced 2026-05-01 00:38:40 +01:00
Restructure the project tree
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "radius"
|
||||
version = "0.1.0"
|
||||
authors = ["moznion <moznion@gmail.com>"]
|
||||
edition = "2018"
|
||||
license-file = "../LICENSE"
|
||||
repository = "https://github.com/moznion/radius-rs"
|
||||
keywords = ["radius"]
|
||||
|
||||
[dependencies]
|
||||
md5 = "0.7.0"
|
||||
chrono = "0.4"
|
||||
rand = "0.7.3"
|
||||
num_enum = "0.5.1"
|
||||
thiserror = "1.0"
|
||||
@@ -0,0 +1,85 @@
|
||||
use crate::avp::{AVPType, AVP};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) struct Attributes(pub(crate) Vec<AVP>);
|
||||
|
||||
impl Attributes {
|
||||
pub(crate) fn decode(bs: &[u8]) -> Result<Attributes, String> {
|
||||
let mut i = 0;
|
||||
let mut attrs = Vec::new();
|
||||
|
||||
while bs.len() > i {
|
||||
if bs[i..].len() < 2 {
|
||||
return Err("short buffer".to_owned());
|
||||
}
|
||||
|
||||
let length = bs[i + 1] as usize;
|
||||
if length > bs[i..].len() || length < 2 || length > 255 {
|
||||
return Err("invalid attribute length".to_owned());
|
||||
}
|
||||
|
||||
attrs.push(AVP {
|
||||
typ: bs[i],
|
||||
value: if length > 2 {
|
||||
bs[i + 2..i + length].to_vec()
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
});
|
||||
|
||||
i += length;
|
||||
}
|
||||
|
||||
Ok(Attributes(attrs))
|
||||
}
|
||||
|
||||
pub(crate) fn add(&mut self, avp: AVP) {
|
||||
self.0.push(avp)
|
||||
}
|
||||
|
||||
pub(crate) fn del(&mut self, typ: AVPType) {
|
||||
self.0 = self
|
||||
.0
|
||||
.iter()
|
||||
.filter(|&avp| avp.typ != typ)
|
||||
.cloned()
|
||||
.collect();
|
||||
}
|
||||
|
||||
pub(crate) fn lookup(&self, typ: AVPType) -> Option<&AVP> {
|
||||
self.0.iter().find_map(|avp| {
|
||||
if avp.typ == typ {
|
||||
return Some(avp);
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn lookup_all(&self, typ: AVPType) -> Vec<&AVP> {
|
||||
self.0
|
||||
.iter()
|
||||
.filter_map(|avp| {
|
||||
if avp.typ == typ {
|
||||
return Some(avp);
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn encode(&self) -> Result<Vec<u8>, String> {
|
||||
let mut encoded: Vec<u8> = Vec::new();
|
||||
|
||||
for avp in &self.0 {
|
||||
let attr_len = avp.value.len();
|
||||
if attr_len > 253 {
|
||||
return Err("attribute is too large".to_owned());
|
||||
}
|
||||
encoded.push(avp.typ);
|
||||
encoded.push(2 + attr_len as u8);
|
||||
encoded.extend(&avp.value);
|
||||
}
|
||||
|
||||
Ok(encoded)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
use std::convert::TryInto;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AVPError {
|
||||
#[error(
|
||||
"the maximum length of the plain text is 128, but the given value is longer than that"
|
||||
)]
|
||||
PlainTextMaximumLengthExceededError(),
|
||||
#[error("secret hasn't be empty, but the given value is empty")]
|
||||
SecretMissingError(),
|
||||
#[error("request authenticator has to have 16-bytes payload, but the given value doesn't")]
|
||||
InvalidRequestAuthenticatorLength(),
|
||||
#[error("invalid attribute length: {0}")]
|
||||
InvalidAttributeLengthError(usize),
|
||||
#[error("unexpected decoding error: {0}")]
|
||||
UnexpectedDecodingError(String),
|
||||
}
|
||||
|
||||
pub type AVPType = u8;
|
||||
|
||||
pub const TYPE_INVALID: AVPType = 255;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct AVP {
|
||||
pub(crate) typ: AVPType,
|
||||
pub(crate) value: Vec<u8>,
|
||||
}
|
||||
|
||||
impl AVP {
|
||||
pub fn encode_u32(typ: AVPType, value: u32) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: u32::to_be_bytes(value).to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_string(typ: AVPType, value: &str) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: value.as_bytes().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_bytes(typ: AVPType, value: &[u8]) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: value.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_ipv4(typ: AVPType, value: &Ipv4Addr) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: value.octets().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_ipv6(typ: AVPType, value: &Ipv6Addr) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: value.octets().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_user_password(
|
||||
typ: AVPType,
|
||||
plain_text: &[u8],
|
||||
secret: &[u8],
|
||||
request_authenticator: &[u8],
|
||||
) -> Result<Self, AVPError> {
|
||||
// Call the shared secret S and the pseudo-random 128-bit Request
|
||||
// Authenticator RA. Break the password into 16-octet chunks p1, p2,
|
||||
// etc. with the last one padded at the end with nulls to a 16-octet
|
||||
// boundary. Call the ciphertext blocks c(1), c(2), etc. We'll need
|
||||
// intermediate values b1, b2, etc.
|
||||
//
|
||||
// b1 = MD5(S + RA) c(1) = p1 xor b1
|
||||
// b2 = MD5(S + c(1)) c(2) = p2 xor b2
|
||||
// . .
|
||||
// . .
|
||||
// . .
|
||||
// bi = MD5(S + c(i-1)) c(i) = pi xor bi
|
||||
//
|
||||
// ref: https://tools.ietf.org/html/rfc2865#section-5.2
|
||||
|
||||
if plain_text.len() > 128 {
|
||||
return Err(AVPError::PlainTextMaximumLengthExceededError());
|
||||
}
|
||||
|
||||
if secret.is_empty() {
|
||||
return Err(AVPError::SecretMissingError());
|
||||
}
|
||||
|
||||
if request_authenticator.len() != 16 {
|
||||
return Err(AVPError::InvalidRequestAuthenticatorLength());
|
||||
}
|
||||
|
||||
let mut buff = request_authenticator.to_vec();
|
||||
|
||||
let l = plain_text.len();
|
||||
if l < 16 {
|
||||
let enc = md5::compute([secret, &buff[..]].concat()).to_vec();
|
||||
return Ok(AVP {
|
||||
typ,
|
||||
value: enc
|
||||
.iter()
|
||||
.zip([plain_text, vec![0 as u8; 16 - l].as_slice()].concat())
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ zero padding
|
||||
.map(|(d, p)| d ^ p)
|
||||
.collect(),
|
||||
});
|
||||
}
|
||||
|
||||
let mut enc: Vec<u8> = Vec::new();
|
||||
for chunk in plain_text.chunks(16) {
|
||||
let mut chunk_vec = chunk.to_vec();
|
||||
let l = chunk.len();
|
||||
if l < 16 {
|
||||
chunk_vec.extend(vec![0 as u8; 16 - l]); // zero padding
|
||||
}
|
||||
|
||||
let enc_block = md5::compute([secret, &buff[..]].concat()).to_vec();
|
||||
buff = enc_block
|
||||
.iter()
|
||||
.zip(chunk_vec)
|
||||
.map(|(d, p)| d ^ p)
|
||||
.collect();
|
||||
enc.extend(&buff);
|
||||
}
|
||||
|
||||
Ok(AVP { typ, value: enc })
|
||||
}
|
||||
|
||||
pub fn encode_date(typ: AVPType, dt: &DateTime<Utc>) -> Self {
|
||||
AVP {
|
||||
typ,
|
||||
value: u32::to_be_bytes(dt.timestamp() as u32).to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_u32(&self) -> Result<u32, AVPError> {
|
||||
const U32_SIZE: usize = std::mem::size_of::<u32>();
|
||||
if self.value.len() != U32_SIZE {
|
||||
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
|
||||
}
|
||||
|
||||
let (int_bytes, _) = self.value.split_at(U32_SIZE);
|
||||
match int_bytes.try_into() {
|
||||
Ok(boxed_array) => Ok(u32::from_be_bytes(boxed_array)),
|
||||
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_string(&self) -> Result<String, AVPError> {
|
||||
match String::from_utf8(self.value.to_vec()) {
|
||||
Ok(str) => Ok(str),
|
||||
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_bytes(&self) -> Vec<u8> {
|
||||
self.value.to_vec()
|
||||
}
|
||||
|
||||
pub fn decode_ipv4(&self) -> Result<Ipv4Addr, AVPError> {
|
||||
const IPV4_SIZE: usize = std::mem::size_of::<Ipv4Addr>();
|
||||
if self.value.len() != IPV4_SIZE {
|
||||
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
|
||||
}
|
||||
|
||||
let (int_bytes, _) = self.value.split_at(IPV4_SIZE);
|
||||
match int_bytes.try_into() {
|
||||
Ok::<[u8; IPV4_SIZE], _>(boxed_array) => Ok(Ipv4Addr::from(boxed_array)),
|
||||
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_ipv6(&self) -> Result<Ipv6Addr, AVPError> {
|
||||
const IPV6_SIZE: usize = std::mem::size_of::<Ipv6Addr>();
|
||||
if self.value.len() != IPV6_SIZE {
|
||||
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
|
||||
}
|
||||
|
||||
let (int_bytes, _) = self.value.split_at(IPV6_SIZE);
|
||||
match int_bytes.try_into() {
|
||||
Ok::<[u8; IPV6_SIZE], _>(boxed_array) => Ok(Ipv6Addr::from(boxed_array)),
|
||||
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_user_password(
|
||||
&self,
|
||||
secret: &[u8],
|
||||
request_authenticator: &[u8],
|
||||
) -> Result<Vec<u8>, AVPError> {
|
||||
if self.value.len() < 16 || self.value.len() > 128 {
|
||||
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
|
||||
}
|
||||
|
||||
if secret.is_empty() {
|
||||
return Err(AVPError::SecretMissingError());
|
||||
}
|
||||
|
||||
if request_authenticator.len() != 16 {
|
||||
return Err(AVPError::InvalidRequestAuthenticatorLength());
|
||||
}
|
||||
|
||||
let mut dec: Vec<u8> = Vec::new();
|
||||
let mut buff: Vec<u8> = request_authenticator.to_vec();
|
||||
|
||||
// NOTE:
|
||||
// It ensures attribute value has 16 bytes length at least because the value is encoded by md5.
|
||||
// And this must be aligned by each 16 bytes length.
|
||||
for chunk in self.value.chunks(16) {
|
||||
let chunk_vec = chunk.to_vec();
|
||||
let dec_block = md5::compute([secret, &buff[..]].concat()).to_vec();
|
||||
dec.extend(
|
||||
dec_block
|
||||
.iter()
|
||||
.zip(&chunk_vec)
|
||||
.map(|(d, p)| d ^ p)
|
||||
.collect::<Vec<u8>>(),
|
||||
);
|
||||
buff = chunk_vec.clone();
|
||||
}
|
||||
|
||||
// remove trailing zero bytes
|
||||
match dec.split(|b| *b == 0).next() {
|
||||
Some(dec) => Ok(dec.to_vec()),
|
||||
None => Ok(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_date(&self) -> Result<DateTime<Utc>, AVPError> {
|
||||
const U32_SIZE: usize = std::mem::size_of::<u32>();
|
||||
if self.value.len() != U32_SIZE {
|
||||
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
|
||||
}
|
||||
|
||||
let (int_bytes, _) = self.value.split_at(U32_SIZE);
|
||||
match int_bytes.try_into() {
|
||||
Ok(boxed_array) => {
|
||||
let timestamp = u32::from_be_bytes(boxed_array);
|
||||
Ok(Utc.timestamp(timestamp as i64, 0))
|
||||
}
|
||||
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
use chrono::Utc;
|
||||
|
||||
use crate::avp::{AVPError, AVP};
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_attribute_to_integer32() -> Result<(), AVPError> {
|
||||
let given_u32 = 16909060;
|
||||
let avp = AVP::encode_u32(1, given_u32);
|
||||
assert_eq!(avp.decode_u32()?, given_u32);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_attribute_to_string() -> Result<(), AVPError> {
|
||||
let given_str = "Hello, World";
|
||||
let avp = AVP::encode_string(1, given_str);
|
||||
assert_eq!(avp.decode_string()?, given_str);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_attribute_to_byte() {
|
||||
let given_bytes = b"Hello, World";
|
||||
let avp = AVP::encode_bytes(1, given_bytes);
|
||||
assert_eq!(avp.decode_bytes(), given_bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_ipv4() -> Result<(), AVPError> {
|
||||
let given_ipv4 = Ipv4Addr::new(192, 0, 2, 1);
|
||||
let avp = AVP::encode_ipv4(1, &given_ipv4);
|
||||
assert_eq!(avp.decode_ipv4()?, given_ipv4);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_ipv6() -> Result<(), AVPError> {
|
||||
let given_ipv6 = Ipv6Addr::new(
|
||||
0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001,
|
||||
);
|
||||
let avp = AVP::encode_ipv6(1, &given_ipv6);
|
||||
assert_eq!(avp.decode_ipv6()?, given_ipv6);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_user_password() {
|
||||
let secret = b"12345".to_vec();
|
||||
let request_authenticator = b"0123456789abcdef".to_vec();
|
||||
|
||||
struct TestCase<'a> {
|
||||
plain_text: &'a str,
|
||||
expected_encoded_len: usize,
|
||||
};
|
||||
|
||||
let test_cases = &[
|
||||
TestCase {
|
||||
plain_text: "",
|
||||
expected_encoded_len: 16,
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "abc",
|
||||
expected_encoded_len: 16,
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "0123456789abcde",
|
||||
expected_encoded_len: 16,
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "0123456789abcdef",
|
||||
expected_encoded_len: 16,
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "0123456789abcdef0",
|
||||
expected_encoded_len: 32,
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||
expected_encoded_len: 48,
|
||||
},
|
||||
];
|
||||
|
||||
for test_case in test_cases {
|
||||
let user_password_avp_result = AVP::encode_user_password(
|
||||
1,
|
||||
test_case.plain_text.as_bytes(),
|
||||
&secret,
|
||||
&request_authenticator,
|
||||
);
|
||||
let avp = user_password_avp_result.unwrap();
|
||||
assert_eq!(avp.value.len(), test_case.expected_encoded_len);
|
||||
|
||||
let decoded_password = avp
|
||||
.decode_user_password(&secret, &request_authenticator)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
String::from_utf8(decoded_password).unwrap(),
|
||||
test_case.plain_text
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_convert_date() -> Result<(), AVPError> {
|
||||
let now = Utc::now();
|
||||
let avp = AVP::encode_date(1, &now);
|
||||
assert_eq!(avp.decode_date()?.timestamp(), now.timestamp(),);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum Code {
|
||||
AccessRequest = 1,
|
||||
AccessAccept = 2,
|
||||
AccessReject = 3,
|
||||
AccountingRequest = 4,
|
||||
AccountingResponse = 5,
|
||||
AccessChallenge = 11,
|
||||
StatusServer = 12,
|
||||
StatusClient = 13,
|
||||
DisconnectRequest = 40,
|
||||
DisconnectACK = 41,
|
||||
DisconnectNAK = 42,
|
||||
CoARequest = 43,
|
||||
CoAACK = 44,
|
||||
CoANAK = 45,
|
||||
Reserved = 255,
|
||||
Invalid = 0,
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn string(&self) -> &'static str {
|
||||
match self {
|
||||
Code::AccessRequest => "Access-Request",
|
||||
Code::AccessAccept => "Access-Accept",
|
||||
Code::AccessReject => "Access-Reject",
|
||||
Code::AccountingRequest => "Accounting-Request",
|
||||
Code::AccountingResponse => "Accounting-Response",
|
||||
Code::AccessChallenge => "Access-Challenge",
|
||||
Code::StatusServer => "Status-Server",
|
||||
Code::StatusClient => "Status-Client",
|
||||
Code::DisconnectRequest => "Disconnect-Request",
|
||||
Code::DisconnectACK => "Disconnect-ACK",
|
||||
Code::DisconnectNAK => "Disconnect-NAK",
|
||||
Code::CoARequest => "CoA-Request",
|
||||
Code::CoAACK => "CoA-ACK",
|
||||
Code::CoANAK => "CoA-NAK",
|
||||
Code::Reserved => "Reserved",
|
||||
Code::Invalid => "Invalid",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(value: u8) -> Self {
|
||||
match Code::try_from(value) {
|
||||
Ok(code) => code,
|
||||
Err(_) => Code::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
pub(crate) mod attributes;
|
||||
pub mod avp;
|
||||
pub mod code;
|
||||
pub mod packet;
|
||||
pub mod request;
|
||||
pub mod rfc2865;
|
||||
pub mod rfc2866;
|
||||
pub mod rfc2867;
|
||||
@@ -0,0 +1,490 @@
|
||||
use std::convert::TryInto;
|
||||
|
||||
use rand::Rng;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::attributes::Attributes;
|
||||
use crate::avp::{AVPType, AVP};
|
||||
use crate::code::Code;
|
||||
|
||||
const MAX_PACKET_LENGTH: usize = 4096;
|
||||
const RADIUS_PACKET_HEADER_LENGTH: usize = 20; // i.e. minimum packet length
|
||||
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
pub enum PacketError {
|
||||
#[error("radius packet doesn't have enough length of bytes; it has to be at least {0} bytes")]
|
||||
InsufficientPacketLengthError(usize),
|
||||
#[error("invalid radius packet length: {0}")]
|
||||
InvalidPacketLengthError(usize),
|
||||
#[error("unexpected decoding error: {0}")]
|
||||
UnexpectedDecodingError(String),
|
||||
#[error("failed to decode the packet: {0}")]
|
||||
DecodingError(String),
|
||||
#[error("failed to encode the packet: {0}")]
|
||||
EncodingError(String),
|
||||
#[error("Unknown radius packet code: {0}")]
|
||||
UnknownCodeError(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Packet {
|
||||
code: Code,
|
||||
identifier: u8,
|
||||
authenticator: Vec<u8>,
|
||||
secret: Vec<u8>,
|
||||
attributes: Attributes,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
pub fn new(code: Code, secret: &[u8]) -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
let authenticator = (0..16).map(|_| rng.gen()).collect::<Vec<u8>>();
|
||||
Packet {
|
||||
code: code.to_owned(),
|
||||
identifier: rng.gen(),
|
||||
authenticator,
|
||||
secret: secret.to_owned(),
|
||||
attributes: Attributes(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_code(&self) -> Code {
|
||||
self.code
|
||||
}
|
||||
|
||||
pub fn get_identifier(&self) -> u8 {
|
||||
self.identifier
|
||||
}
|
||||
|
||||
pub fn get_secret(&self) -> &Vec<u8> {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
pub fn get_authenticator(&self) -> &Vec<u8> {
|
||||
&self.authenticator
|
||||
}
|
||||
|
||||
pub fn decode(bs: &[u8], secret: &[u8]) -> Result<Self, PacketError> {
|
||||
if bs.len() < RADIUS_PACKET_HEADER_LENGTH {
|
||||
return Err(PacketError::InsufficientPacketLengthError(
|
||||
RADIUS_PACKET_HEADER_LENGTH,
|
||||
));
|
||||
}
|
||||
|
||||
let len = match bs[2..4].try_into() {
|
||||
Ok(v) => u16::from_be_bytes(v),
|
||||
Err(e) => return Err(PacketError::UnexpectedDecodingError(e.to_string())),
|
||||
} as usize;
|
||||
if len < RADIUS_PACKET_HEADER_LENGTH || len > MAX_PACKET_LENGTH || bs.len() < len {
|
||||
return Err(PacketError::InvalidPacketLengthError(len));
|
||||
}
|
||||
|
||||
let attributes = match Attributes::decode(&bs[RADIUS_PACKET_HEADER_LENGTH..len].to_vec()) {
|
||||
Ok(attributes) => attributes,
|
||||
Err(e) => return Err(PacketError::DecodingError(e)),
|
||||
};
|
||||
|
||||
Ok(Packet {
|
||||
code: Code::from(bs[0]),
|
||||
identifier: bs[1],
|
||||
authenticator: bs[4..RADIUS_PACKET_HEADER_LENGTH].to_owned(),
|
||||
secret: secret.to_owned(),
|
||||
attributes,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_response_packet(&self, code: Code) -> Self {
|
||||
Packet {
|
||||
code,
|
||||
identifier: self.identifier,
|
||||
authenticator: self.authenticator.clone(),
|
||||
secret: self.secret.clone(),
|
||||
attributes: Attributes(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode(&self) -> Result<Vec<u8>, PacketError> {
|
||||
let mut bs = match self.marshal_binary() {
|
||||
Ok(bs) => bs,
|
||||
Err(e) => return Err(PacketError::EncodingError(e)),
|
||||
};
|
||||
|
||||
match self.code {
|
||||
Code::AccessRequest | Code::StatusServer => Ok(bs),
|
||||
Code::AccessAccept
|
||||
| Code::AccessReject
|
||||
| Code::AccountingRequest
|
||||
| Code::AccessChallenge
|
||||
| Code::DisconnectRequest
|
||||
| Code::DisconnectACK
|
||||
| Code::DisconnectNAK
|
||||
| Code::CoARequest
|
||||
| Code::CoAACK
|
||||
| Code::CoANAK => {
|
||||
let mut buf: Vec<u8> = bs[..4].to_vec();
|
||||
match self.code {
|
||||
Code::AccountingRequest | Code::DisconnectRequest | Code::CoARequest => {
|
||||
buf.extend(vec![
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
]);
|
||||
}
|
||||
_ => {
|
||||
buf.extend(self.authenticator.clone()); // TODO take from `bs`?
|
||||
}
|
||||
}
|
||||
buf.extend(bs[RADIUS_PACKET_HEADER_LENGTH..].to_vec());
|
||||
buf.extend(&self.secret);
|
||||
bs.splice(4..20, md5::compute(&buf).to_vec());
|
||||
|
||||
Ok(bs)
|
||||
}
|
||||
_ => Err(PacketError::UnknownCodeError(format!("{:?}", self.code))),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Binary structure:
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Code | Identifier | Length |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | |
|
||||
* | Authenticator |
|
||||
* | |
|
||||
* | |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Attributes ...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-
|
||||
*/
|
||||
fn marshal_binary(&self) -> Result<Vec<u8>, String> {
|
||||
let encoded_avp = match self.attributes.encode() {
|
||||
Ok(encoded) => encoded,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
let size = RADIUS_PACKET_HEADER_LENGTH as u16 + encoded_avp.len() as u16;
|
||||
if size as usize > MAX_PACKET_LENGTH {
|
||||
return Err("packet is too large".to_owned());
|
||||
}
|
||||
|
||||
let mut bs: Vec<u8> = Vec::new();
|
||||
bs.push(self.code as u8);
|
||||
bs.push(self.identifier);
|
||||
bs.extend(u16::to_be_bytes(size).to_vec());
|
||||
bs.extend(self.authenticator.to_vec());
|
||||
bs.extend(match self.attributes.encode() {
|
||||
Ok(encoded) => encoded,
|
||||
Err(e) => return Err(e),
|
||||
});
|
||||
Ok(bs)
|
||||
}
|
||||
|
||||
pub fn is_authentic_response(response: &[u8], request: &[u8], secret: &[u8]) -> bool {
|
||||
if response.len() < RADIUS_PACKET_HEADER_LENGTH
|
||||
|| request.len() < RADIUS_PACKET_HEADER_LENGTH
|
||||
|| secret.is_empty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
md5::compute(
|
||||
[
|
||||
&response[..4],
|
||||
&request[4..RADIUS_PACKET_HEADER_LENGTH],
|
||||
&response[RADIUS_PACKET_HEADER_LENGTH..],
|
||||
&secret,
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
.to_vec()
|
||||
.eq(&response[4..RADIUS_PACKET_HEADER_LENGTH].to_vec())
|
||||
}
|
||||
|
||||
pub fn is_authentic_request(request: &[u8], secret: &[u8]) -> bool {
|
||||
if request.len() < RADIUS_PACKET_HEADER_LENGTH || secret.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
match Code::from(request[0]) {
|
||||
Code::AccessRequest | Code::StatusServer => true,
|
||||
Code::AccountingRequest | Code::DisconnectRequest | Code::CoARequest => md5::compute(
|
||||
[
|
||||
&request[..4],
|
||||
&[
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
&request[RADIUS_PACKET_HEADER_LENGTH..],
|
||||
&secret,
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
.to_vec()
|
||||
.eq(&request[4..RADIUS_PACKET_HEADER_LENGTH].to_vec()),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, avp: AVP) {
|
||||
self.attributes.add(avp);
|
||||
}
|
||||
|
||||
pub fn delete(&mut self, typ: AVPType) {
|
||||
self.attributes.del(typ);
|
||||
}
|
||||
|
||||
pub fn lookup(&self, typ: AVPType) -> Option<&AVP> {
|
||||
self.attributes.lookup(typ)
|
||||
}
|
||||
|
||||
pub fn lookup_all(&self, typ: AVPType) -> Vec<&AVP> {
|
||||
self.attributes.lookup_all(typ)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::avp::AVP;
|
||||
use crate::code::Code;
|
||||
use crate::packet::{Packet, PacketError};
|
||||
use crate::rfc2865;
|
||||
|
||||
#[test]
|
||||
fn test_for_rfc2865_7_1() -> Result<(), PacketError> {
|
||||
// ref: https://tools.ietf.org/html/rfc2865#section-7.1
|
||||
|
||||
let secret: Vec<u8> = "xyzzy5461".as_bytes().to_vec();
|
||||
let request: Vec<u8> = vec![
|
||||
0x01, 0x00, 0x00, 0x38, 0x0f, 0x40, 0x3f, 0x94, 0x73, 0x97, 0x80, 0x57, 0xbd, 0x83,
|
||||
0xd5, 0xcb, 0x98, 0xf4, 0x22, 0x7a, 0x01, 0x06, 0x6e, 0x65, 0x6d, 0x6f, 0x02, 0x12,
|
||||
0x0d, 0xbe, 0x70, 0x8d, 0x93, 0xd4, 0x13, 0xce, 0x31, 0x96, 0xe4, 0x3f, 0x78, 0x2a,
|
||||
0x0a, 0xee, 0x04, 0x06, 0xc0, 0xa8, 0x01, 0x10, 0x05, 0x06, 0x00, 0x00, 0x00, 0x03,
|
||||
];
|
||||
|
||||
let request_packet = Packet::decode(&request, &secret)?;
|
||||
assert_eq!(request_packet.code, Code::AccessRequest);
|
||||
assert_eq!(request_packet.identifier, 0);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_user_name(&request_packet).unwrap().unwrap(),
|
||||
"nemo"
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_user_password(&request_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
b"arctangent"
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_nas_ip_address(&request_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Ipv4Addr::from([192, 168, 1, 16]),
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_nas_port(&request_packet).unwrap().unwrap(),
|
||||
3
|
||||
);
|
||||
assert_eq!(request_packet.encode().unwrap(), request);
|
||||
assert_eq!(Packet::is_authentic_request(&request, &secret), true);
|
||||
|
||||
let response: Vec<u8> = vec![
|
||||
0x02, 0x00, 0x00, 0x26, 0x86, 0xfe, 0x22, 0x0e, 0x76, 0x24, 0xba, 0x2a, 0x10, 0x05,
|
||||
0xf6, 0xbf, 0x9b, 0x55, 0xe0, 0xb2, 0x06, 0x06, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0x06, 0xc0, 0xa8, 0x01, 0x03,
|
||||
];
|
||||
let mut response_packet = request_packet.make_response_packet(Code::AccessAccept);
|
||||
rfc2865::add_service_type(&mut response_packet, rfc2865::SERVICE_TYPE_LOGIN_USER);
|
||||
rfc2865::add_login_service(&mut response_packet, rfc2865::LOGIN_SERVICE_TELNET);
|
||||
rfc2865::add_login_ip_host(&mut response_packet, &Ipv4Addr::from([192, 168, 1, 3]));
|
||||
assert_eq!(response_packet.encode().unwrap(), response);
|
||||
assert_eq!(
|
||||
Packet::is_authentic_response(&response, &request, &secret),
|
||||
true
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_for_rfc2865_7_2() -> Result<(), PacketError> {
|
||||
let secret: Vec<u8> = "xyzzy5461".as_bytes().to_vec();
|
||||
let request: Vec<u8> = vec![
|
||||
0x01, 0x01, 0x00, 0x47, 0x2a, 0xee, 0x86, 0xf0, 0x8d, 0x0d, 0x55, 0x96, 0x9c, 0xa5,
|
||||
0x97, 0x8e, 0x0d, 0x33, 0x67, 0xa2, 0x01, 0x08, 0x66, 0x6c, 0x6f, 0x70, 0x73, 0x79,
|
||||
0x03, 0x13, 0x16, 0xe9, 0x75, 0x57, 0xc3, 0x16, 0x18, 0x58, 0x95, 0xf2, 0x93, 0xff,
|
||||
0x63, 0x44, 0x07, 0x72, 0x75, 0x04, 0x06, 0xc0, 0xa8, 0x01, 0x10, 0x05, 0x06, 0x00,
|
||||
0x00, 0x00, 0x14, 0x06, 0x06, 0x00, 0x00, 0x00, 0x02, 0x07, 0x06, 0x00, 0x00, 0x00,
|
||||
0x01,
|
||||
];
|
||||
|
||||
let request_packet = Packet::decode(&request, &secret)?;
|
||||
assert_eq!(request_packet.get_code(), Code::AccessRequest);
|
||||
assert_eq!(request_packet.identifier, 1);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_user_name(&request_packet).unwrap().unwrap(),
|
||||
"flopsy"
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_nas_ip_address(&request_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Ipv4Addr::from([192, 168, 1, 16]),
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_nas_port(&request_packet).unwrap().unwrap(),
|
||||
20
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_service_type(&request_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::SERVICE_TYPE_FRAMED_USER,
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_protocol(&request_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::FRAMED_PROTOCOL_PPP,
|
||||
);
|
||||
|
||||
let response: Vec<u8> = vec![
|
||||
0x02, 0x01, 0x00, 0x38, 0x15, 0xef, 0xbc, 0x7d, 0xab, 0x26, 0xcf, 0xa3, 0xdc, 0x34,
|
||||
0xd9, 0xc0, 0x3c, 0x86, 0x01, 0xa4, 0x06, 0x06, 0x00, 0x00, 0x00, 0x02, 0x07, 0x06,
|
||||
0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0xff, 0xff, 0xff, 0xfe, 0x0a, 0x06, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x06, 0x00, 0x00, 0x05,
|
||||
// ^ incorrectly a 2 in the document
|
||||
0xdc,
|
||||
];
|
||||
let response_packet = Packet::decode(&response, &secret).unwrap();
|
||||
|
||||
assert_eq!(response_packet.get_code(), Code::AccessAccept);
|
||||
assert_eq!(response_packet.get_identifier(), 1);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_service_type(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::SERVICE_TYPE_FRAMED_USER
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_protocol(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::FRAMED_PROTOCOL_PPP,
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_ip_address(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
Ipv4Addr::from([255, 255, 255, 254]),
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_routing(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::FRAMED_ROUTING_NONE,
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_compression(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
rfc2865::FRAMED_COMPRESSION_VAN_JACOBSON_TCP_IP,
|
||||
);
|
||||
assert_eq!(
|
||||
rfc2865::lookup_framed_mtu(&response_packet)
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
1500,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_passwords() {
|
||||
let passwords = vec![
|
||||
b"".to_vec(),
|
||||
b"qwerty".to_vec(),
|
||||
b"helloworld1231231231231233489hegufudhsgdsfygdf8g".to_vec(),
|
||||
];
|
||||
|
||||
let secret = b"xyzzy5461";
|
||||
|
||||
for password in passwords {
|
||||
let mut request_packet = Packet::new(Code::AccessRequest, secret);
|
||||
rfc2865::add_user_password(&mut request_packet, &password).unwrap();
|
||||
|
||||
let encoded = request_packet.encode().unwrap();
|
||||
|
||||
let decoded = Packet::decode(&encoded, secret).unwrap();
|
||||
assert_eq!(
|
||||
rfc2865::lookup_user_password(&decoded).unwrap().unwrap(),
|
||||
password
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_invalid() {
|
||||
struct TestCase<'a> {
|
||||
plain_text: &'a str,
|
||||
expected_error: PacketError,
|
||||
};
|
||||
|
||||
let test_cases = &[
|
||||
TestCase {
|
||||
plain_text: "\x01",
|
||||
expected_error: PacketError::InsufficientPacketLengthError(20),
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "\x01\x7f\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",
|
||||
expected_error: PacketError::InvalidPacketLengthError(0),
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "\x01\x7f\x7f\x7f\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",
|
||||
expected_error: PacketError::InvalidPacketLengthError(32639),
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "\x00\x7f\x00\x16\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00",
|
||||
expected_error: PacketError::InvalidPacketLengthError(22),
|
||||
},
|
||||
TestCase {
|
||||
plain_text: "\x01\x01\x00\x16\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00",
|
||||
expected_error: PacketError::DecodingError("invalid attribute length".to_owned()),
|
||||
}
|
||||
];
|
||||
|
||||
let secret = b"12345";
|
||||
for test_case in test_cases {
|
||||
let result = Packet::decode(test_case.plain_text.as_bytes(), secret);
|
||||
assert_eq!(result.is_err(), true);
|
||||
assert_eq!(result.err().unwrap(), test_case.expected_error);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_packet_attribute_length_boundary() {
|
||||
let mut packet = Packet::new(Code::AccessRequest, b"12345");
|
||||
packet.add(AVP {
|
||||
typ: 1,
|
||||
value: vec![1; 253],
|
||||
});
|
||||
let encoded = packet.encode();
|
||||
assert_eq!(encoded.is_err(), false);
|
||||
|
||||
let mut packet = Packet::new(Code::AccessRequest, b"12345");
|
||||
packet.add(AVP {
|
||||
typ: 1,
|
||||
value: vec![1; 254],
|
||||
});
|
||||
let encoded = packet.encode();
|
||||
assert_eq!(encoded.is_err(), true);
|
||||
assert_eq!(
|
||||
encoded.err().unwrap(),
|
||||
PacketError::EncodingError("attribute is too large".to_owned()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use crate::packet::Packet;
|
||||
|
||||
pub struct Request {
|
||||
local_addr: SocketAddr,
|
||||
remote_addr: SocketAddr,
|
||||
packet: Packet,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn new(local_addr: SocketAddr, remote_addr: SocketAddr, packet: Packet) -> Self {
|
||||
Self {
|
||||
local_addr,
|
||||
remote_addr,
|
||||
packet,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_local_addr(&self) -> SocketAddr {
|
||||
self.local_addr
|
||||
}
|
||||
|
||||
pub fn get_remote_addr(&self) -> SocketAddr {
|
||||
self.remote_addr
|
||||
}
|
||||
|
||||
pub fn get_packet(&self) -> &Packet {
|
||||
&self.packet
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,857 @@
|
||||
// Code generated by machine generator; DO NOT EDIT.
|
||||
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::avp::{AVPError, AVPType, AVP};
|
||||
use crate::packet::Packet;
|
||||
|
||||
pub type FramedCompression = u32;
|
||||
pub const FRAMED_COMPRESSION_NONE: FramedCompression = 0;
|
||||
pub const FRAMED_COMPRESSION_VAN_JACOBSON_TCP_IP: FramedCompression = 1;
|
||||
pub const FRAMED_COMPRESSION_IPX_HEADER_COMPRESSION: FramedCompression = 2;
|
||||
pub const FRAMED_COMPRESSION_STAC_LZS: FramedCompression = 3;
|
||||
|
||||
pub type FramedProtocol = u32;
|
||||
pub const FRAMED_PROTOCOL_PPP: FramedProtocol = 1;
|
||||
pub const FRAMED_PROTOCOL_SLIP: FramedProtocol = 2;
|
||||
pub const FRAMED_PROTOCOL_ARAP: FramedProtocol = 3;
|
||||
pub const FRAMED_PROTOCOL_GANDALF_SLML: FramedProtocol = 4;
|
||||
pub const FRAMED_PROTOCOL_XYLOGICS_IPX_SLIP: FramedProtocol = 5;
|
||||
pub const FRAMED_PROTOCOL_X_75_SYNCHRONOUS: FramedProtocol = 6;
|
||||
|
||||
pub type FramedRouting = u32;
|
||||
pub const FRAMED_ROUTING_NONE: FramedRouting = 0;
|
||||
pub const FRAMED_ROUTING_BROADCAST: FramedRouting = 1;
|
||||
pub const FRAMED_ROUTING_LISTEN: FramedRouting = 2;
|
||||
pub const FRAMED_ROUTING_BROADCAST_LISTEN: FramedRouting = 3;
|
||||
|
||||
pub type LoginService = u32;
|
||||
pub const LOGIN_SERVICE_TELNET: LoginService = 0;
|
||||
pub const LOGIN_SERVICE_RLOGIN: LoginService = 1;
|
||||
pub const LOGIN_SERVICE_TCP_CLEAR: LoginService = 2;
|
||||
pub const LOGIN_SERVICE_PORT_MASTER: LoginService = 3;
|
||||
pub const LOGIN_SERVICE_LAT: LoginService = 4;
|
||||
pub const LOGIN_SERVICE_X25_PAD: LoginService = 5;
|
||||
pub const LOGIN_SERVICE_X25_T3POS: LoginService = 6;
|
||||
pub const LOGIN_SERVICE_TCP_CLEAR_QUIET: LoginService = 8;
|
||||
|
||||
pub type LoginTCPPort = u32;
|
||||
pub const LOGIN_TCP_PORT_TELNET: LoginTCPPort = 23;
|
||||
pub const LOGIN_TCP_PORT_RLOGIN: LoginTCPPort = 513;
|
||||
pub const LOGIN_TCP_PORT_RSH: LoginTCPPort = 514;
|
||||
|
||||
pub type NasPortType = u32;
|
||||
pub const NAS_PORT_TYPE_ASYNC: NasPortType = 0;
|
||||
pub const NAS_PORT_TYPE_SYNC: NasPortType = 1;
|
||||
pub const NAS_PORT_TYPE_ISDN: NasPortType = 2;
|
||||
pub const NAS_PORT_TYPE_ISDN_V120: NasPortType = 3;
|
||||
pub const NAS_PORT_TYPE_ISDN_V110: NasPortType = 4;
|
||||
pub const NAS_PORT_TYPE_VIRTUAL: NasPortType = 5;
|
||||
pub const NAS_PORT_TYPE_PIAFS: NasPortType = 6;
|
||||
pub const NAS_PORT_TYPE_HDLC_CLEAR_CHANNEL: NasPortType = 7;
|
||||
pub const NAS_PORT_TYPE_X_25: NasPortType = 8;
|
||||
pub const NAS_PORT_TYPE_X_75: NasPortType = 9;
|
||||
pub const NAS_PORT_TYPE_G_3_FAX: NasPortType = 10;
|
||||
pub const NAS_PORT_TYPE_SDSL: NasPortType = 11;
|
||||
pub const NAS_PORT_TYPE_ADSL_CAP: NasPortType = 12;
|
||||
pub const NAS_PORT_TYPE_ADSL_DMT: NasPortType = 13;
|
||||
pub const NAS_PORT_TYPE_IDSL: NasPortType = 14;
|
||||
pub const NAS_PORT_TYPE_ETHERNET: NasPortType = 15;
|
||||
pub const NAS_PORT_TYPE_X_DSL: NasPortType = 16;
|
||||
pub const NAS_PORT_TYPE_CABLE: NasPortType = 17;
|
||||
pub const NAS_PORT_TYPE_WIRELESS_OTHER: NasPortType = 18;
|
||||
pub const NAS_PORT_TYPE_WIRELESS_802_11: NasPortType = 19;
|
||||
|
||||
pub type ServiceType = u32;
|
||||
pub const SERVICE_TYPE_LOGIN_USER: ServiceType = 1;
|
||||
pub const SERVICE_TYPE_FRAMED_USER: ServiceType = 2;
|
||||
pub const SERVICE_TYPE_CALLBACK_LOGIN_USER: ServiceType = 3;
|
||||
pub const SERVICE_TYPE_CALLBACK_FRAMED_USER: ServiceType = 4;
|
||||
pub const SERVICE_TYPE_OUTBOUND_USER: ServiceType = 5;
|
||||
pub const SERVICE_TYPE_ADMINISTRATIVE_USER: ServiceType = 6;
|
||||
pub const SERVICE_TYPE_NAS_PROMPT_USER: ServiceType = 7;
|
||||
pub const SERVICE_TYPE_AUTHENTICATE_ONLY: ServiceType = 8;
|
||||
pub const SERVICE_TYPE_CALLBACK_NAS_PROMPT: ServiceType = 9;
|
||||
pub const SERVICE_TYPE_CALL_CHECK: ServiceType = 10;
|
||||
pub const SERVICE_TYPE_CALLBACK_ADMINISTRATIVE: ServiceType = 11;
|
||||
|
||||
pub type TerminationAction = u32;
|
||||
pub const TERMINATION_ACTION_DEFAULT: TerminationAction = 0;
|
||||
pub const TERMINATION_ACTION_RADIUS_REQUEST: TerminationAction = 1;
|
||||
|
||||
pub const USER_NAME_TYPE: AVPType = 1;
|
||||
pub fn delete_user_name(packet: &mut Packet) {
|
||||
packet.delete(USER_NAME_TYPE);
|
||||
}
|
||||
pub fn add_user_name(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(USER_NAME_TYPE, value));
|
||||
}
|
||||
pub fn lookup_user_name(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet.lookup(USER_NAME_TYPE).map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_user_name(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(USER_NAME_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const USER_PASSWORD_TYPE: AVPType = 2;
|
||||
pub fn delete_user_password(packet: &mut Packet) {
|
||||
packet.delete(USER_PASSWORD_TYPE);
|
||||
}
|
||||
pub fn add_user_password(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
|
||||
packet.add(AVP::encode_user_password(
|
||||
USER_PASSWORD_TYPE,
|
||||
value,
|
||||
packet.get_secret(),
|
||||
packet.get_authenticator(),
|
||||
)?);
|
||||
Ok(())
|
||||
}
|
||||
pub fn lookup_user_password(packet: &Packet) -> Option<Result<Vec<u8>, AVPError>> {
|
||||
packet
|
||||
.lookup(USER_PASSWORD_TYPE)
|
||||
.map(|v| v.decode_user_password(packet.get_secret(), packet.get_authenticator()))
|
||||
}
|
||||
pub fn lookup_all_user_password(packet: &Packet) -> Result<Vec<Vec<u8>>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(USER_PASSWORD_TYPE) {
|
||||
vec.push(avp.decode_user_password(packet.get_secret(), packet.get_authenticator())?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CHAP_PASSWORD_TYPE: AVPType = 3;
|
||||
pub fn delete_chap_password(packet: &mut Packet) {
|
||||
packet.delete(CHAP_PASSWORD_TYPE);
|
||||
}
|
||||
pub fn add_chap_password(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(CHAP_PASSWORD_TYPE, value));
|
||||
}
|
||||
pub fn lookup_chap_password(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet.lookup(CHAP_PASSWORD_TYPE).map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_chap_password(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CHAP_PASSWORD_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const NAS_IP_ADDRESS_TYPE: AVPType = 4;
|
||||
pub fn delete_nas_ip_address(packet: &mut Packet) {
|
||||
packet.delete(NAS_IP_ADDRESS_TYPE);
|
||||
}
|
||||
pub fn add_nas_ip_address(packet: &mut Packet, value: &Ipv4Addr) {
|
||||
packet.add(AVP::encode_ipv4(NAS_IP_ADDRESS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_nas_ip_address(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {
|
||||
packet.lookup(NAS_IP_ADDRESS_TYPE).map(|v| v.decode_ipv4())
|
||||
}
|
||||
pub fn lookup_all_nas_ip_address(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(NAS_IP_ADDRESS_TYPE) {
|
||||
vec.push(avp.decode_ipv4()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const NAS_PORT_TYPE: AVPType = 5;
|
||||
pub fn delete_nas_port(packet: &mut Packet) {
|
||||
packet.delete(NAS_PORT_TYPE);
|
||||
}
|
||||
pub fn add_nas_port(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(NAS_PORT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_nas_port(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(NAS_PORT_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_nas_port(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(NAS_PORT_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const SERVICE_TYPE_TYPE: AVPType = 6;
|
||||
pub fn delete_service_type(packet: &mut Packet) {
|
||||
packet.delete(SERVICE_TYPE_TYPE);
|
||||
}
|
||||
pub fn add_service_type(packet: &mut Packet, value: ServiceType) {
|
||||
packet.add(AVP::encode_u32(SERVICE_TYPE_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_service_type(packet: &Packet) -> Option<Result<ServiceType, AVPError>> {
|
||||
packet
|
||||
.lookup(SERVICE_TYPE_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as ServiceType))
|
||||
}
|
||||
pub fn lookup_all_service_type(packet: &Packet) -> Result<Vec<ServiceType>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(SERVICE_TYPE_TYPE) {
|
||||
vec.push(avp.decode_u32()? as ServiceType)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_PROTOCOL_TYPE: AVPType = 7;
|
||||
pub fn delete_framed_protocol(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_PROTOCOL_TYPE);
|
||||
}
|
||||
pub fn add_framed_protocol(packet: &mut Packet, value: FramedProtocol) {
|
||||
packet.add(AVP::encode_u32(FRAMED_PROTOCOL_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_framed_protocol(packet: &Packet) -> Option<Result<FramedProtocol, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_PROTOCOL_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as FramedProtocol))
|
||||
}
|
||||
pub fn lookup_all_framed_protocol(packet: &Packet) -> Result<Vec<FramedProtocol>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_PROTOCOL_TYPE) {
|
||||
vec.push(avp.decode_u32()? as FramedProtocol)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_IP_ADDRESS_TYPE: AVPType = 8;
|
||||
pub fn delete_framed_ip_address(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_IP_ADDRESS_TYPE);
|
||||
}
|
||||
pub fn add_framed_ip_address(packet: &mut Packet, value: &Ipv4Addr) {
|
||||
packet.add(AVP::encode_ipv4(FRAMED_IP_ADDRESS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_ip_address(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_IP_ADDRESS_TYPE)
|
||||
.map(|v| v.decode_ipv4())
|
||||
}
|
||||
pub fn lookup_all_framed_ip_address(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_IP_ADDRESS_TYPE) {
|
||||
vec.push(avp.decode_ipv4()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_IP_NETMASK_TYPE: AVPType = 9;
|
||||
pub fn delete_framed_ip_netmask(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_IP_NETMASK_TYPE);
|
||||
}
|
||||
pub fn add_framed_ip_netmask(packet: &mut Packet, value: &Ipv4Addr) {
|
||||
packet.add(AVP::encode_ipv4(FRAMED_IP_NETMASK_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_ip_netmask(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_IP_NETMASK_TYPE)
|
||||
.map(|v| v.decode_ipv4())
|
||||
}
|
||||
pub fn lookup_all_framed_ip_netmask(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_IP_NETMASK_TYPE) {
|
||||
vec.push(avp.decode_ipv4()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_ROUTING_TYPE: AVPType = 10;
|
||||
pub fn delete_framed_routing(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_ROUTING_TYPE);
|
||||
}
|
||||
pub fn add_framed_routing(packet: &mut Packet, value: FramedRouting) {
|
||||
packet.add(AVP::encode_u32(FRAMED_ROUTING_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_framed_routing(packet: &Packet) -> Option<Result<FramedRouting, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_ROUTING_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as FramedRouting))
|
||||
}
|
||||
pub fn lookup_all_framed_routing(packet: &Packet) -> Result<Vec<FramedRouting>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_ROUTING_TYPE) {
|
||||
vec.push(avp.decode_u32()? as FramedRouting)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FILTER_ID_TYPE: AVPType = 11;
|
||||
pub fn delete_filter_id(packet: &mut Packet) {
|
||||
packet.delete(FILTER_ID_TYPE);
|
||||
}
|
||||
pub fn add_filter_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(FILTER_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_filter_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet.lookup(FILTER_ID_TYPE).map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_filter_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FILTER_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_MTU_TYPE: AVPType = 12;
|
||||
pub fn delete_framed_mtu(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_MTU_TYPE);
|
||||
}
|
||||
pub fn add_framed_mtu(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(FRAMED_MTU_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_mtu(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(FRAMED_MTU_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_framed_mtu(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_MTU_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_COMPRESSION_TYPE: AVPType = 13;
|
||||
pub fn delete_framed_compression(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_COMPRESSION_TYPE);
|
||||
}
|
||||
pub fn add_framed_compression(packet: &mut Packet, value: FramedCompression) {
|
||||
packet.add(AVP::encode_u32(FRAMED_COMPRESSION_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_framed_compression(packet: &Packet) -> Option<Result<FramedCompression, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_COMPRESSION_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as FramedCompression))
|
||||
}
|
||||
pub fn lookup_all_framed_compression(packet: &Packet) -> Result<Vec<FramedCompression>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_COMPRESSION_TYPE) {
|
||||
vec.push(avp.decode_u32()? as FramedCompression)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_IP_HOST_TYPE: AVPType = 14;
|
||||
pub fn delete_login_ip_host(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_IP_HOST_TYPE);
|
||||
}
|
||||
pub fn add_login_ip_host(packet: &mut Packet, value: &Ipv4Addr) {
|
||||
packet.add(AVP::encode_ipv4(LOGIN_IP_HOST_TYPE, value));
|
||||
}
|
||||
pub fn lookup_login_ip_host(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {
|
||||
packet.lookup(LOGIN_IP_HOST_TYPE).map(|v| v.decode_ipv4())
|
||||
}
|
||||
pub fn lookup_all_login_ip_host(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_IP_HOST_TYPE) {
|
||||
vec.push(avp.decode_ipv4()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_SERVICE_TYPE: AVPType = 15;
|
||||
pub fn delete_login_service(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_SERVICE_TYPE);
|
||||
}
|
||||
pub fn add_login_service(packet: &mut Packet, value: LoginService) {
|
||||
packet.add(AVP::encode_u32(LOGIN_SERVICE_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_login_service(packet: &Packet) -> Option<Result<LoginService, AVPError>> {
|
||||
packet
|
||||
.lookup(LOGIN_SERVICE_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as LoginService))
|
||||
}
|
||||
pub fn lookup_all_login_service(packet: &Packet) -> Result<Vec<LoginService>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_SERVICE_TYPE) {
|
||||
vec.push(avp.decode_u32()? as LoginService)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_TCP_PORT_TYPE: AVPType = 16;
|
||||
pub fn delete_login_tcp_port(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_TCP_PORT_TYPE);
|
||||
}
|
||||
pub fn add_login_tcp_port(packet: &mut Packet, value: LoginTCPPort) {
|
||||
packet.add(AVP::encode_u32(LOGIN_TCP_PORT_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_login_tcp_port(packet: &Packet) -> Option<Result<LoginTCPPort, AVPError>> {
|
||||
packet
|
||||
.lookup(LOGIN_TCP_PORT_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as LoginTCPPort))
|
||||
}
|
||||
pub fn lookup_all_login_tcp_port(packet: &Packet) -> Result<Vec<LoginTCPPort>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_TCP_PORT_TYPE) {
|
||||
vec.push(avp.decode_u32()? as LoginTCPPort)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const REPLY_MESSAGE_TYPE: AVPType = 18;
|
||||
pub fn delete_reply_message(packet: &mut Packet) {
|
||||
packet.delete(REPLY_MESSAGE_TYPE);
|
||||
}
|
||||
pub fn add_reply_message(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(REPLY_MESSAGE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_reply_message(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet.lookup(REPLY_MESSAGE_TYPE).map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_reply_message(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(REPLY_MESSAGE_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CALLBACK_NUMBER_TYPE: AVPType = 19;
|
||||
pub fn delete_callback_number(packet: &mut Packet) {
|
||||
packet.delete(CALLBACK_NUMBER_TYPE);
|
||||
}
|
||||
pub fn add_callback_number(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(CALLBACK_NUMBER_TYPE, value));
|
||||
}
|
||||
pub fn lookup_callback_number(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(CALLBACK_NUMBER_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_callback_number(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CALLBACK_NUMBER_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CALLBACK_ID_TYPE: AVPType = 20;
|
||||
pub fn delete_callback_id(packet: &mut Packet) {
|
||||
packet.delete(CALLBACK_ID_TYPE);
|
||||
}
|
||||
pub fn add_callback_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(CALLBACK_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_callback_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet.lookup(CALLBACK_ID_TYPE).map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_callback_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CALLBACK_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_ROUTE_TYPE: AVPType = 22;
|
||||
pub fn delete_framed_route(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_ROUTE_TYPE);
|
||||
}
|
||||
pub fn add_framed_route(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(FRAMED_ROUTE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_route(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet.lookup(FRAMED_ROUTE_TYPE).map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_framed_route(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_ROUTE_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_IPX_NETWORK_TYPE: AVPType = 23;
|
||||
pub fn delete_framed_ipx_network(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_IPX_NETWORK_TYPE);
|
||||
}
|
||||
pub fn add_framed_ipx_network(packet: &mut Packet, value: &Ipv4Addr) {
|
||||
packet.add(AVP::encode_ipv4(FRAMED_IPX_NETWORK_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_ipx_network(packet: &Packet) -> Option<Result<Ipv4Addr, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_IPX_NETWORK_TYPE)
|
||||
.map(|v| v.decode_ipv4())
|
||||
}
|
||||
pub fn lookup_all_framed_ipx_network(packet: &Packet) -> Result<Vec<Ipv4Addr>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_IPX_NETWORK_TYPE) {
|
||||
vec.push(avp.decode_ipv4()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const STATE_TYPE: AVPType = 24;
|
||||
pub fn delete_state(packet: &mut Packet) {
|
||||
packet.delete(STATE_TYPE);
|
||||
}
|
||||
pub fn add_state(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(STATE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_state(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet.lookup(STATE_TYPE).map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_state(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(STATE_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const CLASS_TYPE: AVPType = 25;
|
||||
pub fn delete_class(packet: &mut Packet) {
|
||||
packet.delete(CLASS_TYPE);
|
||||
}
|
||||
pub fn add_class(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(CLASS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_class(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet.lookup(CLASS_TYPE).map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_class(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CLASS_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const VENDOR_SPECIFIC_TYPE: AVPType = 26;
|
||||
pub fn delete_vendor_specific(packet: &mut Packet) {
|
||||
packet.delete(VENDOR_SPECIFIC_TYPE);
|
||||
}
|
||||
|
||||
pub const SESSION_TIMEOUT_TYPE: AVPType = 27;
|
||||
pub fn delete_session_timeout(packet: &mut Packet) {
|
||||
packet.delete(SESSION_TIMEOUT_TYPE);
|
||||
}
|
||||
pub fn add_session_timeout(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(SESSION_TIMEOUT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_session_timeout(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(SESSION_TIMEOUT_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_session_timeout(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(SESSION_TIMEOUT_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const IDLE_TIMEOUT_TYPE: AVPType = 28;
|
||||
pub fn delete_idle_timeout(packet: &mut Packet) {
|
||||
packet.delete(IDLE_TIMEOUT_TYPE);
|
||||
}
|
||||
pub fn add_idle_timeout(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(IDLE_TIMEOUT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_idle_timeout(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(IDLE_TIMEOUT_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_idle_timeout(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(IDLE_TIMEOUT_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const TERMINATION_ACTION_TYPE: AVPType = 29;
|
||||
pub fn delete_termination_action(packet: &mut Packet) {
|
||||
packet.delete(TERMINATION_ACTION_TYPE);
|
||||
}
|
||||
pub fn add_termination_action(packet: &mut Packet, value: TerminationAction) {
|
||||
packet.add(AVP::encode_u32(TERMINATION_ACTION_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_termination_action(packet: &Packet) -> Option<Result<TerminationAction, AVPError>> {
|
||||
packet
|
||||
.lookup(TERMINATION_ACTION_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as TerminationAction))
|
||||
}
|
||||
pub fn lookup_all_termination_action(packet: &Packet) -> Result<Vec<TerminationAction>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(TERMINATION_ACTION_TYPE) {
|
||||
vec.push(avp.decode_u32()? as TerminationAction)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CALLED_STATION_ID_TYPE: AVPType = 30;
|
||||
pub fn delete_called_station_id(packet: &mut Packet) {
|
||||
packet.delete(CALLED_STATION_ID_TYPE);
|
||||
}
|
||||
pub fn add_called_station_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(CALLED_STATION_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_called_station_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(CALLED_STATION_ID_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_called_station_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CALLED_STATION_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CALLING_STATION_ID_TYPE: AVPType = 31;
|
||||
pub fn delete_calling_station_id(packet: &mut Packet) {
|
||||
packet.delete(CALLING_STATION_ID_TYPE);
|
||||
}
|
||||
pub fn add_calling_station_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(CALLING_STATION_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_calling_station_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(CALLING_STATION_ID_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_calling_station_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CALLING_STATION_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const NAS_IDENTIFIER_TYPE: AVPType = 32;
|
||||
pub fn delete_nas_identifier(packet: &mut Packet) {
|
||||
packet.delete(NAS_IDENTIFIER_TYPE);
|
||||
}
|
||||
pub fn add_nas_identifier(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(NAS_IDENTIFIER_TYPE, value));
|
||||
}
|
||||
pub fn lookup_nas_identifier(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(NAS_IDENTIFIER_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_nas_identifier(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(NAS_IDENTIFIER_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const PROXY_STATE_TYPE: AVPType = 33;
|
||||
pub fn delete_proxy_state(packet: &mut Packet) {
|
||||
packet.delete(PROXY_STATE_TYPE);
|
||||
}
|
||||
pub fn add_proxy_state(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(PROXY_STATE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_proxy_state(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet.lookup(PROXY_STATE_TYPE).map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_proxy_state(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(PROXY_STATE_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const LOGIN_LAT_SERVICE_TYPE: AVPType = 34;
|
||||
pub fn delete_login_lat_service(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_LAT_SERVICE_TYPE);
|
||||
}
|
||||
pub fn add_login_lat_service(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(LOGIN_LAT_SERVICE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_login_lat_service(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(LOGIN_LAT_SERVICE_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_login_lat_service(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_LAT_SERVICE_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_LAT_NODE_TYPE: AVPType = 35;
|
||||
pub fn delete_login_lat_node(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_LAT_NODE_TYPE);
|
||||
}
|
||||
pub fn add_login_lat_node(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(LOGIN_LAT_NODE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_login_lat_node(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(LOGIN_LAT_NODE_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_login_lat_node(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_LAT_NODE_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_LAT_GROUP_TYPE: AVPType = 36;
|
||||
pub fn delete_login_lat_group(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_LAT_GROUP_TYPE);
|
||||
}
|
||||
pub fn add_login_lat_group(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(LOGIN_LAT_GROUP_TYPE, value));
|
||||
}
|
||||
pub fn lookup_login_lat_group(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet
|
||||
.lookup(LOGIN_LAT_GROUP_TYPE)
|
||||
.map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_login_lat_group(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_LAT_GROUP_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const FRAMED_APPLE_TALK_LINK_TYPE: AVPType = 37;
|
||||
pub fn delete_framed_apple_talk_link(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_APPLE_TALK_LINK_TYPE);
|
||||
}
|
||||
pub fn add_framed_apple_talk_link(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(FRAMED_APPLE_TALK_LINK_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_apple_talk_link(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_APPLE_TALK_LINK_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_framed_apple_talk_link(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_APPLE_TALK_LINK_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_APPLE_TALK_NETWORK_TYPE: AVPType = 38;
|
||||
pub fn delete_framed_apple_talk_network(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_APPLE_TALK_NETWORK_TYPE);
|
||||
}
|
||||
pub fn add_framed_apple_talk_network(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(FRAMED_APPLE_TALK_NETWORK_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_apple_talk_network(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_APPLE_TALK_NETWORK_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_framed_apple_talk_network(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_APPLE_TALK_NETWORK_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const FRAMED_APPLE_TALK_ZONE_TYPE: AVPType = 39;
|
||||
pub fn delete_framed_apple_talk_zone(packet: &mut Packet) {
|
||||
packet.delete(FRAMED_APPLE_TALK_ZONE_TYPE);
|
||||
}
|
||||
pub fn add_framed_apple_talk_zone(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(FRAMED_APPLE_TALK_ZONE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_framed_apple_talk_zone(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(FRAMED_APPLE_TALK_ZONE_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_framed_apple_talk_zone(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(FRAMED_APPLE_TALK_ZONE_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const CHAP_CHALLENGE_TYPE: AVPType = 60;
|
||||
pub fn delete_chap_challenge(packet: &mut Packet) {
|
||||
packet.delete(CHAP_CHALLENGE_TYPE);
|
||||
}
|
||||
pub fn add_chap_challenge(packet: &mut Packet, value: &[u8]) {
|
||||
packet.add(AVP::encode_bytes(CHAP_CHALLENGE_TYPE, value));
|
||||
}
|
||||
pub fn lookup_chap_challenge(packet: &Packet) -> Option<Vec<u8>> {
|
||||
packet.lookup(CHAP_CHALLENGE_TYPE).map(|v| v.decode_bytes())
|
||||
}
|
||||
pub fn lookup_all_chap_challenge(packet: &Packet) -> Vec<Vec<u8>> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(CHAP_CHALLENGE_TYPE) {
|
||||
vec.push(avp.decode_bytes())
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
pub const NAS_PORT_TYPE_TYPE: AVPType = 61;
|
||||
pub fn delete_nas_port_type(packet: &mut Packet) {
|
||||
packet.delete(NAS_PORT_TYPE_TYPE);
|
||||
}
|
||||
pub fn add_nas_port_type(packet: &mut Packet, value: NasPortType) {
|
||||
packet.add(AVP::encode_u32(NAS_PORT_TYPE_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_nas_port_type(packet: &Packet) -> Option<Result<NasPortType, AVPError>> {
|
||||
packet
|
||||
.lookup(NAS_PORT_TYPE_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as NasPortType))
|
||||
}
|
||||
pub fn lookup_all_nas_port_type(packet: &Packet) -> Result<Vec<NasPortType>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(NAS_PORT_TYPE_TYPE) {
|
||||
vec.push(avp.decode_u32()? as NasPortType)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const PORT_LIMIT_TYPE: AVPType = 62;
|
||||
pub fn delete_port_limit(packet: &mut Packet) {
|
||||
packet.delete(PORT_LIMIT_TYPE);
|
||||
}
|
||||
pub fn add_port_limit(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(PORT_LIMIT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_port_limit(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(PORT_LIMIT_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_port_limit(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(PORT_LIMIT_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const LOGIN_LAT_PORT_TYPE: AVPType = 63;
|
||||
pub fn delete_login_lat_port(packet: &mut Packet) {
|
||||
packet.delete(LOGIN_LAT_PORT_TYPE);
|
||||
}
|
||||
pub fn add_login_lat_port(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(LOGIN_LAT_PORT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_login_lat_port(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(LOGIN_LAT_PORT_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_login_lat_port(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(LOGIN_LAT_PORT_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
// Code generated by machine generator; DO NOT EDIT.
|
||||
|
||||
use crate::avp::{AVPError, AVPType, AVP};
|
||||
use crate::packet::Packet;
|
||||
|
||||
pub type AcctAuthentic = u32;
|
||||
pub const ACCT_AUTHENTIC_RADIUS: AcctAuthentic = 1;
|
||||
pub const ACCT_AUTHENTIC_LOCAL: AcctAuthentic = 2;
|
||||
pub const ACCT_AUTHENTIC_REMOTE: AcctAuthentic = 3;
|
||||
pub const ACCT_AUTHENTIC_DIAMETER: AcctAuthentic = 4;
|
||||
|
||||
pub type AcctStatusType = u32;
|
||||
pub const ACCT_STATUS_TYPE_START: AcctStatusType = 1;
|
||||
pub const ACCT_STATUS_TYPE_STOP: AcctStatusType = 2;
|
||||
pub const ACCT_STATUS_TYPE_ALIVE: AcctStatusType = 3;
|
||||
pub const ACCT_STATUS_TYPE_INTERIM_UPDATE: AcctStatusType = 3;
|
||||
pub const ACCT_STATUS_TYPE_ACCOUNTING_ON: AcctStatusType = 7;
|
||||
pub const ACCT_STATUS_TYPE_ACCOUNTING_OFF: AcctStatusType = 8;
|
||||
pub const ACCT_STATUS_TYPE_FAILED: AcctStatusType = 15;
|
||||
|
||||
pub type AcctTerminateCause = u32;
|
||||
pub const ACCT_TERMINATE_CAUSE_USER_REQUEST: AcctTerminateCause = 1;
|
||||
pub const ACCT_TERMINATE_CAUSE_LOST_CARRIER: AcctTerminateCause = 2;
|
||||
pub const ACCT_TERMINATE_CAUSE_LOST_SERVICE: AcctTerminateCause = 3;
|
||||
pub const ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT: AcctTerminateCause = 4;
|
||||
pub const ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT: AcctTerminateCause = 5;
|
||||
pub const ACCT_TERMINATE_CAUSE_ADMIN_RESET: AcctTerminateCause = 6;
|
||||
pub const ACCT_TERMINATE_CAUSE_ADMIN_REBOOT: AcctTerminateCause = 7;
|
||||
pub const ACCT_TERMINATE_CAUSE_PORT_ERROR: AcctTerminateCause = 8;
|
||||
pub const ACCT_TERMINATE_CAUSE_NAS_ERROR: AcctTerminateCause = 9;
|
||||
pub const ACCT_TERMINATE_CAUSE_NAS_REQUEST: AcctTerminateCause = 10;
|
||||
pub const ACCT_TERMINATE_CAUSE_NAS_REBOOT: AcctTerminateCause = 11;
|
||||
pub const ACCT_TERMINATE_CAUSE_PORT_UNNEEDED: AcctTerminateCause = 12;
|
||||
pub const ACCT_TERMINATE_CAUSE_PORT_PREEMPTED: AcctTerminateCause = 13;
|
||||
pub const ACCT_TERMINATE_CAUSE_PORT_SUSPENDED: AcctTerminateCause = 14;
|
||||
pub const ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE: AcctTerminateCause = 15;
|
||||
pub const ACCT_TERMINATE_CAUSE_CALLBACK: AcctTerminateCause = 16;
|
||||
pub const ACCT_TERMINATE_CAUSE_USER_ERROR: AcctTerminateCause = 17;
|
||||
pub const ACCT_TERMINATE_CAUSE_HOST_REQUEST: AcctTerminateCause = 18;
|
||||
|
||||
pub const ACCT_STATUS_TYPE_TYPE: AVPType = 40;
|
||||
pub fn delete_acct_status_type(packet: &mut Packet) {
|
||||
packet.delete(ACCT_STATUS_TYPE_TYPE);
|
||||
}
|
||||
pub fn add_acct_status_type(packet: &mut Packet, value: AcctStatusType) {
|
||||
packet.add(AVP::encode_u32(ACCT_STATUS_TYPE_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_acct_status_type(packet: &Packet) -> Option<Result<AcctStatusType, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_STATUS_TYPE_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as AcctStatusType))
|
||||
}
|
||||
pub fn lookup_all_acct_status_type(packet: &Packet) -> Result<Vec<AcctStatusType>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_STATUS_TYPE_TYPE) {
|
||||
vec.push(avp.decode_u32()? as AcctStatusType)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_DELAY_TIME_TYPE: AVPType = 41;
|
||||
pub fn delete_acct_delay_time(packet: &mut Packet) {
|
||||
packet.delete(ACCT_DELAY_TIME_TYPE);
|
||||
}
|
||||
pub fn add_acct_delay_time(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_DELAY_TIME_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_delay_time(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(ACCT_DELAY_TIME_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_delay_time(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_DELAY_TIME_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_INPUT_OCTETS_TYPE: AVPType = 42;
|
||||
pub fn delete_acct_input_octets(packet: &mut Packet) {
|
||||
packet.delete(ACCT_INPUT_OCTETS_TYPE);
|
||||
}
|
||||
pub fn add_acct_input_octets(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_INPUT_OCTETS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_input_octets(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_INPUT_OCTETS_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_input_octets(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_INPUT_OCTETS_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_OUTPUT_OCTETS_TYPE: AVPType = 43;
|
||||
pub fn delete_acct_output_octets(packet: &mut Packet) {
|
||||
packet.delete(ACCT_OUTPUT_OCTETS_TYPE);
|
||||
}
|
||||
pub fn add_acct_output_octets(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_OUTPUT_OCTETS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_output_octets(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_OUTPUT_OCTETS_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_output_octets(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_OUTPUT_OCTETS_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_SESSION_ID_TYPE: AVPType = 44;
|
||||
pub fn delete_acct_session_id(packet: &mut Packet) {
|
||||
packet.delete(ACCT_SESSION_ID_TYPE);
|
||||
}
|
||||
pub fn add_acct_session_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(ACCT_SESSION_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_session_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_SESSION_ID_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_acct_session_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_SESSION_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_AUTHENTIC_TYPE: AVPType = 45;
|
||||
pub fn delete_acct_authentic(packet: &mut Packet) {
|
||||
packet.delete(ACCT_AUTHENTIC_TYPE);
|
||||
}
|
||||
pub fn add_acct_authentic(packet: &mut Packet, value: AcctAuthentic) {
|
||||
packet.add(AVP::encode_u32(ACCT_AUTHENTIC_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_acct_authentic(packet: &Packet) -> Option<Result<AcctAuthentic, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_AUTHENTIC_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as AcctAuthentic))
|
||||
}
|
||||
pub fn lookup_all_acct_authentic(packet: &Packet) -> Result<Vec<AcctAuthentic>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_AUTHENTIC_TYPE) {
|
||||
vec.push(avp.decode_u32()? as AcctAuthentic)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_SESSION_TIME_TYPE: AVPType = 46;
|
||||
pub fn delete_acct_session_time(packet: &mut Packet) {
|
||||
packet.delete(ACCT_SESSION_TIME_TYPE);
|
||||
}
|
||||
pub fn add_acct_session_time(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_SESSION_TIME_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_session_time(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_SESSION_TIME_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_session_time(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_SESSION_TIME_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_INPUT_PACKETS_TYPE: AVPType = 47;
|
||||
pub fn delete_acct_input_packets(packet: &mut Packet) {
|
||||
packet.delete(ACCT_INPUT_PACKETS_TYPE);
|
||||
}
|
||||
pub fn add_acct_input_packets(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_INPUT_PACKETS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_input_packets(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_INPUT_PACKETS_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_input_packets(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_INPUT_PACKETS_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_OUTPUT_PACKETS_TYPE: AVPType = 48;
|
||||
pub fn delete_acct_output_packets(packet: &mut Packet) {
|
||||
packet.delete(ACCT_OUTPUT_PACKETS_TYPE);
|
||||
}
|
||||
pub fn add_acct_output_packets(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_OUTPUT_PACKETS_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_output_packets(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_OUTPUT_PACKETS_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_output_packets(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_OUTPUT_PACKETS_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_TERMINATE_CAUSE_TYPE: AVPType = 49;
|
||||
pub fn delete_acct_terminate_cause(packet: &mut Packet) {
|
||||
packet.delete(ACCT_TERMINATE_CAUSE_TYPE);
|
||||
}
|
||||
pub fn add_acct_terminate_cause(packet: &mut Packet, value: AcctTerminateCause) {
|
||||
packet.add(AVP::encode_u32(ACCT_TERMINATE_CAUSE_TYPE, value as u32));
|
||||
}
|
||||
pub fn lookup_acct_terminate_cause(
|
||||
packet: &Packet,
|
||||
) -> Option<Result<AcctTerminateCause, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_TERMINATE_CAUSE_TYPE)
|
||||
.map(|v| Ok(v.decode_u32()? as AcctTerminateCause))
|
||||
}
|
||||
pub fn lookup_all_acct_terminate_cause(
|
||||
packet: &Packet,
|
||||
) -> Result<Vec<AcctTerminateCause>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_TERMINATE_CAUSE_TYPE) {
|
||||
vec.push(avp.decode_u32()? as AcctTerminateCause)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_MULTI_SESSION_ID_TYPE: AVPType = 50;
|
||||
pub fn delete_acct_multi_session_id(packet: &mut Packet) {
|
||||
packet.delete(ACCT_MULTI_SESSION_ID_TYPE);
|
||||
}
|
||||
pub fn add_acct_multi_session_id(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(ACCT_MULTI_SESSION_ID_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_multi_session_id(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_MULTI_SESSION_ID_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_acct_multi_session_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_MULTI_SESSION_ID_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_LINK_COUNT_TYPE: AVPType = 51;
|
||||
pub fn delete_acct_link_count(packet: &mut Packet) {
|
||||
packet.delete(ACCT_LINK_COUNT_TYPE);
|
||||
}
|
||||
pub fn add_acct_link_count(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_LINK_COUNT_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_link_count(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet.lookup(ACCT_LINK_COUNT_TYPE).map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_link_count(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_LINK_COUNT_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Code generated by machine generator; DO NOT EDIT.
|
||||
|
||||
use crate::avp::{AVPError, AVPType, AVP};
|
||||
use crate::packet::Packet;
|
||||
|
||||
pub type AcctStatusType = u32;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_START: AcctStatusType = 9;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_STOP: AcctStatusType = 10;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_REJECT: AcctStatusType = 11;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_LINK_START: AcctStatusType = 12;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_LINK_STOP: AcctStatusType = 13;
|
||||
pub const ACCT_STATUS_TYPE_TUNNEL_LINK_REJECT: AcctStatusType = 14;
|
||||
|
||||
pub const ACCT_TUNNEL_CONNECTION_TYPE: AVPType = 68;
|
||||
pub fn delete_acct_tunnel_connection(packet: &mut Packet) {
|
||||
packet.delete(ACCT_TUNNEL_CONNECTION_TYPE);
|
||||
}
|
||||
pub fn add_acct_tunnel_connection(packet: &mut Packet, value: &str) {
|
||||
packet.add(AVP::encode_string(ACCT_TUNNEL_CONNECTION_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_tunnel_connection(packet: &Packet) -> Option<Result<String, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_TUNNEL_CONNECTION_TYPE)
|
||||
.map(|v| v.decode_string())
|
||||
}
|
||||
pub fn lookup_all_acct_tunnel_connection(packet: &Packet) -> Result<Vec<String>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_TUNNEL_CONNECTION_TYPE) {
|
||||
vec.push(avp.decode_string()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub const ACCT_TUNNEL_PACKETS_LOST_TYPE: AVPType = 86;
|
||||
pub fn delete_acct_tunnel_packets_lost(packet: &mut Packet) {
|
||||
packet.delete(ACCT_TUNNEL_PACKETS_LOST_TYPE);
|
||||
}
|
||||
pub fn add_acct_tunnel_packets_lost(packet: &mut Packet, value: u32) {
|
||||
packet.add(AVP::encode_u32(ACCT_TUNNEL_PACKETS_LOST_TYPE, value));
|
||||
}
|
||||
pub fn lookup_acct_tunnel_packets_lost(packet: &Packet) -> Option<Result<u32, AVPError>> {
|
||||
packet
|
||||
.lookup(ACCT_TUNNEL_PACKETS_LOST_TYPE)
|
||||
.map(|v| v.decode_u32())
|
||||
}
|
||||
pub fn lookup_all_acct_tunnel_packets_lost(packet: &Packet) -> Result<Vec<u32>, AVPError> {
|
||||
let mut vec = Vec::new();
|
||||
for avp in packet.lookup_all(ACCT_TUNNEL_PACKETS_LOST_TYPE) {
|
||||
vec.push(avp.decode_u32()?)
|
||||
}
|
||||
Ok(vec)
|
||||
}
|
||||
Reference in New Issue
Block a user