Improve error enums

This commit is contained in:
moznion
2020-12-12 02:50:39 +09:00
parent ced6b62e5e
commit 7910542618
9 changed files with 240 additions and 97 deletions

View File

@@ -556,7 +556,7 @@ fn generate_fixed_length_octets_attribute_code(
let code = format!(
"pub fn add_{method_identifier}(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {{
if value.len() != {fixed_octets_length} {{
return Err(AVPError::InvalidAttributeLengthError({fixed_octets_length}));
return Err(AVPError::InvalidAttributeLengthError(\"{fixed_octets_length} bytes\".to_owned(), value.len()));
}}
packet.add(AVP::from_bytes({type_identifier}, value));
Ok(())

View File

@@ -7,27 +7,39 @@ use tokio::time::timeout;
use radius::packet::Packet;
use crate::client::ClientError::{
FailedConnection, FailedParsingUDPResponse, FailedRadiusPacketEncoding,
FailedReceivingResponse, FailedSendingPacket, FailedUdpSocketBinding,
};
#[derive(Error, Debug)]
pub enum ClientError {
#[error("failed to bind a UDP socket => `{0}`")]
FailedUdpSocketBinding(String),
#[error("failed to connect to `{0}` => `{1}`")]
FailedConnection(String, String),
#[error("failed to encode a RADIUS request => `{0}`")]
FailedRadiusPacketEncoding(String),
#[error("failed to send a UDP datagram to `{0}` => `{1}`")]
FailedSendingPacket(String, String),
#[error("failed to receive the UDP response from `{0}` => `{1}`")]
FailedReceivingResponse(String, String),
#[error("failed to parse a UDP response into a RADIUS packet => `{0}`")]
FailedParsingUDPResponse(String),
/// This error is occurred when UDP socket binding has been failed.
#[error("failed to bind a UDP socket; {0}")]
FailedUdpSocketBindingError(String),
/// This error is raised when it failed to establish the connection.
#[error("failed to establish a UDP connection to {0}; {1}")]
FailedEstablishingUdpConnectionError(String, String),
/// This error is raised when encoding RADIUS packet has been failed.
#[error("failed to encode a RADIUS request; {0}")]
FailedRadiusPacketEncodingError(String),
/// This error is raised when it fails to send a RADIUS packet.
#[error("failed to send a UDP datagram to {0}; {1}")]
FailedSendingRadiusPacketError(String, String),
/// This error is raised when it fails to receive a RADIUS response.
#[error("failed to receive the UDP response from {0}; {1}")]
FailedReceivingResponseError(String, String),
/// This error is raised when it fails to decode a RADIUS response packet.
#[error("failed to decode a RADIUS response packet; {0}")]
FailedDecodingRadiusResponseError(String),
/// This error is raised when it exceeds the connection timeout duration.
/// Connection timeout means it fails to establish a connection in time.
#[error("connection timeout")]
ConnectionTimeoutError(),
/// This error is raised when it exceeds the socket timeout duration.
/// Socket timeout means it fails to receive a response from the request target in time.
#[error("socket timeout")]
SocketTimeoutError(),
}
@@ -74,7 +86,7 @@ impl Client {
let conn = match UdpSocket::bind(local_addr).await {
Ok(conn) => conn,
Err(e) => return Err(FailedUdpSocketBinding(e.to_string())),
Err(e) => return Err(ClientError::FailedUdpSocketBindingError(e.to_string())),
};
match self.connection_timeout {
@@ -89,7 +101,12 @@ impl Client {
let request_data = match request_packet.encode() {
Ok(encoded) => encoded,
Err(e) => return Err(FailedRadiusPacketEncoding(format!("{:?}", e))),
Err(e) => {
return Err(ClientError::FailedRadiusPacketEncodingError(format!(
"{:?}",
e
)))
}
};
let response = match self.socket_timeout {
@@ -109,14 +126,20 @@ impl Client {
match Packet::decode(&response.to_vec(), request_packet.get_secret()) {
Ok(response_packet) => Ok(response_packet),
Err(e) => Err(FailedParsingUDPResponse(format!("{:?}", e))),
Err(e) => Err(ClientError::FailedDecodingRadiusResponseError(format!(
"{:?}",
e
))),
}
}
async fn connect(&self, conn: &UdpSocket, remote_addr: &SocketAddr) -> Result<(), ClientError> {
match conn.connect(remote_addr).await {
Ok(_) => Ok(()),
Err(e) => Err(FailedConnection(remote_addr.to_string(), e.to_string())),
Err(e) => Err(ClientError::FailedEstablishingUdpConnectionError(
remote_addr.to_string(),
e.to_string(),
)),
}
}
@@ -128,13 +151,18 @@ impl Client {
) -> Result<Vec<u8>, ClientError> {
match conn.send(request_data).await {
Ok(_) => {}
Err(e) => return Err(FailedSendingPacket(remote_addr.to_string(), e.to_string())),
Err(e) => {
return Err(ClientError::FailedSendingRadiusPacketError(
remote_addr.to_string(),
e.to_string(),
))
}
};
let mut buf = vec![0; Self::MAX_DATAGRAM_SIZE];
match conn.recv(&mut buf).await {
Ok(len) => Ok(buf[..len].to_vec()),
Err(e) => Err(FailedReceivingResponse(
Err(e) => Err(ClientError::FailedReceivingResponseError(
remote_addr.to_string(),
e.to_string(),
)),

View File

@@ -4,8 +4,12 @@ use thiserror::Error;
#[derive(Error, Debug)]
pub enum SecretProviderError {
#[error("failed to fetch a secret value => `{0}`")]
FailedFetching(String),
/// An error that represents a failure to fetch a secret value from the provider.
#[error("failed to fetch a secret value: {0}")]
FailedFetchingError(String),
/// An error that represents a generic (i.e. unclassified) error that occurs on the secret value provider.
#[error("unexpected error: {0}")]
GenericError(String),
}
/// SecretProvider is a provider for secret value.

View File

@@ -9,23 +9,39 @@ use crate::tag::{Tag, UNUSED_TAG_VALUE};
#[derive(Error, PartialEq, 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")]
/// This error is raised on the length of given plain text for user-password exceeds the maximum limit.
#[error("the maximum length of the plain text for user-password is 128, but the given value has {0} bytes")]
UserPasswordPlainTextMaximumLengthExceededError(usize),
/// This error is raised when the given secret value for a password is empty.
#[error("secret for password mustn't be empty, but the given value is empty")]
PasswordSecretMissingError(),
/// This error is raised when the given request-authenticator for the password doesn't have 16 bytes length exactly.
#[error("request authenticator for password has to have 16-bytes payload, but the given value doesn't")]
InvalidRequestAuthenticatorLength(),
#[error("invalid attribute length: {0}")]
InvalidAttributeLengthError(usize),
// ^ TODO: more meaningful error message
#[error("unexpected decoding error: {0}")]
UnexpectedDecodingError(String),
/// This error is raised when attribute length is conflicted with the expected.
#[error("invalid attribute length: expected={0}, actual={1} bytes")]
InvalidAttributeLengthError(String, usize),
/// This error is raised when the tagged-value doesn't have a tag byte.
#[error("tag value is missing")]
TagMissingError(),
/// This error represents AVP decoding error.
#[error("decoding error: {0}")]
DecodingError(String),
/// This error is raised when the MSB of salt is invalid.
#[error("invalid salt. the MSB has to be 1, but given value isn't: {0}")]
InvalidSaltMSBError(u8),
/// This error is raised when a tag is invalid for the tagged-staring value.
#[error("invalid tag for string value. this must not be zero")]
InvalidTagForStringValueError(),
/// This error is raised when a tag is invalid for the tagged-integer value.
#[error("invalid tag for integer value. this must be less than or equal 0x1f")]
InvalidTagForIntegerValueError(),
}
@@ -115,7 +131,10 @@ impl AVP {
pub fn from_ipv4_prefix(typ: AVPType, prefix: &[u8]) -> Result<Self, AVPError> {
let prefix_len = prefix.len();
if prefix_len != 4 {
return Err(AVPError::InvalidAttributeLengthError(prefix_len));
return Err(AVPError::InvalidAttributeLengthError(
"4 bytes".to_owned(),
prefix_len,
));
}
Ok(AVP {
@@ -136,7 +155,10 @@ impl AVP {
pub fn from_ipv6_prefix(typ: AVPType, prefix: &[u8]) -> Result<Self, AVPError> {
let prefix_len = prefix.len();
if prefix_len > 16 {
return Err(AVPError::InvalidAttributeLengthError(prefix_len));
return Err(AVPError::InvalidAttributeLengthError(
"16 bytes".to_owned(),
prefix_len,
));
}
Ok(AVP {
@@ -169,11 +191,13 @@ impl AVP {
// ref: https://tools.ietf.org/html/rfc2865#section-5.2
if plain_text.len() > 128 {
return Err(AVPError::PlainTextMaximumLengthExceededError());
return Err(AVPError::UserPasswordPlainTextMaximumLengthExceededError(
plain_text.len(),
));
}
if secret.is_empty() {
return Err(AVPError::SecretMissingError());
return Err(AVPError::PasswordSecretMissingError());
}
if request_authenticator.len() != 16 {
@@ -251,6 +275,7 @@ impl AVP {
if request_authenticator.len() > 240 {
return Err(AVPError::InvalidAttributeLengthError(
"240 bytes".to_owned(),
request_authenticator.len(),
));
}
@@ -259,7 +284,7 @@ impl AVP {
let salt: [u8; 2] = [rng.gen::<u8>() | 0x80, rng.gen::<u8>()];
if secret.is_empty() {
return Err(AVPError::SecretMissingError());
return Err(AVPError::PasswordSecretMissingError());
}
if request_authenticator.len() != 16 {
@@ -313,13 +338,16 @@ impl AVP {
pub fn encode_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()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{} bytes", U32_SIZE),
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())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -327,20 +355,23 @@ impl AVP {
pub fn encode_u16(&self) -> Result<u16, AVPError> {
const U16_SIZE: usize = std::mem::size_of::<u16>();
if self.value.len() != U16_SIZE {
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{} bytes", U16_SIZE),
self.value.len(),
));
}
let (int_bytes, _) = self.value.split_at(U16_SIZE);
match int_bytes.try_into() {
Ok(boxed_array) => Ok(u16::from_be_bytes(boxed_array)),
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
/// (This method is for dictionary developers) encode an AVP into a tag and u32 value.
pub fn encode_tagged_u32(&self) -> Result<(u32, Tag), AVPError> {
if self.value.is_empty() {
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
return Err(AVPError::TagMissingError());
}
let tag = Tag {
@@ -356,12 +387,15 @@ impl AVP {
const U32_SIZE: usize = std::mem::size_of::<u32>();
if self.value[1..].len() != U32_SIZE {
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{} bytes", U32_SIZE + 1),
self.value.len(),
));
}
let (int_bytes, _) = self.value[1..].split_at(U32_SIZE);
match int_bytes.try_into() {
Ok(boxed_array) => Ok((u32::from_be_bytes(boxed_array), tag)),
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -369,7 +403,7 @@ impl AVP {
pub fn encode_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())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -377,7 +411,7 @@ impl AVP {
pub fn encode_tagged_string(&self) -> Result<(String, Option<Tag>), AVPError> {
let string_vec = self.value.to_vec();
if string_vec.is_empty() {
return Err(AVPError::InvalidAttributeLengthError(string_vec.len()));
return Err(AVPError::TagMissingError());
}
let tag = Tag {
@@ -392,7 +426,7 @@ impl AVP {
if tag.is_valid_value() {
return match String::from_utf8(string_vec[1..].to_vec()) {
Ok(str) => Ok((str, Some(tag))),
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
};
}
@@ -405,7 +439,7 @@ impl AVP {
// interpreted as the first byte of the following String field.
match String::from_utf8(self.value.to_vec()) {
Ok(str) => Ok((str, None)),
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -418,13 +452,16 @@ impl AVP {
pub fn encode_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()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{} bytes", IPV4_SIZE),
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())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -432,7 +469,10 @@ impl AVP {
pub fn encode_ipv4_prefix(&self) -> Result<Vec<u8>, AVPError> {
match self.value.len() == 6 {
true => Ok(self.value[2..].to_owned()),
false => Err(AVPError::InvalidAttributeLengthError(self.value.len())),
false => Err(AVPError::InvalidAttributeLengthError(
"6 bytes".to_owned(),
self.value.len(),
)),
}
}
@@ -440,13 +480,16 @@ impl AVP {
pub fn encode_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()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{} bytes", IPV6_SIZE),
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())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -454,7 +497,10 @@ impl AVP {
pub fn encode_ipv6_prefix(&self) -> Result<Vec<u8>, AVPError> {
match self.value.len() >= 2 {
true => Ok(self.value[2..].to_owned()),
false => Err(AVPError::InvalidAttributeLengthError(self.value.len())),
false => Err(AVPError::InvalidAttributeLengthError(
"2+ bytes".to_owned(),
self.value.len(),
)),
}
}
@@ -465,11 +511,14 @@ impl AVP {
request_authenticator: &[u8],
) -> Result<Vec<u8>, AVPError> {
if self.value.len() < 16 || self.value.len() > 128 {
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
return Err(AVPError::InvalidAttributeLengthError(
"16 >= bytes && 128 <= bytes".to_owned(),
self.value.len(),
));
}
if secret.is_empty() {
return Err(AVPError::SecretMissingError());
return Err(AVPError::PasswordSecretMissingError());
}
if request_authenticator.len() != 16 {
@@ -506,7 +555,10 @@ impl AVP {
pub fn encode_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()));
return Err(AVPError::InvalidAttributeLengthError(
format!("{}", U32_SIZE),
self.value.len(),
));
}
let (int_bytes, _) = self.value.split_at(U32_SIZE);
@@ -515,7 +567,7 @@ impl AVP {
let timestamp = u32::from_be_bytes(boxed_array);
Ok(Utc.timestamp(timestamp as i64, 0))
}
Err(e) => Err(AVPError::UnexpectedDecodingError(e.to_string())),
Err(e) => Err(AVPError::DecodingError(e.to_string())),
}
}
@@ -525,11 +577,11 @@ impl AVP {
secret: &[u8],
request_authenticator: &[u8],
) -> Result<(Vec<u8>, Tag), AVPError> {
if self.value.len() - 3 < 16
|| self.value.len() - 3 > 240
|| (self.value.len() - 3) % 16 != 0
{
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
if self.value.len() < 19 || self.value.len() > 243 || (self.value.len() - 3) % 16 != 0 {
return Err(AVPError::InvalidAttributeLengthError(
"19 <= bytes && bytes <= 242 && (bytes - 3) % 16 == 0".to_owned(),
self.value.len(),
));
}
if self.value[1] & 0x80 != 0x80 {
@@ -538,7 +590,7 @@ impl AVP {
}
if secret.is_empty() {
return Err(AVPError::SecretMissingError());
return Err(AVPError::PasswordSecretMissingError());
}
if request_authenticator.len() != 16 {
@@ -804,10 +856,16 @@ mod tests {
#[test]
fn should_convert_ipv4_prefix_fail_because_of_invalid_prefix_length() {
let avp = AVP::from_ipv4_prefix(1, &[0x01, 0x02, 0x03]);
assert_eq!(avp.unwrap_err(), AVPError::InvalidAttributeLengthError(3));
assert_eq!(
avp.unwrap_err(),
AVPError::InvalidAttributeLengthError("4 bytes".to_owned(), 3)
);
let avp = AVP::from_ipv4_prefix(1, &[0x01, 0x02, 0x03, 0x04, 0x05]);
assert_eq!(avp.unwrap_err(), AVPError::InvalidAttributeLengthError(5));
assert_eq!(
avp.unwrap_err(),
AVPError::InvalidAttributeLengthError("4 bytes".to_owned(), 5)
);
assert_eq!(
AVP {
@@ -816,7 +874,7 @@ mod tests {
}
.encode_ipv4_prefix()
.unwrap_err(),
AVPError::InvalidAttributeLengthError(0)
AVPError::InvalidAttributeLengthError("6 bytes".to_owned(), 0)
);
}
@@ -849,6 +907,9 @@ mod tests {
0x0e, 0x0f, 0x10,
],
);
assert_eq!(avp.unwrap_err(), AVPError::InvalidAttributeLengthError(17));
assert_eq!(
avp.unwrap_err(),
AVPError::InvalidAttributeLengthError("16 bytes".to_owned(), 17)
);
}
}

View File

@@ -12,17 +12,28 @@ 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),
/// An error indicates the entire length of the given packet has insufficient length.
#[error("RADIUS packet doesn't have enough length of bytes; it has to be at least {0} bytes, but actual length was {1}")]
InsufficientPacketPayloadLengthError(usize, usize),
/// An error indicates the length that is instructed by a header is insufficient.
#[error("RADIUS packet header indicates the length as {0} bytes, but this is insufficient; this must have {1} bytes at least")]
InsufficientHeaderDefinedPacketLengthError(usize, usize),
/// An error indicates the length that is instructed by a header exceeds the maximum length of the RADIUS packet.
#[error("RADIUS packet header indicates the length as {0} bytes, but this exceeds the maximum length {1} bytes")]
HeaderDefinedPacketLengthExceedsMaximumLimitError(usize, usize),
/// An error that is raised when an error has been occurred on decoding bytes for a packet.
#[error("failed to decode the packet: {0}")]
DecodingError(String),
/// An error that is raised when an error has been occurred on encoding a packet into bytes.
#[error("failed to encode the packet: {0}")]
EncodingError(String),
#[error("Unknown radius packet code: {0}")]
/// An error that is raised when it received unknown packet type code of RADIUS.
#[error("Unknown RADIUS packet type code: {0}")]
UnknownCodeError(String),
}
@@ -69,17 +80,35 @@ impl Packet {
/// This decodes bytes into a Packet.
pub fn decode(bs: &[u8], secret: &[u8]) -> Result<Self, PacketError> {
if bs.len() < RADIUS_PACKET_HEADER_LENGTH {
return Err(PacketError::InsufficientPacketLengthError(
return Err(PacketError::InsufficientPacketPayloadLengthError(
RADIUS_PACKET_HEADER_LENGTH,
bs.len(),
));
}
let len = match bs[2..4].try_into() {
Ok(v) => u16::from_be_bytes(v),
Err(e) => return Err(PacketError::UnexpectedDecodingError(e.to_string())),
Err(e) => return Err(PacketError::DecodingError(e.to_string())),
} as usize;
if len < RADIUS_PACKET_HEADER_LENGTH || len > MAX_PACKET_LENGTH || bs.len() < len {
return Err(PacketError::InvalidPacketLengthError(len));
if len < RADIUS_PACKET_HEADER_LENGTH {
return Err(PacketError::InsufficientHeaderDefinedPacketLengthError(
len,
RADIUS_PACKET_HEADER_LENGTH,
));
}
if len > MAX_PACKET_LENGTH {
return Err(
PacketError::HeaderDefinedPacketLengthExceedsMaximumLimitError(
len,
MAX_PACKET_LENGTH,
),
);
}
if bs.len() < len {
return Err(PacketError::InsufficientPacketPayloadLengthError(
len,
bs.len(),
));
}
let attributes = match Attributes::decode(&bs[RADIUS_PACKET_HEADER_LENGTH..len].to_vec()) {
@@ -266,7 +295,7 @@ mod tests {
use crate::avp::AVP;
use crate::code::Code;
use crate::packet::{Packet, PacketError};
use crate::packet::{Packet, PacketError, MAX_PACKET_LENGTH, RADIUS_PACKET_HEADER_LENGTH};
use crate::rfc2865;
#[test]
@@ -468,19 +497,19 @@ mod tests {
let test_cases = &[
TestCase {
plain_text: "\x01",
expected_error: PacketError::InsufficientPacketLengthError(20),
expected_error: PacketError::InsufficientPacketPayloadLengthError(RADIUS_PACKET_HEADER_LENGTH, 1),
},
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),
expected_error: PacketError::InsufficientHeaderDefinedPacketLengthError(0, RADIUS_PACKET_HEADER_LENGTH),
},
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),
expected_error: PacketError::HeaderDefinedPacketLengthExceedsMaximumLimitError(32639, MAX_PACKET_LENGTH),
},
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),
expected_error: PacketError::InsufficientPacketPayloadLengthError(22, 21),
},
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",

View File

@@ -69,7 +69,10 @@ pub fn delete_arap_password(packet: &mut Packet) {
}
pub fn add_arap_password(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 16 {
return Err(AVPError::InvalidAttributeLengthError(16));
return Err(AVPError::InvalidAttributeLengthError(
"16 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(ARAP_PASSWORD_TYPE, value));
Ok(())
@@ -91,7 +94,10 @@ pub fn delete_arap_features(packet: &mut Packet) {
}
pub fn add_arap_features(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 14 {
return Err(AVPError::InvalidAttributeLengthError(14));
return Err(AVPError::InvalidAttributeLengthError(
"14 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(ARAP_FEATURES_TYPE, value));
Ok(())
@@ -290,7 +296,10 @@ pub fn delete_arap_challenge_response(packet: &mut Packet) {
}
pub fn add_arap_challenge_response(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 8 {
return Err(AVPError::InvalidAttributeLengthError(8));
return Err(AVPError::InvalidAttributeLengthError(
"8 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(ARAP_CHALLENGE_RESPONSE_TYPE, value));
Ok(())

View File

@@ -31,7 +31,10 @@ pub fn delete_framed_interface_id(packet: &mut Packet) {
}
pub fn add_framed_interface_id(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 8 {
return Err(AVPError::InvalidAttributeLengthError(8));
return Err(AVPError::InvalidAttributeLengthError(
"8 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(FRAMED_INTERFACE_ID_TYPE, value));
Ok(())

View File

@@ -181,7 +181,10 @@ pub fn delete_pmip6_home_interface_id(packet: &mut Packet) {
}
pub fn add_pmip6_home_interface_id(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 8 {
return Err(AVPError::InvalidAttributeLengthError(8));
return Err(AVPError::InvalidAttributeLengthError(
"8 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(PMIP6_HOME_INTERFACE_ID_TYPE, value));
Ok(())
@@ -205,7 +208,10 @@ pub fn delete_pmip6_visited_interface_id(packet: &mut Packet) {
}
pub fn add_pmip6_visited_interface_id(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 8 {
return Err(AVPError::InvalidAttributeLengthError(8));
return Err(AVPError::InvalidAttributeLengthError(
"8 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(PMIP6_VISITED_INTERFACE_ID_TYPE, value));
Ok(())

View File

@@ -9,7 +9,10 @@ pub fn delete_originating_line_info(packet: &mut Packet) {
}
pub fn add_originating_line_info(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 2 {
return Err(AVPError::InvalidAttributeLengthError(2));
return Err(AVPError::InvalidAttributeLengthError(
"2 bytes".to_owned(),
value.len(),
));
}
packet.add(AVP::from_bytes(ORIGINATING_LINE_INFO_TYPE, value));
Ok(())