packet_strata/packet/
protocol.rs

1//! IP Protocol Numbers
2//!
3//! This module defines IP protocol numbers as specified in RFC 1700 and maintained
4//! by IANA. These protocol numbers are used in IPv4 headers (Protocol field) and
5//! IPv6 headers (Next Header field).
6//!
7//! # Examples
8//!
9//! ```
10//! use packet_strata::packet::protocol::IpProto;
11//!
12//! // Common protocols
13//! let tcp = IpProto::TCP;
14//! let udp = IpProto::UDP;
15//! let icmp = IpProto::ICMP;
16//!
17//! // IPv6 extension headers
18//! let hop_by_hop = IpProto::IPV6_HOPOPT;
19//! let routing = IpProto::IPV6_ROUTE;
20//! let fragment = IpProto::IPV6_FRAG;
21//!
22//! // Display protocol names
23//! assert_eq!(format!("{}", tcp), "tcp");
24//! assert_eq!(format!("{}", udp), "udp");
25//! assert_eq!(format!("{}", IpProto::IPV6_ICMP), "icmp6");
26//!
27//! // Convert from/to u8
28//! let proto = IpProto::from(6);
29//! assert_eq!(proto, IpProto::TCP);
30//! let value: u8 = IpProto::UDP.into();
31//! assert_eq!(value, 17);
32//!
33//! // Check if protocol is valid/known
34//! assert!(IpProto::TCP.is_valid());
35//! assert!(IpProto::UDP.is_valid());
36//! assert!(!IpProto::from(200).is_valid());
37//! ```
38
39use 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    // DIX Ethernet Protocol Types
69    pub const LOOP: EtherProto = EtherProto(U16::new(0x0060)); /* Ethernet Loopback packet */
70    pub const PUP: EtherProto = EtherProto(U16::new(0x0200)); /* Xerox PUP packet */
71    pub const PUPAT: EtherProto = EtherProto(U16::new(0x0201)); /* Xerox PUP Addr Trans packet */
72    pub const IPV4: EtherProto = EtherProto(U16::new(0x0800)); /* Internet Protocol packet (was IP) */
73    pub const X25: EtherProto = EtherProto(U16::new(0x0805)); /* CCITT X.25 */
74    pub const ARP: EtherProto = EtherProto(U16::new(0x0806)); /* Address Resolution packet */
75    pub const BPQ: EtherProto = EtherProto(U16::new(0x08FF)); /* G8BPQ AX.25 Ethernet Packet [NOT AN OFFICIALLY REGISTERED ID] */
76    pub const IEEEPUP: EtherProto = EtherProto(U16::new(0x0a00)); /* Xerox IEEE802.3 PUP packet */
77    pub const IEEEPUPAT: EtherProto = EtherProto(U16::new(0x0a01)); /* Xerox IEEE802.3 PUP Addr Trans packet */
78    pub const BATMAN: EtherProto = EtherProto(U16::new(0x4305)); /* B.A.T.M.A.N.-Advanced packet [NOT AN OFFICIALLY REGISTERED ID] */
79    pub const DEC: EtherProto = EtherProto(U16::new(0x6000)); /* DEC Assigned proto */
80    pub const DNA_DL: EtherProto = EtherProto(U16::new(0x6001)); /* DEC DNA Dump/Load */
81    pub const DNA_RC: EtherProto = EtherProto(U16::new(0x6002)); /* DEC DNA Remote Console */
82    pub const DNA_RT: EtherProto = EtherProto(U16::new(0x6003)); /* DEC DNA Routing */
83    pub const LAT: EtherProto = EtherProto(U16::new(0x6004)); /* DEC LAT */
84    pub const DIAG: EtherProto = EtherProto(U16::new(0x6005)); /* DEC Diagnostics */
85    pub const CUST: EtherProto = EtherProto(U16::new(0x6006)); /* DEC Customer use */
86    pub const SCA: EtherProto = EtherProto(U16::new(0x6007)); /* DEC Systems Comms Arch */
87    pub const TEB: EtherProto = EtherProto(U16::new(0x6558)); /* Transp. Ether Bridging */
88    pub const RARP: EtherProto = EtherProto(U16::new(0x8035)); /* Reverse Addr Res packet */
89    pub const ATALK: EtherProto = EtherProto(U16::new(0x809B)); /* Appletalk DDP */
90    pub const AARP: EtherProto = EtherProto(U16::new(0x80F3)); /* Appletalk AARP */
91    pub const VLAN_8021Q: EtherProto = EtherProto(U16::new(0x8100)); /* 802.1Q VLAN Extended Header (was VLAN_8021Q) */
92    pub const IPX: EtherProto = EtherProto(U16::new(0x8137)); /* IPX over DIX */
93    pub const IPV6: EtherProto = EtherProto(U16::new(0x86DD)); /* IPv6 over bluebook */
94    pub const PAUSE: EtherProto = EtherProto(U16::new(0x8808)); /* IEEE Pause frames. See 802.3 31B */
95    pub const SLOW: EtherProto = EtherProto(U16::new(0x8809)); /* Slow Protocol. See 802.3ad 43B */
96    pub const WCCP: EtherProto = EtherProto(U16::new(0x883E)); /* Web-cache coordination protocol */
97    pub const MPLS_UC: EtherProto = EtherProto(U16::new(0x8847)); /* MPLS Unicast traffic */
98    pub const MPLS_MC: EtherProto = EtherProto(U16::new(0x8848)); /* MPLS Multicast traffic */
99    pub const ATMMPOA: EtherProto = EtherProto(U16::new(0x884c)); /* MultiProtocol Over ATM */
100    pub const PPP_DISC: EtherProto = EtherProto(U16::new(0x8863)); /* PPPoE discovery messages */
101    pub const PPP_SES: EtherProto = EtherProto(U16::new(0x8864)); /* PPPoE session messages */
102    pub const LINK_CTL: EtherProto = EtherProto(U16::new(0x886c)); /* HPNA, wlan link local tunnel */
103    pub const ATMFATE: EtherProto = EtherProto(U16::new(0x8884)); /* Frame-based ATM Transport over Ethernet */
104    pub const PAE: EtherProto = EtherProto(U16::new(0x888E)); /* Port Access Entity (IEEE 802.1X) */
105    pub const AOE: EtherProto = EtherProto(U16::new(0x88A2)); /* ATA over Ethernet */
106    pub const VLAN_8021AD: EtherProto = EtherProto(U16::new(0x88A8)); /* 802.1ad Service VLAN */
107    pub const IEEE_802_EX1: EtherProto = EtherProto(U16::new(0x88B5)); /* 802.1 Local Experimental 1. */
108    pub const TIPC: EtherProto = EtherProto(U16::new(0x88CA)); /* TIPC */
109    pub const VLAN_8021AH: EtherProto = EtherProto(U16::new(0x88E7)); /* 802.1ah Backbone Service Tag */
110    pub const MVRP: EtherProto = EtherProto(U16::new(0x88F5)); /* 802.1Q MVRP */
111    pub const IEEE_1588: EtherProto = EtherProto(U16::new(0x88F7)); /* IEEE 1588 Timesync */
112    pub const PRP: EtherProto = EtherProto(U16::new(0x88FB)); /* IEC 62439-3 PRP/HSRv0 */
113    pub const FCOE: EtherProto = EtherProto(U16::new(0x8906)); /* Fibre Channel over Ethernet */
114    pub const TDLS: EtherProto = EtherProto(U16::new(0x890D)); /* TDLS */
115    pub const FIP: EtherProto = EtherProto(U16::new(0x8914)); /* FCoE Initialization Protocol */
116    pub const IEEE_80221: EtherProto = EtherProto(U16::new(0x8917)); /* IEEE 802.21 Media Independent Handover Protocol */
117    pub const LOOPBACK: EtherProto = EtherProto(U16::new(0x9000)); /* Ethernet loopback packet, per IEEE 802.3 */
118    pub const QINQ1: EtherProto = EtherProto(U16::new(0x9100)); /* deprecated QinQ VLAN [NOT AN OFFICIALLY REGISTERED ID] */
119    pub const QINQ2: EtherProto = EtherProto(U16::new(0x9200)); /* deprecated QinQ VLAN [NOT AN OFFICIALLY REGISTERED ID] */
120    pub const QINQ3: EtherProto = EtherProto(U16::new(0x9300)); /* deprecated QinQ VLAN [NOT AN OFFICIALLY REGISTERED ID] */
121    pub const EDSA: EtherProto = EtherProto(U16::new(0xDADA)); /* Ethertype DSA [NOT AN OFFICIALLY REGISTERED ID] */
122    pub const AF_IUCV: EtherProto = EtherProto(U16::new(0xFBFB)); /* IBM af_iucv [NOT AN OFFICIALLY REGISTERED ID] */
123    pub const IEEE_802_3_MIN: EtherProto = EtherProto(U16::new(0x0600)); /* If the value in the ethernet type is less than this value then the frame is Ethernet II. Else it is 802.3 */
124
125    // Non DIX types. Won't clash for 1500 types.
126    pub const IEEE_802_3: EtherProto = EtherProto(U16::new(0x0001)); /* Dummy type for 802.3 frames */
127    pub const AX25: EtherProto = EtherProto(U16::new(0x0002)); /* Dummy protocol id for AX.25 */
128    pub const ALL: EtherProto = EtherProto(U16::new(0x0003)); /* Every packet (be careful!!!) */
129    pub const IEEE_802_2: EtherProto = EtherProto(U16::new(0x0004)); /* 802.2 frames */
130    pub const SNAP: EtherProto = EtherProto(U16::new(0x0005)); /* Internal only */
131    pub const DDCMP: EtherProto = EtherProto(U16::new(0x0006)); /* DEC DDCMP: Internal only */
132    pub const WAN_PPP: EtherProto = EtherProto(U16::new(0x0007)); /* Dummy type for WAN PPP frames */
133    pub const PPP_MP: EtherProto = EtherProto(U16::new(0x0008)); /* Dummy type for PPP MP frames */
134    pub const LOCALTALK: EtherProto = EtherProto(U16::new(0x0009)); /* Localtalk pseudo type */
135    pub const CAN: EtherProto = EtherProto(U16::new(0x000C)); /* CAN: Controller Area Network */
136    pub const CANFD: EtherProto = EtherProto(U16::new(0x000D)); /* CANFD: CAN flexible data rate */
137    pub const PPPTALK: EtherProto = EtherProto(U16::new(0x0010)); /* Dummy type for Atalk over PPP */
138    pub const TR_802_2: EtherProto = EtherProto(U16::new(0x0011)); /* 802.2 frames */
139    pub const MOBITEX: EtherProto = EtherProto(U16::new(0x0015)); /* Mobitex (kaz@cafe.net) */
140    pub const CONTROL: EtherProto = EtherProto(U16::new(0x0016)); /* Card specific control frames */
141    pub const IRDA: EtherProto = EtherProto(U16::new(0x0017)); /* Linux-IrDA */
142    pub const ECONET: EtherProto = EtherProto(U16::new(0x0018)); /* Acorn Econet */
143    pub const HDLC: EtherProto = EtherProto(U16::new(0x0019)); /* HDLC frames */
144    pub const ARCNET: EtherProto = EtherProto(U16::new(0x001A)); /* 1A for ArcNet :-) */
145    pub const DSA: EtherProto = EtherProto(U16::new(0x001B)); /* Distributed Switch Arch. */
146    pub const TRAILER: EtherProto = EtherProto(U16::new(0x001C)); /* Trailer switch tagging */
147    pub const PHONET: EtherProto = EtherProto(U16::new(0x00F5)); /* Nokia Phonet frames */
148    pub const IEEE802154: EtherProto = EtherProto(U16::new(0x00F6)); /* IEEE802.15.4 frame */
149    pub const CAIF: EtherProto = EtherProto(U16::new(0x00F7)); /* ST-Ericsson CAIF protocol */
150}
151
152impl Display for EtherProto {
153    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
154        let name = match *self {
155            // DIX Ethernet Protocol Types
156            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            // Non DIX types
212            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/// IP Protocol Number
255///
256/// A newtype wrapper around a `u8` representing an IP protocol number.
257/// Used in IPv4 headers (Protocol field) and IPv6 headers (Next Header field).
258///
259/// This type provides named constants for well-known protocols and implements
260/// `Display` to show human-readable protocol names.
261#[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    /// Check if this protocol number is a known/valid protocol
286    ///
287    /// Returns `true` if this protocol number corresponds to a known protocol,
288    /// `false` otherwise.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// use packet_strata::packet::protocol::IpProto;
294    ///
295    /// assert!(IpProto::TCP.is_valid());
296    /// assert!(IpProto::UDP.is_valid());
297    /// assert!(!IpProto::from(200).is_valid());
298    /// ```
299    pub fn is_valid(&self) -> bool {
300        to_string_literal(*self).is_some()
301    }
302
303    pub const IPV6_HOPOPT: IpProto = IpProto(0); // IPv6 Hop-by-hop options
304    pub const ICMP: IpProto = IpProto(1); // Internet Control Message Protocol
305    pub const IGMP: IpProto = IpProto(2); // Internet Group Management
306    pub const GGP: IpProto = IpProto(3); // gateway-gateway protocol
307    pub const IP_ENCAP: IpProto = IpProto(4); // IP encapsulated in IP (officially ``IP'')
308    pub const ST: IpProto = IpProto(5); // ST datagram mode
309    pub const TCP: IpProto = IpProto(6); // transmission control protocol
310    pub const CBT: IpProto = IpProto(7); // core-based trees
311    pub const EGP: IpProto = IpProto(8); // exterior gateway protocol
312    pub const IGP: IpProto = IpProto(9); // any private interior gateway (Cisco)
313    pub const BBN_RCC: IpProto = IpProto(10); // bbn-rcc-mon
314    pub const NVP: IpProto = IpProto(11); // nvp
315    pub const PUP: IpProto = IpProto(12); // PARC universal packet protocol
316    pub const ARGUS: IpProto = IpProto(13); // argus
317    pub const EMCON: IpProto = IpProto(14); // EMCON
318    pub const XNET: IpProto = IpProto(15); // X-net debugger
319    pub const CHAOS: IpProto = IpProto(16); // chaos
320    pub const UDP: IpProto = IpProto(17); // user datagram protocol
321    pub const MUX: IpProto = IpProto(18); // multiplexing
322    pub const DCN_MEAS: IpProto = IpProto(19); // DCN measurement subsystems
323    pub const HMP: IpProto = IpProto(20); // host monitoring protocol
324    pub const PRM: IpProto = IpProto(21); // packet radio measurement
325    pub const XNS_IDP: IpProto = IpProto(22); // Xerox NS IDP
326    pub const TRUNK1: IpProto = IpProto(23); // Trunk-1
327    pub const TRUNK2: IpProto = IpProto(24); // Trunk-2
328    pub const LEAF1: IpProto = IpProto(25); // Leaf-1
329    pub const LEAF2: IpProto = IpProto(26); // Leaf-2
330    pub const RDP: IpProto = IpProto(27); // "reliable datagram" protocol
331    pub const IRTP: IpProto = IpProto(28); // IRTP
332    pub const ISO_TP4: IpProto = IpProto(29); // ISO Transport Protocol class 4 [RFC905]
333    pub const NETBLT: IpProto = IpProto(30); // bulk data transfer protocol
334    pub const MFE_NSP: IpProto = IpProto(31); // MFE network services protocol
335    pub const MERIT_INP: IpProto = IpProto(32); // Merit inter nodal protocol
336    pub const DCCP: IpProto = IpProto(33); // Datagram Congestion Control Prot. [RFC4340]
337    pub const _3PC: IpProto = IpProto(34); // Third party connect protocol
338    pub const IDPR: IpProto = IpProto(35); // Inter domain policy routing protocol
339    pub const XTP: IpProto = IpProto(36); // Xpress Transfer Protocol
340    pub const DDP: IpProto = IpProto(37); // Datagram Delivery Protocol
341    pub const IDPR_CMTP: IpProto = IpProto(38); // IDPR Control Message Transport
342    pub const TP_PP: IpProto = IpProto(39); // TP++ transport protocol
343    pub const IL: IpProto = IpProto(40); // IL transport protocol
344    pub const IPV6: IpProto = IpProto(41); // Internet Protocol, version 6
345    pub const SDRP: IpProto = IpProto(42); // Source demand routing protocol
346    pub const IPV6_ROUTE: IpProto = IpProto(43); // Routing Header for IPv6
347    pub const IPV6_FRAG: IpProto = IpProto(44); // Fragment Header for IPv6
348    pub const IDRP: IpProto = IpProto(45); // Inter-Domain Routing Protocol
349    pub const RSVP: IpProto = IpProto(46); // Reservation Protocol
350    pub const GRE: IpProto = IpProto(47); // General Routing Encapsulation
351    pub const BNA: IpProto = IpProto(49); // Burroughs Network Architecture
352    pub const ESP: IpProto = IpProto(50); // Encapsulating Security Payload RFC 4303
353    pub const AH: IpProto = IpProto(51); // Authentication Header RFC 4302
354    pub const I_NLSP: IpProto = IpProto(52); // Integrated Net Layer Security Protocol TUBA
355    pub const SWIPE: IpProto = IpProto(53); // SwIPe IP with Encryption
356    pub const NARP: IpProto = IpProto(54); // NBMA Address Resolution Protocol RFC 1735
357    pub const MOBILE: IpProto = IpProto(55); // IP Mobility (Min Encap) RFC 2004
358    pub const TLSP: IpProto = IpProto(56); // Transport Layer Security Protocol (using Kryptonet key management)
359    pub const SKIP: IpProto = IpProto(57); // Simple Key-Management for Internet Protocol RFC 2356
360    pub const ICMP6: IpProto = IpProto(58); // ICMP for IPv6 RFC 4443, RFC 4884 (alias)
361    pub const IPV6_ICMP: IpProto = IpProto(58); // ICMP for IPv6 RFC 4443, RFC 4884
362    pub const IPV6_NONXT: IpProto = IpProto(59); // No Next Header for IPv6 RFC 8200
363    pub const IPV6_OPTS: IpProto = IpProto(60); // Destination Options for IPv6 RFC 8200
364    pub const CFTP: IpProto = IpProto(62); // CFTP
365    pub const SAT_EXPAK: IpProto = IpProto(64); // SATNET and Backroom EXPAK
366    pub const KRYPTOLAN: IpProto = IpProto(65); // Kryptolan
367    pub const RVD: IpProto = IpProto(66); // MIT Remote Virtual Disk Protocol
368    pub const IPPC: IpProto = IpProto(67); // Internet Pluribus Packet Core
369    pub const SAT_MON: IpProto = IpProto(69); // SATNET Monitoring
370    pub const VISA: IpProto = IpProto(70); // VISA Protocol
371    pub const IPCU: IpProto = IpProto(71); // Internet Packet Core Utility
372    pub const CPNX: IpProto = IpProto(72); // Computer Protocol Network Executive
373    pub const CPHB: IpProto = IpProto(73); // Computer Protocol Heart Beat
374    pub const WSN: IpProto = IpProto(74); // Wang Span Network
375    pub const PVP: IpProto = IpProto(75); // Packet Video Protocol
376    pub const BR_SAT_MON: IpProto = IpProto(76); // Backroom SATNET Monitoring
377    pub const SUN_ND: IpProto = IpProto(77); // SUN ND PROTOCOL-Temporary
378    pub const WB_MON: IpProto = IpProto(78); // WIDEBAND Monitoring
379    pub const WB_EXPAK: IpProto = IpProto(79); // WIDEBAND EXPAK
380    pub const ISO_IP: IpProto = IpProto(80); // International Organization for Standardization Internet Protocol
381    pub const VMTP: IpProto = IpProto(81); // Versatile Message Transaction Protocol RFC 1045
382    pub const SECURE_VMTP: IpProto = IpProto(82); // Secure Versatile Message Transaction Protocol RFC 1045
383    pub const VINES: IpProto = IpProto(83); // VINES
384    pub const IPTM: IpProto = IpProto(84); // Internet Protocol Traffic Manager (same as TTP)
385    pub const NSFNET_IGP: IpProto = IpProto(85); // NSFNET-IGP
386    pub const DGP: IpProto = IpProto(86); // Dissimilar Gateway Protocol
387    pub const TCF: IpProto = IpProto(87); // TCF
388    pub const EIGRP: IpProto = IpProto(88); // EIGRP
389    pub const OSPF: IpProto = IpProto(89); // Open Shortest Path First RFC 1583
390    pub const SPRITE_RPC: IpProto = IpProto(90); // Sprite RPC Protocol
391    pub const LARP: IpProto = IpProto(91); // Locus Address Resolution Protocol
392    pub const MTP: IpProto = IpProto(92); // Multicast Transport Protocol
393    pub const AX_25: IpProto = IpProto(93); // AX.25
394    pub const OS: IpProto = IpProto(94); // KA9Q NOS compatible IP over IP tunneling
395    pub const MICP: IpProto = IpProto(95); // Mobile Internetworking Control Protocol
396    pub const SCC_SP: IpProto = IpProto(96); // Semaphore Communications Sec. Pro
397    pub const ETHERIP: IpProto = IpProto(97); // Ethernet-within-IP Encapsulation RFC 3378
398    pub const ENCAP: IpProto = IpProto(98); // Encapsulation Header RFC 1241
399    pub const GMTP: IpProto = IpProto(100); // GMTP
400    pub const IFMP: IpProto = IpProto(101); // Ipsilon Flow Management Protocol
401    pub const PNNI: IpProto = IpProto(102); // PNNI over IP
402    pub const PIM: IpProto = IpProto(103); // Protocol Independent Multicast
403    pub const ARIS: IpProto = IpProto(104); // IBM's ARIS (Aggregate Route IP Switching) Protocol
404    pub const SCPS: IpProto = IpProto(105); // SCPS (Space Communications Protocol Standards) SCPS-TP[2]
405    pub const QNX: IpProto = IpProto(106); // QNX
406    pub const AN: IpProto = IpProto(107); // Active Networks
407    pub const IPCOMP: IpProto = IpProto(108); // IP Payload Compression Protocol RFC 3173
408    pub const SNP: IpProto = IpProto(109); // Sitara Networks Protocol
409    pub const COMPAQ_PEER: IpProto = IpProto(110); // Compaq Peer Protocol
410    pub const IPX_IN_IP: IpProto = IpProto(111); // IPX in IP
411    pub const VRRP: IpProto = IpProto(112); // Virtual Router Redundancy Protocol, Common Address Redundancy Protocol (not IANA assigned) VRRP:RFC 3768
412    pub const PGM: IpProto = IpProto(113); // PGM Reliable Transport Protocol RFC 3208
413    pub const L2TP: IpProto = IpProto(115); // Layer Two Tunneling Protocol Version 3 RFC 3931
414    pub const DDX: IpProto = IpProto(116); // D-II Data Exchange (DDX)
415    pub const IATP: IpProto = IpProto(117); // Interactive Agent Transfer Protocol
416    pub const STP: IpProto = IpProto(118); // Schedule Transfer Protocol
417    pub const SRP: IpProto = IpProto(119); // SpectraLink Radio Protocol
418    pub const UTI: IpProto = IpProto(120); // Universal Transport Interface Protocol
419    pub const SMP: IpProto = IpProto(121); // Simple Message Protocol
420    pub const SM: IpProto = IpProto(122); // Simple Multicast Protocol draft-perlman-simple-multicast-03
421    pub const PTP: IpProto = IpProto(123); // Performance Transparency Protocol
422    pub const IS_IS: IpProto = IpProto(124); // Intermediate System to Intermediate System (IS-IS) Protocol over IPv4 RFC 1142 and RFC 1195
423    pub const FIRE: IpProto = IpProto(125); // Flexible Intra-AS Routing Environment
424    pub const CRTP: IpProto = IpProto(126); // Combat Radio Transport Protocol
425    pub const CRUDP: IpProto = IpProto(127); // Combat Radio User Datagram
426    pub const SSCOPMCE: IpProto = IpProto(128); // Service-Specific Connection-Oriented Protocol in a Multilink and Connectionless Environment ITU-T Q.2111 (1999)
427    pub const IPLT: IpProto = IpProto(129); // IPLT
428    pub const SPS: IpProto = IpProto(130); // Secure Packet Shield
429    pub const PIPE: IpProto = IpProto(131); // Private IP Encapsulation within IP Expired I-D draft-petri-mobileip-pipe-00.txt
430    pub const SCTP: IpProto = IpProto(132); // Stream Control Transmission Protocol RFC 4960
431    pub const FC: IpProto = IpProto(133); // Fibre Channel
432    pub const RSVP_E2E: IpProto = IpProto(134); // Reservation Protocol (RSVP) End-to-End Ignore RFC 3175
433    pub const IPV6_MOBILITY: IpProto = IpProto(135); // Mobility Extension Header for IPv6 RFC 6275
434    pub const UDPLITE: IpProto = IpProto(136); // Lightweight User Datagram Protocol RFC 3828
435    pub const MPLS_IN_IP: IpProto = IpProto(137); // Multiprotocol Label Switching Encapsulated in IP RFC 4023, RFC 5332
436    pub const MANET: IpProto = IpProto(138); // MANET Protocols RFC 5498
437    pub const HIP: IpProto = IpProto(139); // Host Identity Protocol RFC 5201
438    pub const SHIM6: IpProto = IpProto(140); // Site Multihoming by IPv6 Intermediation RFC 5533
439    pub const WESP: IpProto = IpProto(141); // Wrapped Encapsulating Security Payload RFC 5840
440    pub const ROHC: IpProto = IpProto(142); // Robust Header Compression RFC 5856
441    pub const ANY: IpProto = IpProto(255); // Raw/ANY IP packets
442}
443
444/// Returns the string literal name for a known IP protocol, or None for unknown protocols
445fn 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", // same value as TTP
528        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        // Known protocols should be valid
678        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        // Unknown protocols should be invalid
688        assert!(!IpProto::from(200).is_valid());
689        assert!(!IpProto::from(150).is_valid());
690        assert!(!IpProto::from(48).is_valid()); // Gap in protocol numbers
691        assert!(!IpProto::from(61).is_valid()); // Gap in protocol numbers
692        assert!(!IpProto::from(254).is_valid());
693    }
694}