1use core::fmt::{self, Display, Formatter};
40use serde::{Deserialize, Serialize};
41use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U16};
42
43#[derive(
44 Debug,
45 Clone,
46 Copy,
47 PartialEq,
48 Eq,
49 Hash,
50 FromBytes,
51 IntoBytes,
52 Immutable,
53 KnownLayout,
54 Serialize,
55 Deserialize,
56)]
57#[serde(into = "u16")]
58#[serde(try_from = "u16")]
59pub struct EtherProto(pub U16<BigEndian>);
60
61impl Default for EtherProto {
62 fn default() -> Self {
63 EtherProto::IPV4
64 }
65}
66
67impl EtherProto {
68 pub const LOOP: EtherProto = EtherProto(U16::new(0x0060)); pub const PUP: EtherProto = EtherProto(U16::new(0x0200)); pub const PUPAT: EtherProto = EtherProto(U16::new(0x0201)); pub const IPV4: EtherProto = EtherProto(U16::new(0x0800)); pub const X25: EtherProto = EtherProto(U16::new(0x0805)); pub const ARP: EtherProto = EtherProto(U16::new(0x0806)); pub const BPQ: EtherProto = EtherProto(U16::new(0x08FF)); pub const IEEEPUP: EtherProto = EtherProto(U16::new(0x0a00)); pub const IEEEPUPAT: EtherProto = EtherProto(U16::new(0x0a01)); pub const BATMAN: EtherProto = EtherProto(U16::new(0x4305)); pub const DEC: EtherProto = EtherProto(U16::new(0x6000)); pub const DNA_DL: EtherProto = EtherProto(U16::new(0x6001)); pub const DNA_RC: EtherProto = EtherProto(U16::new(0x6002)); pub const DNA_RT: EtherProto = EtherProto(U16::new(0x6003)); pub const LAT: EtherProto = EtherProto(U16::new(0x6004)); pub const DIAG: EtherProto = EtherProto(U16::new(0x6005)); pub const CUST: EtherProto = EtherProto(U16::new(0x6006)); pub const SCA: EtherProto = EtherProto(U16::new(0x6007)); pub const TEB: EtherProto = EtherProto(U16::new(0x6558)); pub const RARP: EtherProto = EtherProto(U16::new(0x8035)); pub const ATALK: EtherProto = EtherProto(U16::new(0x809B)); pub const AARP: EtherProto = EtherProto(U16::new(0x80F3)); pub const VLAN_8021Q: EtherProto = EtherProto(U16::new(0x8100)); pub const IPX: EtherProto = EtherProto(U16::new(0x8137)); pub const IPV6: EtherProto = EtherProto(U16::new(0x86DD)); pub const PAUSE: EtherProto = EtherProto(U16::new(0x8808)); pub const SLOW: EtherProto = EtherProto(U16::new(0x8809)); pub const WCCP: EtherProto = EtherProto(U16::new(0x883E)); pub const MPLS_UC: EtherProto = EtherProto(U16::new(0x8847)); pub const MPLS_MC: EtherProto = EtherProto(U16::new(0x8848)); pub const ATMMPOA: EtherProto = EtherProto(U16::new(0x884c)); pub const PPP_DISC: EtherProto = EtherProto(U16::new(0x8863)); pub const PPP_SES: EtherProto = EtherProto(U16::new(0x8864)); pub const LINK_CTL: EtherProto = EtherProto(U16::new(0x886c)); pub const ATMFATE: EtherProto = EtherProto(U16::new(0x8884)); pub const PAE: EtherProto = EtherProto(U16::new(0x888E)); pub const AOE: EtherProto = EtherProto(U16::new(0x88A2)); pub const VLAN_8021AD: EtherProto = EtherProto(U16::new(0x88A8)); pub const IEEE_802_EX1: EtherProto = EtherProto(U16::new(0x88B5)); pub const TIPC: EtherProto = EtherProto(U16::new(0x88CA)); pub const VLAN_8021AH: EtherProto = EtherProto(U16::new(0x88E7)); pub const MVRP: EtherProto = EtherProto(U16::new(0x88F5)); pub const IEEE_1588: EtherProto = EtherProto(U16::new(0x88F7)); pub const PRP: EtherProto = EtherProto(U16::new(0x88FB)); pub const FCOE: EtherProto = EtherProto(U16::new(0x8906)); pub const TDLS: EtherProto = EtherProto(U16::new(0x890D)); pub const FIP: EtherProto = EtherProto(U16::new(0x8914)); pub const IEEE_80221: EtherProto = EtherProto(U16::new(0x8917)); pub const LOOPBACK: EtherProto = EtherProto(U16::new(0x9000)); pub const QINQ1: EtherProto = EtherProto(U16::new(0x9100)); pub const QINQ2: EtherProto = EtherProto(U16::new(0x9200)); pub const QINQ3: EtherProto = EtherProto(U16::new(0x9300)); pub const EDSA: EtherProto = EtherProto(U16::new(0xDADA)); pub const AF_IUCV: EtherProto = EtherProto(U16::new(0xFBFB)); pub const IEEE_802_3_MIN: EtherProto = EtherProto(U16::new(0x0600)); pub const IEEE_802_3: EtherProto = EtherProto(U16::new(0x0001)); pub const AX25: EtherProto = EtherProto(U16::new(0x0002)); pub const ALL: EtherProto = EtherProto(U16::new(0x0003)); pub const IEEE_802_2: EtherProto = EtherProto(U16::new(0x0004)); pub const SNAP: EtherProto = EtherProto(U16::new(0x0005)); pub const DDCMP: EtherProto = EtherProto(U16::new(0x0006)); pub const WAN_PPP: EtherProto = EtherProto(U16::new(0x0007)); pub const PPP_MP: EtherProto = EtherProto(U16::new(0x0008)); pub const LOCALTALK: EtherProto = EtherProto(U16::new(0x0009)); pub const CAN: EtherProto = EtherProto(U16::new(0x000C)); pub const CANFD: EtherProto = EtherProto(U16::new(0x000D)); pub const PPPTALK: EtherProto = EtherProto(U16::new(0x0010)); pub const TR_802_2: EtherProto = EtherProto(U16::new(0x0011)); pub const MOBITEX: EtherProto = EtherProto(U16::new(0x0015)); pub const CONTROL: EtherProto = EtherProto(U16::new(0x0016)); pub const IRDA: EtherProto = EtherProto(U16::new(0x0017)); pub const ECONET: EtherProto = EtherProto(U16::new(0x0018)); pub const HDLC: EtherProto = EtherProto(U16::new(0x0019)); pub const ARCNET: EtherProto = EtherProto(U16::new(0x001A)); pub const DSA: EtherProto = EtherProto(U16::new(0x001B)); pub const TRAILER: EtherProto = EtherProto(U16::new(0x001C)); pub const PHONET: EtherProto = EtherProto(U16::new(0x00F5)); pub const IEEE802154: EtherProto = EtherProto(U16::new(0x00F6)); pub const CAIF: EtherProto = EtherProto(U16::new(0x00F7)); }
151
152impl Display for EtherProto {
153 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
154 let name = match *self {
155 EtherProto::LOOP => "loop",
157 EtherProto::PUP => "pup",
158 EtherProto::PUPAT => "pupat",
159 EtherProto::IPV4 => "ipv4",
160 EtherProto::X25 => "x25",
161 EtherProto::ARP => "arp",
162 EtherProto::BPQ => "bpq",
163 EtherProto::IEEEPUP => "ieeepup",
164 EtherProto::IEEEPUPAT => "ieeepupat",
165 EtherProto::BATMAN => "batman",
166 EtherProto::DEC => "dec",
167 EtherProto::DNA_DL => "dna_dl",
168 EtherProto::DNA_RC => "dna_rc",
169 EtherProto::DNA_RT => "dna_rt",
170 EtherProto::LAT => "lat",
171 EtherProto::DIAG => "diag",
172 EtherProto::CUST => "cust",
173 EtherProto::SCA => "sca",
174 EtherProto::TEB => "teb",
175 EtherProto::RARP => "rarp",
176 EtherProto::ATALK => "atalk",
177 EtherProto::AARP => "aarp",
178 EtherProto::VLAN_8021Q => "vlan_8021q",
179 EtherProto::IPX => "ipx",
180 EtherProto::IPV6 => "ipv6",
181 EtherProto::PAUSE => "pause",
182 EtherProto::SLOW => "slow",
183 EtherProto::WCCP => "wccp",
184 EtherProto::MPLS_UC => "mpls_uc",
185 EtherProto::MPLS_MC => "mpls_mc",
186 EtherProto::ATMMPOA => "atmmpoa",
187 EtherProto::PPP_DISC => "ppp_disc",
188 EtherProto::PPP_SES => "ppp_ses",
189 EtherProto::LINK_CTL => "link_ctl",
190 EtherProto::ATMFATE => "atmfate",
191 EtherProto::PAE => "pae",
192 EtherProto::AOE => "aoe",
193 EtherProto::VLAN_8021AD => "vlan_8021ad",
194 EtherProto::IEEE_802_EX1 => "ieee_802_ex1",
195 EtherProto::TIPC => "tipc",
196 EtherProto::VLAN_8021AH => "vlan_8021ah",
197 EtherProto::MVRP => "mvrp",
198 EtherProto::IEEE_1588 => "ieee_1588",
199 EtherProto::PRP => "prp",
200 EtherProto::FCOE => "fcoe",
201 EtherProto::TDLS => "tdls",
202 EtherProto::FIP => "fip",
203 EtherProto::IEEE_80221 => "ieee_80221",
204 EtherProto::LOOPBACK => "loopback",
205 EtherProto::QINQ1 => "qinq1",
206 EtherProto::QINQ2 => "qinq2",
207 EtherProto::QINQ3 => "qinq3",
208 EtherProto::EDSA => "edsa",
209 EtherProto::AF_IUCV => "af_iucv",
210 EtherProto::IEEE_802_3_MIN => "ieee_802_3_min",
211 EtherProto::IEEE_802_3 => "ieee_802_3",
213 EtherProto::AX25 => "ax25",
214 EtherProto::ALL => "all",
215 EtherProto::IEEE_802_2 => "ieee_802_2",
216 EtherProto::SNAP => "snap",
217 EtherProto::DDCMP => "ddcmp",
218 EtherProto::WAN_PPP => "wan_ppp",
219 EtherProto::PPP_MP => "ppp_mp",
220 EtherProto::LOCALTALK => "localtalk",
221 EtherProto::CAN => "can",
222 EtherProto::CANFD => "canfd",
223 EtherProto::PPPTALK => "ppptalk",
224 EtherProto::TR_802_2 => "tr_802_2",
225 EtherProto::MOBITEX => "mobitex",
226 EtherProto::CONTROL => "control",
227 EtherProto::IRDA => "irda",
228 EtherProto::ECONET => "econet",
229 EtherProto::HDLC => "hdlc",
230 EtherProto::ARCNET => "arcnet",
231 EtherProto::DSA => "dsa",
232 EtherProto::TRAILER => "trailer",
233 EtherProto::PHONET => "phonet",
234 EtherProto::IEEE802154 => "ieee802154",
235 EtherProto::CAIF => "caif",
236 _ => return write!(f, "0x{:04x}", self.0.get()),
237 };
238 write!(f, "{}", name)
239 }
240}
241
242impl From<u16> for EtherProto {
243 fn from(value: u16) -> Self {
244 EtherProto(U16::new(value))
245 }
246}
247
248impl From<EtherProto> for u16 {
249 fn from(proto: EtherProto) -> Self {
250 proto.0.get()
251 }
252}
253
254#[derive(
262 Debug,
263 Clone,
264 Copy,
265 PartialEq,
266 Eq,
267 Hash,
268 FromBytes,
269 IntoBytes,
270 Immutable,
271 KnownLayout,
272 Serialize,
273 Deserialize,
274)]
275#[repr(transparent)]
276pub struct IpProto(pub u8);
277
278impl Default for IpProto {
279 fn default() -> Self {
280 IpProto::ANY
281 }
282}
283
284impl IpProto {
285 pub fn is_valid(&self) -> bool {
300 to_string_literal(*self).is_some()
301 }
302
303 pub const IPV6_HOPOPT: IpProto = IpProto(0); pub const ICMP: IpProto = IpProto(1); pub const IGMP: IpProto = IpProto(2); pub const GGP: IpProto = IpProto(3); pub const IP_ENCAP: IpProto = IpProto(4); pub const ST: IpProto = IpProto(5); pub const TCP: IpProto = IpProto(6); pub const CBT: IpProto = IpProto(7); pub const EGP: IpProto = IpProto(8); pub const IGP: IpProto = IpProto(9); pub const BBN_RCC: IpProto = IpProto(10); pub const NVP: IpProto = IpProto(11); pub const PUP: IpProto = IpProto(12); pub const ARGUS: IpProto = IpProto(13); pub const EMCON: IpProto = IpProto(14); pub const XNET: IpProto = IpProto(15); pub const CHAOS: IpProto = IpProto(16); pub const UDP: IpProto = IpProto(17); pub const MUX: IpProto = IpProto(18); pub const DCN_MEAS: IpProto = IpProto(19); pub const HMP: IpProto = IpProto(20); pub const PRM: IpProto = IpProto(21); pub const XNS_IDP: IpProto = IpProto(22); pub const TRUNK1: IpProto = IpProto(23); pub const TRUNK2: IpProto = IpProto(24); pub const LEAF1: IpProto = IpProto(25); pub const LEAF2: IpProto = IpProto(26); pub const RDP: IpProto = IpProto(27); pub const IRTP: IpProto = IpProto(28); pub const ISO_TP4: IpProto = IpProto(29); pub const NETBLT: IpProto = IpProto(30); pub const MFE_NSP: IpProto = IpProto(31); pub const MERIT_INP: IpProto = IpProto(32); pub const DCCP: IpProto = IpProto(33); pub const _3PC: IpProto = IpProto(34); pub const IDPR: IpProto = IpProto(35); pub const XTP: IpProto = IpProto(36); pub const DDP: IpProto = IpProto(37); pub const IDPR_CMTP: IpProto = IpProto(38); pub const TP_PP: IpProto = IpProto(39); pub const IL: IpProto = IpProto(40); pub const IPV6: IpProto = IpProto(41); pub const SDRP: IpProto = IpProto(42); pub const IPV6_ROUTE: IpProto = IpProto(43); pub const IPV6_FRAG: IpProto = IpProto(44); pub const IDRP: IpProto = IpProto(45); pub const RSVP: IpProto = IpProto(46); pub const GRE: IpProto = IpProto(47); pub const BNA: IpProto = IpProto(49); pub const ESP: IpProto = IpProto(50); pub const AH: IpProto = IpProto(51); pub const I_NLSP: IpProto = IpProto(52); pub const SWIPE: IpProto = IpProto(53); pub const NARP: IpProto = IpProto(54); pub const MOBILE: IpProto = IpProto(55); pub const TLSP: IpProto = IpProto(56); pub const SKIP: IpProto = IpProto(57); pub const ICMP6: IpProto = IpProto(58); pub const IPV6_ICMP: IpProto = IpProto(58); pub const IPV6_NONXT: IpProto = IpProto(59); pub const IPV6_OPTS: IpProto = IpProto(60); pub const CFTP: IpProto = IpProto(62); pub const SAT_EXPAK: IpProto = IpProto(64); pub const KRYPTOLAN: IpProto = IpProto(65); pub const RVD: IpProto = IpProto(66); pub const IPPC: IpProto = IpProto(67); pub const SAT_MON: IpProto = IpProto(69); pub const VISA: IpProto = IpProto(70); pub const IPCU: IpProto = IpProto(71); pub const CPNX: IpProto = IpProto(72); pub const CPHB: IpProto = IpProto(73); pub const WSN: IpProto = IpProto(74); pub const PVP: IpProto = IpProto(75); pub const BR_SAT_MON: IpProto = IpProto(76); pub const SUN_ND: IpProto = IpProto(77); pub const WB_MON: IpProto = IpProto(78); pub const WB_EXPAK: IpProto = IpProto(79); pub const ISO_IP: IpProto = IpProto(80); pub const VMTP: IpProto = IpProto(81); pub const SECURE_VMTP: IpProto = IpProto(82); pub const VINES: IpProto = IpProto(83); pub const IPTM: IpProto = IpProto(84); pub const NSFNET_IGP: IpProto = IpProto(85); pub const DGP: IpProto = IpProto(86); pub const TCF: IpProto = IpProto(87); pub const EIGRP: IpProto = IpProto(88); pub const OSPF: IpProto = IpProto(89); pub const SPRITE_RPC: IpProto = IpProto(90); pub const LARP: IpProto = IpProto(91); pub const MTP: IpProto = IpProto(92); pub const AX_25: IpProto = IpProto(93); pub const OS: IpProto = IpProto(94); pub const MICP: IpProto = IpProto(95); pub const SCC_SP: IpProto = IpProto(96); pub const ETHERIP: IpProto = IpProto(97); pub const ENCAP: IpProto = IpProto(98); pub const GMTP: IpProto = IpProto(100); pub const IFMP: IpProto = IpProto(101); pub const PNNI: IpProto = IpProto(102); pub const PIM: IpProto = IpProto(103); pub const ARIS: IpProto = IpProto(104); pub const SCPS: IpProto = IpProto(105); pub const QNX: IpProto = IpProto(106); pub const AN: IpProto = IpProto(107); pub const IPCOMP: IpProto = IpProto(108); pub const SNP: IpProto = IpProto(109); pub const COMPAQ_PEER: IpProto = IpProto(110); pub const IPX_IN_IP: IpProto = IpProto(111); pub const VRRP: IpProto = IpProto(112); pub const PGM: IpProto = IpProto(113); pub const L2TP: IpProto = IpProto(115); pub const DDX: IpProto = IpProto(116); pub const IATP: IpProto = IpProto(117); pub const STP: IpProto = IpProto(118); pub const SRP: IpProto = IpProto(119); pub const UTI: IpProto = IpProto(120); pub const SMP: IpProto = IpProto(121); pub const SM: IpProto = IpProto(122); pub const PTP: IpProto = IpProto(123); pub const IS_IS: IpProto = IpProto(124); pub const FIRE: IpProto = IpProto(125); pub const CRTP: IpProto = IpProto(126); pub const CRUDP: IpProto = IpProto(127); pub const SSCOPMCE: IpProto = IpProto(128); pub const IPLT: IpProto = IpProto(129); pub const SPS: IpProto = IpProto(130); pub const PIPE: IpProto = IpProto(131); pub const SCTP: IpProto = IpProto(132); pub const FC: IpProto = IpProto(133); pub const RSVP_E2E: IpProto = IpProto(134); pub const IPV6_MOBILITY: IpProto = IpProto(135); pub const UDPLITE: IpProto = IpProto(136); pub const MPLS_IN_IP: IpProto = IpProto(137); pub const MANET: IpProto = IpProto(138); pub const HIP: IpProto = IpProto(139); pub const SHIM6: IpProto = IpProto(140); pub const WESP: IpProto = IpProto(141); pub const ROHC: IpProto = IpProto(142); pub const ANY: IpProto = IpProto(255); }
443
444fn to_string_literal(proto: IpProto) -> Option<&'static str> {
446 let name = match proto {
447 IpProto::IPV6_HOPOPT => "ipv6-hopopt",
448 IpProto::ICMP => "icmp",
449 IpProto::IGMP => "igmp",
450 IpProto::GGP => "ggp",
451 IpProto::IP_ENCAP => "ip-encap",
452 IpProto::ST => "st",
453 IpProto::TCP => "tcp",
454 IpProto::CBT => "cbt",
455 IpProto::EGP => "egp",
456 IpProto::IGP => "igp",
457 IpProto::BBN_RCC => "bbn-rcc",
458 IpProto::NVP => "nvp",
459 IpProto::PUP => "pup",
460 IpProto::ARGUS => "argus",
461 IpProto::EMCON => "emcon",
462 IpProto::XNET => "xnet",
463 IpProto::CHAOS => "chaos",
464 IpProto::UDP => "udp",
465 IpProto::MUX => "mux",
466 IpProto::DCN_MEAS => "dcn-meas",
467 IpProto::HMP => "hmp",
468 IpProto::PRM => "prm",
469 IpProto::XNS_IDP => "xns-idp",
470 IpProto::TRUNK1 => "trunk1",
471 IpProto::TRUNK2 => "trunk2",
472 IpProto::LEAF1 => "leaf1",
473 IpProto::LEAF2 => "leaf2",
474 IpProto::RDP => "rdp",
475 IpProto::IRTP => "irtp",
476 IpProto::ISO_TP4 => "iso-tp4",
477 IpProto::NETBLT => "netblt",
478 IpProto::MFE_NSP => "mfe-nsp",
479 IpProto::MERIT_INP => "merit-inp",
480 IpProto::DCCP => "dccp",
481 IpProto::_3PC => "3pc",
482 IpProto::IDPR => "idpr",
483 IpProto::XTP => "xtp",
484 IpProto::DDP => "ddp",
485 IpProto::IDPR_CMTP => "idpr-cmtp",
486 IpProto::TP_PP => "tp-pp",
487 IpProto::IL => "il",
488 IpProto::IPV6 => "ipv6",
489 IpProto::SDRP => "sdrp",
490 IpProto::IPV6_ROUTE => "ipv6-route",
491 IpProto::IPV6_FRAG => "ipv6-frag",
492 IpProto::IDRP => "idrp",
493 IpProto::RSVP => "rsvp",
494 IpProto::GRE => "gre",
495 IpProto::BNA => "bna",
496 IpProto::ESP => "esp",
497 IpProto::AH => "ah",
498 IpProto::I_NLSP => "i-nlsp",
499 IpProto::SWIPE => "swipe",
500 IpProto::NARP => "narp",
501 IpProto::MOBILE => "mobile",
502 IpProto::TLSP => "tlsp",
503 IpProto::SKIP => "skip",
504 IpProto::IPV6_ICMP => "icmp6",
505 IpProto::IPV6_NONXT => "ipv6-nonxt",
506 IpProto::IPV6_OPTS => "ipv6-opts",
507 IpProto::CFTP => "cftp",
508 IpProto::SAT_EXPAK => "sat-expak",
509 IpProto::KRYPTOLAN => "kryptolan",
510 IpProto::RVD => "rvd",
511 IpProto::IPPC => "ippc",
512 IpProto::SAT_MON => "sat-mon",
513 IpProto::VISA => "visa",
514 IpProto::IPCU => "ipcu",
515 IpProto::CPNX => "cpnx",
516 IpProto::CPHB => "cphb",
517 IpProto::WSN => "wsn",
518 IpProto::PVP => "pvp",
519 IpProto::BR_SAT_MON => "br-sat-mon",
520 IpProto::SUN_ND => "sun-nd",
521 IpProto::WB_MON => "wb-mon",
522 IpProto::WB_EXPAK => "wb-expak",
523 IpProto::ISO_IP => "iso-ip",
524 IpProto::VMTP => "vmtp",
525 IpProto::SECURE_VMTP => "secure-vmtp",
526 IpProto::VINES => "vines",
527 IpProto::IPTM => "iptm", IpProto::NSFNET_IGP => "nsfnet-igp",
529 IpProto::DGP => "dgp",
530 IpProto::TCF => "tcf",
531 IpProto::EIGRP => "eigrp",
532 IpProto::OSPF => "ospf",
533 IpProto::SPRITE_RPC => "sprite-rpc",
534 IpProto::LARP => "larp",
535 IpProto::MTP => "mtp",
536 IpProto::AX_25 => "ax-25",
537 IpProto::OS => "os",
538 IpProto::MICP => "micp",
539 IpProto::SCC_SP => "scc-sp",
540 IpProto::ETHERIP => "etherip",
541 IpProto::ENCAP => "encap",
542 IpProto::GMTP => "gmtp",
543 IpProto::IFMP => "ifmp",
544 IpProto::PNNI => "pnni",
545 IpProto::PIM => "pim",
546 IpProto::ARIS => "aris",
547 IpProto::SCPS => "scps",
548 IpProto::QNX => "qnx",
549 IpProto::AN => "an",
550 IpProto::IPCOMP => "ipcomp",
551 IpProto::SNP => "snp",
552 IpProto::COMPAQ_PEER => "compaq-peer",
553 IpProto::IPX_IN_IP => "ipx-in-ip",
554 IpProto::VRRP => "vrrp",
555 IpProto::PGM => "pgm",
556 IpProto::L2TP => "l2tp",
557 IpProto::DDX => "ddx",
558 IpProto::IATP => "iatp",
559 IpProto::STP => "stp",
560 IpProto::SRP => "srp",
561 IpProto::UTI => "uti",
562 IpProto::SMP => "smp",
563 IpProto::SM => "sm",
564 IpProto::PTP => "ptp",
565 IpProto::IS_IS => "is-is",
566 IpProto::FIRE => "fire",
567 IpProto::CRTP => "crtp",
568 IpProto::CRUDP => "crudp",
569 IpProto::SSCOPMCE => "sscopmce",
570 IpProto::IPLT => "iplt",
571 IpProto::SPS => "sps",
572 IpProto::PIPE => "pipe",
573 IpProto::SCTP => "sctp",
574 IpProto::FC => "fc",
575 IpProto::RSVP_E2E => "rsvp-e2e",
576 IpProto::IPV6_MOBILITY => "ipv6-mobility",
577 IpProto::UDPLITE => "udplite",
578 IpProto::MPLS_IN_IP => "mpls-in-ip",
579 IpProto::MANET => "manet",
580 IpProto::HIP => "hip",
581 IpProto::SHIM6 => "shim6",
582 IpProto::WESP => "wesp",
583 IpProto::ROHC => "rohc",
584 IpProto::ANY => "any",
585 _ => return None,
586 };
587 Some(name)
588}
589
590impl Display for IpProto {
591 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
592 match to_string_literal(*self) {
593 Some(name) => write!(f, "{}", name),
594 None => write!(f, "0x{:04x}", self.0),
595 }
596 }
597}
598
599impl From<u8> for IpProto {
600 fn from(value: u8) -> Self {
601 IpProto(value)
602 }
603}
604
605impl From<IpProto> for u8 {
606 fn from(value: IpProto) -> Self {
607 value.0
608 }
609}
610
611#[cfg(test)]
612mod tests {
613 use super::*;
614
615 #[test]
616 fn test_protocol_constants() {
617 assert_eq!(IpProto::TCP.0, 6);
618 assert_eq!(IpProto::UDP.0, 17);
619 assert_eq!(IpProto::ICMP.0, 1);
620 assert_eq!(IpProto::IPV6.0, 41);
621 assert_eq!(IpProto::IPV6_HOPOPT.0, 0);
622 assert_eq!(IpProto::IPV6_ROUTE.0, 43);
623 assert_eq!(IpProto::IPV6_FRAG.0, 44);
624 assert_eq!(IpProto::IPV6_ICMP.0, 58);
625 assert_eq!(IpProto::IPV6_NONXT.0, 59);
626 assert_eq!(IpProto::IPV6_OPTS.0, 60);
627 assert_eq!(IpProto::ANY.0, 255);
628 }
629
630 #[test]
631 fn test_protocol_display() {
632 assert_eq!(format!("{}", IpProto::TCP), "tcp");
633 assert_eq!(format!("{}", IpProto::UDP), "udp");
634 assert_eq!(format!("{}", IpProto::ICMP), "icmp");
635 assert_eq!(format!("{}", IpProto::IPV6_ICMP), "icmp6");
636 assert_eq!(format!("{}", IpProto::IPV6_ROUTE), "ipv6-route");
637 assert_eq!(format!("{}", IpProto::IPV6_FRAG), "ipv6-frag");
638 assert_eq!(format!("{}", IpProto::IPV6_OPTS), "ipv6-opts");
639 assert_eq!(format!("{}", IpProto::IPV6_NONXT), "ipv6-nonxt");
640 assert_eq!(format!("{}", IpProto::_3PC), "3pc");
641 assert_eq!(format!("{}", IpProto::ANY), "any");
642 }
643
644 #[test]
645 fn test_protocol_display_unknown() {
646 let unknown = IpProto(200);
647 assert_eq!(format!("{}", unknown), "0x00c8");
648 }
649
650 #[test]
651 fn test_protocol_from_u8() {
652 let proto = IpProto::from(6);
653 assert_eq!(proto, IpProto::TCP);
654
655 let proto = IpProto::from(17);
656 assert_eq!(proto, IpProto::UDP);
657 }
658
659 #[test]
660 fn test_protocol_into_u8() {
661 let value: u8 = IpProto::TCP.into();
662 assert_eq!(value, 6);
663
664 let value: u8 = IpProto::UDP.into();
665 assert_eq!(value, 17);
666 }
667
668 #[test]
669 fn test_protocol_equality() {
670 assert_eq!(IpProto::TCP, IpProto::TCP);
671 assert_ne!(IpProto::TCP, IpProto::UDP);
672 assert_eq!(IpProto::from(6), IpProto::TCP);
673 }
674
675 #[test]
676 fn test_protocol_is_valid() {
677 assert!(IpProto::TCP.is_valid());
679 assert!(IpProto::UDP.is_valid());
680 assert!(IpProto::ICMP.is_valid());
681 assert!(IpProto::IPV6.is_valid());
682 assert!(IpProto::IPV6_HOPOPT.is_valid());
683 assert!(IpProto::IPV6_ROUTE.is_valid());
684 assert!(IpProto::IPV6_FRAG.is_valid());
685 assert!(IpProto::ANY.is_valid());
686
687 assert!(!IpProto::from(200).is_valid());
689 assert!(!IpProto::from(150).is_valid());
690 assert!(!IpProto::from(48).is_valid()); assert!(!IpProto::from(61).is_valid()); assert!(!IpProto::from(254).is_valid());
693 }
694}