1*ffe74184SMartin Algesten use crate::attributes::*; 2*ffe74184SMartin Algesten use crate::checks::*; 3*ffe74184SMartin Algesten use crate::error::*; 4*ffe74184SMartin Algesten use crate::message::*; 5*ffe74184SMartin Algesten 6*ffe74184SMartin Algesten use std::collections::HashMap; 7*ffe74184SMartin Algesten use std::fmt; 8*ffe74184SMartin Algesten 9*ffe74184SMartin Algesten // ErrorCodeAttribute represents ERROR-CODE attribute. 10*ffe74184SMartin Algesten // 11*ffe74184SMartin Algesten // RFC 5389 Section 15.6 12*ffe74184SMartin Algesten #[derive(Default)] 13*ffe74184SMartin Algesten pub struct ErrorCodeAttribute { 14*ffe74184SMartin Algesten pub code: ErrorCode, 15*ffe74184SMartin Algesten pub reason: Vec<u8>, 16*ffe74184SMartin Algesten } 17*ffe74184SMartin Algesten 18*ffe74184SMartin Algesten impl fmt::Display for ErrorCodeAttribute { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19*ffe74184SMartin Algesten fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 20*ffe74184SMartin Algesten let reason = match String::from_utf8(self.reason.clone()) { 21*ffe74184SMartin Algesten Ok(reason) => reason, 22*ffe74184SMartin Algesten Err(_) => return Err(fmt::Error {}), 23*ffe74184SMartin Algesten }; 24*ffe74184SMartin Algesten 25*ffe74184SMartin Algesten write!(f, "{}: {}", self.code.0, reason) 26*ffe74184SMartin Algesten } 27*ffe74184SMartin Algesten } 28*ffe74184SMartin Algesten 29*ffe74184SMartin Algesten // constants for ERROR-CODE encoding. 30*ffe74184SMartin Algesten const ERROR_CODE_CLASS_BYTE: usize = 2; 31*ffe74184SMartin Algesten const ERROR_CODE_NUMBER_BYTE: usize = 3; 32*ffe74184SMartin Algesten const ERROR_CODE_REASON_START: usize = 4; 33*ffe74184SMartin Algesten const ERROR_CODE_REASON_MAX_B: usize = 763; 34*ffe74184SMartin Algesten const ERROR_CODE_MODULO: u16 = 100; 35*ffe74184SMartin Algesten 36*ffe74184SMartin Algesten impl Setter for ErrorCodeAttribute { 37*ffe74184SMartin Algesten // add_to adds ERROR-CODE to m. add_to(&self, m: &mut Message) -> Result<()>38*ffe74184SMartin Algesten fn add_to(&self, m: &mut Message) -> Result<()> { 39*ffe74184SMartin Algesten check_overflow( 40*ffe74184SMartin Algesten ATTR_ERROR_CODE, 41*ffe74184SMartin Algesten self.reason.len() + ERROR_CODE_REASON_START, 42*ffe74184SMartin Algesten ERROR_CODE_REASON_MAX_B + ERROR_CODE_REASON_START, 43*ffe74184SMartin Algesten )?; 44*ffe74184SMartin Algesten 45*ffe74184SMartin Algesten let mut value: Vec<u8> = Vec::with_capacity(ERROR_CODE_REASON_MAX_B); 46*ffe74184SMartin Algesten 47*ffe74184SMartin Algesten let number = (self.code.0 % ERROR_CODE_MODULO) as u8; // error code modulo 100 48*ffe74184SMartin Algesten let class = (self.code.0 / ERROR_CODE_MODULO) as u8; // hundred digit 49*ffe74184SMartin Algesten value.extend_from_slice(&[0, 0]); 50*ffe74184SMartin Algesten value.push(class); // [ERROR_CODE_CLASS_BYTE] 51*ffe74184SMartin Algesten value.push(number); //[ERROR_CODE_NUMBER_BYTE] = 52*ffe74184SMartin Algesten value.extend_from_slice(&self.reason); //[ERROR_CODE_REASON_START:] 53*ffe74184SMartin Algesten 54*ffe74184SMartin Algesten m.add(ATTR_ERROR_CODE, &value); 55*ffe74184SMartin Algesten 56*ffe74184SMartin Algesten Ok(()) 57*ffe74184SMartin Algesten } 58*ffe74184SMartin Algesten } 59*ffe74184SMartin Algesten 60*ffe74184SMartin Algesten impl Getter for ErrorCodeAttribute { 61*ffe74184SMartin Algesten // GetFrom decodes ERROR-CODE from m. Reason is valid until m.Raw is valid. get_from(&mut self, m: &Message) -> Result<()>62*ffe74184SMartin Algesten fn get_from(&mut self, m: &Message) -> Result<()> { 63*ffe74184SMartin Algesten let v = m.get(ATTR_ERROR_CODE)?; 64*ffe74184SMartin Algesten 65*ffe74184SMartin Algesten if v.len() < ERROR_CODE_REASON_START { 66*ffe74184SMartin Algesten return Err(Error::ErrUnexpectedEof); 67*ffe74184SMartin Algesten } 68*ffe74184SMartin Algesten 69*ffe74184SMartin Algesten let class = v[ERROR_CODE_CLASS_BYTE] as u16; 70*ffe74184SMartin Algesten let number = v[ERROR_CODE_NUMBER_BYTE] as u16; 71*ffe74184SMartin Algesten let code = class * ERROR_CODE_MODULO + number; 72*ffe74184SMartin Algesten self.code = ErrorCode(code); 73*ffe74184SMartin Algesten self.reason = v[ERROR_CODE_REASON_START..].to_vec(); 74*ffe74184SMartin Algesten 75*ffe74184SMartin Algesten Ok(()) 76*ffe74184SMartin Algesten } 77*ffe74184SMartin Algesten } 78*ffe74184SMartin Algesten 79*ffe74184SMartin Algesten // ErrorCode is code for ERROR-CODE attribute. 80*ffe74184SMartin Algesten #[derive(PartialEq, Eq, Hash, Copy, Clone, Default)] 81*ffe74184SMartin Algesten pub struct ErrorCode(pub u16); 82*ffe74184SMartin Algesten 83*ffe74184SMartin Algesten impl Setter for ErrorCode { 84*ffe74184SMartin Algesten // add_to adds ERROR-CODE with default reason to m. If there 85*ffe74184SMartin Algesten // is no default reason, returns ErrNoDefaultReason. add_to(&self, m: &mut Message) -> Result<()>86*ffe74184SMartin Algesten fn add_to(&self, m: &mut Message) -> Result<()> { 87*ffe74184SMartin Algesten if let Some(reason) = ERROR_REASONS.get(self) { 88*ffe74184SMartin Algesten let a = ErrorCodeAttribute { 89*ffe74184SMartin Algesten code: *self, 90*ffe74184SMartin Algesten reason: reason.clone(), 91*ffe74184SMartin Algesten }; 92*ffe74184SMartin Algesten a.add_to(m) 93*ffe74184SMartin Algesten } else { 94*ffe74184SMartin Algesten Err(Error::ErrNoDefaultReason) 95*ffe74184SMartin Algesten } 96*ffe74184SMartin Algesten } 97*ffe74184SMartin Algesten } 98*ffe74184SMartin Algesten 99*ffe74184SMartin Algesten // Possible error codes. 100*ffe74184SMartin Algesten pub const CODE_TRY_ALTERNATE: ErrorCode = ErrorCode(300); 101*ffe74184SMartin Algesten pub const CODE_BAD_REQUEST: ErrorCode = ErrorCode(400); 102*ffe74184SMartin Algesten pub const CODE_UNAUTHORIZED: ErrorCode = ErrorCode(401); 103*ffe74184SMartin Algesten pub const CODE_UNKNOWN_ATTRIBUTE: ErrorCode = ErrorCode(420); 104*ffe74184SMartin Algesten pub const CODE_STALE_NONCE: ErrorCode = ErrorCode(438); 105*ffe74184SMartin Algesten pub const CODE_ROLE_CONFLICT: ErrorCode = ErrorCode(487); 106*ffe74184SMartin Algesten pub const CODE_SERVER_ERROR: ErrorCode = ErrorCode(500); 107*ffe74184SMartin Algesten 108*ffe74184SMartin Algesten // DEPRECATED constants. 109*ffe74184SMartin Algesten // DEPRECATED, use CODE_UNAUTHORIZED. 110*ffe74184SMartin Algesten pub const CODE_UNAUTHORISED: ErrorCode = CODE_UNAUTHORIZED; 111*ffe74184SMartin Algesten 112*ffe74184SMartin Algesten // Error codes from RFC 5766. 113*ffe74184SMartin Algesten // 114*ffe74184SMartin Algesten // RFC 5766 Section 15 115*ffe74184SMartin Algesten pub const CODE_FORBIDDEN: ErrorCode = ErrorCode(403); // Forbidden 116*ffe74184SMartin Algesten pub const CODE_ALLOC_MISMATCH: ErrorCode = ErrorCode(437); // Allocation Mismatch 117*ffe74184SMartin Algesten pub const CODE_WRONG_CREDENTIALS: ErrorCode = ErrorCode(441); // Wrong Credentials 118*ffe74184SMartin Algesten pub const CODE_UNSUPPORTED_TRANS_PROTO: ErrorCode = ErrorCode(442); // Unsupported Transport Protocol 119*ffe74184SMartin Algesten pub const CODE_ALLOC_QUOTA_REACHED: ErrorCode = ErrorCode(486); // Allocation Quota Reached 120*ffe74184SMartin Algesten pub const CODE_INSUFFICIENT_CAPACITY: ErrorCode = ErrorCode(508); // Insufficient Capacity 121*ffe74184SMartin Algesten 122*ffe74184SMartin Algesten // Error codes from RFC 6062. 123*ffe74184SMartin Algesten // 124*ffe74184SMartin Algesten // RFC 6062 Section 6.3 125*ffe74184SMartin Algesten pub const CODE_CONN_ALREADY_EXISTS: ErrorCode = ErrorCode(446); 126*ffe74184SMartin Algesten pub const CODE_CONN_TIMEOUT_OR_FAILURE: ErrorCode = ErrorCode(447); 127*ffe74184SMartin Algesten 128*ffe74184SMartin Algesten // Error codes from RFC 6156. 129*ffe74184SMartin Algesten // 130*ffe74184SMartin Algesten // RFC 6156 Section 10.2 131*ffe74184SMartin Algesten pub const CODE_ADDR_FAMILY_NOT_SUPPORTED: ErrorCode = ErrorCode(440); // Address Family not Supported 132*ffe74184SMartin Algesten pub const CODE_PEER_ADDR_FAMILY_MISMATCH: ErrorCode = ErrorCode(443); // Peer Address Family Mismatch 133*ffe74184SMartin Algesten 134*ffe74184SMartin Algesten lazy_static! { 135*ffe74184SMartin Algesten pub static ref ERROR_REASONS:HashMap<ErrorCode, Vec<u8>> = 136*ffe74184SMartin Algesten [ 137*ffe74184SMartin Algesten (CODE_TRY_ALTERNATE, b"Try Alternate".to_vec()), 138*ffe74184SMartin Algesten (CODE_BAD_REQUEST, b"Bad Request".to_vec()), 139*ffe74184SMartin Algesten (CODE_UNAUTHORIZED, b"Unauthorized".to_vec()), 140*ffe74184SMartin Algesten (CODE_UNKNOWN_ATTRIBUTE, b"Unknown Attribute".to_vec()), 141*ffe74184SMartin Algesten (CODE_STALE_NONCE, b"Stale Nonce".to_vec()), 142*ffe74184SMartin Algesten (CODE_SERVER_ERROR, b"Server Error".to_vec()), 143*ffe74184SMartin Algesten (CODE_ROLE_CONFLICT, b"Role Conflict".to_vec()), 144*ffe74184SMartin Algesten 145*ffe74184SMartin Algesten // RFC 5766. 146*ffe74184SMartin Algesten (CODE_FORBIDDEN, b"Forbidden".to_vec()), 147*ffe74184SMartin Algesten (CODE_ALLOC_MISMATCH, b"Allocation Mismatch".to_vec()), 148*ffe74184SMartin Algesten (CODE_WRONG_CREDENTIALS, b"Wrong Credentials".to_vec()), 149*ffe74184SMartin Algesten (CODE_UNSUPPORTED_TRANS_PROTO, b"Unsupported Transport Protocol".to_vec()), 150*ffe74184SMartin Algesten (CODE_ALLOC_QUOTA_REACHED, b"Allocation Quota Reached".to_vec()), 151*ffe74184SMartin Algesten (CODE_INSUFFICIENT_CAPACITY, b"Insufficient Capacity".to_vec()), 152*ffe74184SMartin Algesten 153*ffe74184SMartin Algesten // RFC 6062. 154*ffe74184SMartin Algesten (CODE_CONN_ALREADY_EXISTS, b"Connection Already Exists".to_vec()), 155*ffe74184SMartin Algesten (CODE_CONN_TIMEOUT_OR_FAILURE, b"Connection Timeout or Failure".to_vec()), 156*ffe74184SMartin Algesten 157*ffe74184SMartin Algesten // RFC 6156. 158*ffe74184SMartin Algesten (CODE_ADDR_FAMILY_NOT_SUPPORTED, b"Address Family not Supported".to_vec()), 159*ffe74184SMartin Algesten (CODE_PEER_ADDR_FAMILY_MISMATCH, b"Peer Address Family Mismatch".to_vec()), 160*ffe74184SMartin Algesten ].iter().cloned().collect(); 161*ffe74184SMartin Algesten 162*ffe74184SMartin Algesten } 163