pub mod icmp; #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum Kind { /// ping应答,type=0 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data ... +-+-+-+-+- */ EchoReply, /// 目的地不可达,差错报文的一种,路由器收到一个不能转发的数据报,会向源地址返回这个报文,type=3 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ DestinationUnreachable, /// 源抑制报文,用于防止接收端缓存溢出,接收设备发送这个来请求源设备降低发送速度,type=4 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ SourceQuench, /// 重定向报文,当路由器接收包的接口正好是去往目的地的出口时,会向源地址发送重定向报文,告知源直接将数据发往自己的下一跳,type=5 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Gateway Internet Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ Redirect, /// ping请求,type=8 EchoRequest, /// 路由器通告,type=9, RouterAdvertisement, /// 路由器请求,type=10 RouterSolicitation, /// 报文ttl为0后,路由器会向源发送此报文,type=11 /// Tracert工作原理: /// 首先向目的地发送ttl=1的包,下一跳路由器收到后ttl-1,此时ttl=0,将向源发送 ICMP time exceeded /// 再发送ttl=2的包,以此类推,直到目标主机接收到改包,此时不会回复ICMP time exceeded,代表已经探测到目的地 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ TimeExceeded, /// 参数错误,数据有误、校验和不对等,type=12 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Pointer | unused | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Internet Header + 64 bits of Original Data Datagram | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 注:Pointer指示错误的位置 */ ParameterProblem, /// 时间戳请求,type=13 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Originate Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Receive Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Transmit Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ TimestampRequest, /// 时间戳响应,type=14 TimestampReply, /// 信息请求,type=15 /* 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type | Code | Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ InformationRequest, /// 信息响应,type=16 InformationReply, /// 地址掩码请求,type=17 AddressMaskRequest, /// 地址掩码应答,type=18 AddressMaskReply, /// TraceRoute, /// Unknown(u8), } impl From for Kind { fn from(value: u8) -> Kind { use self::Kind::*; match value { 0 => EchoReply, 3 => DestinationUnreachable, 4 => SourceQuench, 5 => Redirect, 8 => EchoRequest, 9 => RouterAdvertisement, 10 => RouterSolicitation, 11 => TimeExceeded, 12 => ParameterProblem, 13 => TimestampRequest, 14 => TimestampReply, 15 => InformationRequest, 16 => InformationReply, 17 => AddressMaskRequest, 18 => AddressMaskReply, 30 => TraceRoute, v => Unknown(v), } } } impl Into for Kind { fn into(self) -> u8 { use self::Kind::*; match self { EchoReply => 0, DestinationUnreachable => 3, SourceQuench => 4, Redirect => 5, EchoRequest => 8, RouterAdvertisement => 9, RouterSolicitation => 10, TimeExceeded => 11, ParameterProblem => 12, TimestampRequest => 13, TimestampReply => 14, InformationRequest => 15, InformationReply => 16, AddressMaskRequest => 17, AddressMaskReply => 18, TraceRoute => 30, Unknown(v) => v, } } } #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum Code { DestinationUnreachable(DestinationUnreachable), Redirect(Redirect), ParameterProblem(ParameterProblem), Other(u8), } impl Code { pub fn from(kind: Kind, code: u8) -> Code { match kind { Kind::DestinationUnreachable => { Code::DestinationUnreachable(DestinationUnreachable::from(code)) } Kind::Redirect => Code::Redirect(Redirect::from(code)), Kind::ParameterProblem => Code::ParameterProblem(ParameterProblem::from(code)), _ => Code::Other(code), } } } #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum DestinationUnreachable { /// 网络不可达 DestinationNetworkUnreachable, /// 主机不可达 DestinationHostUnreachable, /// 协议不可达 DestinationProtocolUnreachable, /// 端口不可达 DestinationPortUnreachable, /// 需要进行分片但设置不分片比特 FragmentationRequired, /// 源站选路失败 SourceRouteFailed, /// 目的网络未知 DestinationNetworkUnknown, /// 目的主机未知 DestinationHostUnknown, /// 源主机被隔离(作废不用) SourceHostIsolated, /// 目的网络被强制禁止 NetworkAdministrativelyProhibited, /// 目的主机被强制禁止 HostAdministrativelyProhibited, /// 由于服务类型TOS,网络不可达 NetworkUnreachableForTos, /// 由于服务类型TOS,主机不可达 HostUnreachableForTos, /// 由于过滤,通信被强制禁止 CommunicationAdministrativelyProhibited, /// 主机越权 HostPrecedenceViolation, /// 优先中止生效 PrecedentCutoffInEffect, /// Unknown(u8), } /// Codes for Redirect Message packets. #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum Redirect { /// 对网络重定向 RedirectDatagramForNetwork, /// 对主机重定向 RedirectDatagramForHost, /// 对服务类型和网络重定向 RedirectDatagramForTosAndNetwork, /// 对服务类型和主机重定向 RedirectDatagramForTosAndHost, /// Unknown(u8), } /// Codes for TimeExceeded Message packets. #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum TimeExceeded { /// TTL超时报文 Transit, /// 分片重组超时报文 Reassembly, /// Unknown(u8), } /// Codes for Parameter Problem packets. #[derive(Eq, PartialEq, Copy, Clone, Debug)] pub enum ParameterProblem { /// 坏的IP首部(包括各种差错) PointerIndicatesError, /// 缺少必需的选项 MissingRequiredData, /// 长度错误 BadLength, /// Unknown(u8), } impl From for DestinationUnreachable { fn from(value: u8) -> Self { use self::DestinationUnreachable::*; match value { 0 => DestinationNetworkUnreachable, 1 => DestinationHostUnreachable, 2 => DestinationProtocolUnreachable, 3 => DestinationPortUnreachable, 4 => FragmentationRequired, 5 => SourceRouteFailed, 6 => DestinationNetworkUnknown, 7 => DestinationHostUnknown, 8 => SourceHostIsolated, 9 => NetworkAdministrativelyProhibited, 10 => HostAdministrativelyProhibited, 11 => NetworkUnreachableForTos, 12 => HostUnreachableForTos, 13 => CommunicationAdministrativelyProhibited, 14 => HostPrecedenceViolation, 15 => PrecedentCutoffInEffect, v => Unknown(v), } } } impl Into for DestinationUnreachable { fn into(self) -> u8 { use self::DestinationUnreachable::*; match self { DestinationNetworkUnreachable => 0, DestinationHostUnreachable => 1, DestinationProtocolUnreachable => 2, DestinationPortUnreachable => 3, FragmentationRequired => 4, SourceRouteFailed => 5, DestinationNetworkUnknown => 6, DestinationHostUnknown => 7, SourceHostIsolated => 8, NetworkAdministrativelyProhibited => 9, HostAdministrativelyProhibited => 10, NetworkUnreachableForTos => 11, HostUnreachableForTos => 12, CommunicationAdministrativelyProhibited => 13, HostPrecedenceViolation => 14, PrecedentCutoffInEffect => 15, Unknown(v) => v, } } } impl From for Redirect { fn from(value: u8) -> Self { use self::Redirect::*; match value { 0 => RedirectDatagramForNetwork, 1 => RedirectDatagramForHost, 2 => RedirectDatagramForTosAndNetwork, 3 => RedirectDatagramForTosAndHost, v => Unknown(v), } } } impl Into for Redirect { fn into(self) -> u8 { use self::Redirect::*; match self { RedirectDatagramForNetwork => 0, RedirectDatagramForHost => 1, RedirectDatagramForTosAndNetwork => 2, RedirectDatagramForTosAndHost => 3, Unknown(v) => v, } } } impl From for TimeExceeded { fn from(value: u8) -> Self { use self::TimeExceeded::*; match value { 0 => Transit, 1 => Reassembly, v => Unknown(v), } } } impl Into for TimeExceeded { fn into(self) -> u8 { use self::TimeExceeded::*; match self { Transit => 0, Reassembly => 1, Unknown(v) => v, } } } impl From for ParameterProblem { fn from(value: u8) -> Self { use self::ParameterProblem::*; match value { 0 => PointerIndicatesError, 1 => MissingRequiredData, 2 => BadLength, v => Unknown(v), } } } impl Into for ParameterProblem { fn into(self) -> u8 { use self::ParameterProblem::*; match self { PointerIndicatesError => 0, MissingRequiredData => 1, BadLength => 2, Unknown(v) => v, } } }