1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::error::Error;
use std::fmt;
use std::string::FromUtf8Error;

use openssl::ssl::error::SslError;

pub enum DecodeError {
  ParseUtf8Error(FromUtf8Error),
  UnknownDnsClassValue(u16),
  UnknownDnsClassStr(String),
  UnknownRecordTypeValue(u16),
  UnknownRecordTypeStr(String),
  UnknownAlgorithmTypeValue(u8),
  NoRecordDataType,
  NoRecordDataLength,
  EOF,
  Sig0NotLast,
  EdnsNameNotRoot,
  DnsKeyProtocolNot3(u8),
  UnrecognizedNsec3Flags(u8),
  UnrecognizedLabelCode(u8),
  IncorrectRDataLengthRead(usize, usize),
  BadPublicKey,
  SslError(SslError),
  MoreThanOneEdns,
}

impl fmt::Debug for DecodeError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    fmt::Display::fmt(&self, f)
  }
}

impl fmt::Display for DecodeError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      DecodeError::ParseUtf8Error(ref err) => err.fmt(f),
      DecodeError::UnknownDnsClassValue(ref val) => write!(f, "DnsClass value unknown: {}", val),
      DecodeError::UnknownDnsClassStr(ref val) => write!(f, "DnsClass string unknown: {}", val),
      DecodeError::UnknownRecordTypeValue(ref val) => write!(f, "RecordType value unknown: {}", val),
      DecodeError::UnknownRecordTypeStr(ref val) => write!(f, "RecordType string unknown: {}", val),
      DecodeError::UnknownAlgorithmTypeValue(ref val) => write!(f, "AlgorithmType value unknown: {}", val),
      DecodeError::NoRecordDataType => write!(f, "There was no record data type specified"),
      DecodeError::NoRecordDataLength => write!(f, "There was no record data length specified"),
      DecodeError::EOF => write!(f, "End of input reached before next read could complete"),
      DecodeError::Sig0NotLast => write!(f, "SIG0 must be final resource record"),
      DecodeError::EdnsNameNotRoot => write!(f, "EDNS resource record label must be the root label (.)"),
      DecodeError::DnsKeyProtocolNot3(ref val) => write!(f, "DnsKey value unknown, must be 3: {}", val),
      DecodeError::UnrecognizedNsec3Flags(ref val) => write!(f, "Nsec3 flags should be 0b0000000*: {:b}", val),
      DecodeError::UnrecognizedLabelCode(ref val) => write!(f, "Unrecognized Label Code: {:b}", val),
      DecodeError::IncorrectRDataLengthRead(ref read, ref rdata_length) => write!(f, "IncorrectRDataLengthRead read: {}, expected: {}", read, rdata_length),
      DecodeError::BadPublicKey => write!(f, "BadPublicKey"),
      DecodeError::SslError(ref err) => err.fmt(f),
      DecodeError::MoreThanOneEdns => write!(f, "More than one EDNS record is already set"),
    }
  }
}

impl Error for DecodeError {
  fn description(&self) -> &str {
    match *self {
      DecodeError::ParseUtf8Error(ref err) => err.description(),
      DecodeError::UnknownDnsClassValue(..) => "DnsClass value unknown",
      DecodeError::UnknownDnsClassStr(..) => "DnsClass string unknown",
      DecodeError::UnknownRecordTypeValue(..) => "RecordType value unknown",
      DecodeError::UnknownRecordTypeStr(..) => "RecordType string unknown",
      DecodeError::UnknownAlgorithmTypeValue(..) => "AlgorithmType value unknown",
      DecodeError::NoRecordDataType => "RecordType unspecified",
      DecodeError::NoRecordDataLength => "RecordData length unspecified",
      DecodeError::EOF => "End of input",
      DecodeError::Sig0NotLast => "SIG0 must be final resource record",
      DecodeError::EdnsNameNotRoot => "EDNS resource record label must be the root label (.)",
      DecodeError::DnsKeyProtocolNot3(..) => "DnsKey value unknown, must be 3",
      DecodeError::UnrecognizedNsec3Flags(..) => "Nsec3 flags should be 0b0000000*",
      DecodeError::UnrecognizedLabelCode(..) => "Unrecognized label code",
      DecodeError::IncorrectRDataLengthRead(..) => "IncorrectRDataLengthRead",
      DecodeError::BadPublicKey => "BadPublicKey",
      DecodeError::SslError(ref err) => err.description(),
      DecodeError::MoreThanOneEdns => "More than one EDNS record is already set",
    }
  }

  fn cause(&self) -> Option<&Error> {
    match *self {
      DecodeError::ParseUtf8Error(ref err) => Some(err),
      _ => None,
    }
  }
}

impl From<FromUtf8Error> for DecodeError {
    fn from(err: FromUtf8Error) -> DecodeError {
        DecodeError::ParseUtf8Error(err)
    }
}

impl From<SslError> for DecodeError {
    fn from(err: SslError) -> DecodeError {
        DecodeError::SslError(err)
    }
}