1use std::fmt;
2
3use byteorder::{ByteOrder, NetworkEndian};
4
5use crate::ipv4::Ipv4Addr;
6
7#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
23pub struct Ipv6Addr(pub [u8; 16]);
24
25impl Ipv6Addr {
26 pub const UNSPECIFIED: Ipv6Addr = Ipv6Addr([0x00; 16]);
27
28 pub const LINK_LOCAL_ALL_NODES: Ipv6Addr = Ipv6Addr([
29 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x01,
31 ]);
32
33 pub const LINK_LOCAL_ALL_ROUTERS: Ipv6Addr = Ipv6Addr([
34 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x02,
36 ]);
37
38 pub const LOOPBACK: Ipv6Addr = Ipv6Addr([
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x01,
41 ]);
42
43 const IPV4_MAPPED_PREFIX: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0];
44
45 pub const fn new(
46 a0: u16,
47 a1: u16,
48 a2: u16,
49 a3: u16,
50 a4: u16,
51 a5: u16,
52 a6: u16,
53 a7: u16,
54 ) -> Ipv6Addr {
55 Ipv6Addr([
56 (a0 >> 8) as u8,
57 a0 as u8,
58 (a1 >> 8) as u8,
59 a1 as u8,
60 (a2 >> 8) as u8,
61 a2 as u8,
62 (a3 >> 8) as u8,
63 a3 as u8,
64 (a4 >> 8) as u8,
65 a4 as u8,
66 (a5 >> 8) as u8,
67 a5 as u8,
68 (a6 >> 8) as u8,
69 a6 as u8,
70 (a7 >> 8) as u8,
71 a7 as u8,
72 ])
73 }
74
75 pub fn from_bytes(data: &[u8]) -> Ipv6Addr {
76 let mut bytes = [0; 16];
77 bytes.copy_from_slice(data);
78 Ipv6Addr(bytes)
79 }
80
81 pub fn from_parts(data: &[u16]) -> Ipv6Addr {
82 assert!(data.len() >= 8);
83 let mut bytes = [0; 16];
84 for (word_idx, chunk) in bytes.chunks_mut(2).enumerate() {
85 NetworkEndian::write_u16(chunk, data[word_idx]);
86 }
87 Ipv6Addr(bytes)
88 }
89
90 pub fn write_parts(&self, data: &mut [u16]) {
91 assert!(data.len() >= 8);
92 for (i, chunk) in self.0.chunks(2).enumerate() {
93 data[i] = NetworkEndian::read_u16(chunk);
94 }
95 }
96
97 pub const fn as_bytes(&self) -> &[u8] {
98 &self.0
99 }
100
101 pub fn is_unicast(&self) -> bool {
102 !(self.is_multicast() || self.is_unspecified())
103 }
104
105 pub const fn is_multicast(&self) -> bool {
106 self.0[0] == 0xff
107 }
108
109 pub fn is_unspecified(&self) -> bool {
110 *self == Self::UNSPECIFIED
111 }
112
113 pub fn is_link_local(&self) -> bool {
114 self.0[0..8] == [0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
115 }
116
117 pub fn is_loopback(&self) -> bool {
118 *self == Self::LOOPBACK
119 }
120
121 pub fn is_ipv4_mapped(&self) -> bool {
122 self.0[..12] == Self::IPV4_MAPPED_PREFIX[..12]
123 }
124
125 pub fn as_ipv4(&self) -> Option<Ipv4Addr> {
126 if self.is_ipv4_mapped() {
127 Some(Ipv4Addr::from_bytes(&self.0[12..]))
128 } else {
129 None
130 }
131 }
132
133 pub fn solicited_node(&self) -> Ipv6Addr {
134 assert!(self.is_unicast());
135 Ipv6Addr([
136 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF,
137 self.0[13], self.0[14], self.0[15],
138 ])
139 }
140}
141
142impl From<::std::net::Ipv6Addr> for Ipv6Addr {
143 fn from(x: ::std::net::Ipv6Addr) -> Ipv6Addr {
144 Ipv6Addr(x.octets())
145 }
146}
147
148impl From<Ipv6Addr> for ::std::net::Ipv6Addr {
149 fn from(x: Ipv6Addr) -> ::std::net::Ipv6Addr {
150 x.into()
151 }
152}
153
154impl From<Ipv4Addr> for Ipv6Addr {
155 fn from(x: Ipv4Addr) -> Ipv6Addr {
156 let mut bytes = Self::IPV4_MAPPED_PREFIX;
157 (&mut bytes[12..16]).copy_from_slice(x.as_bytes());
158 Ipv6Addr(bytes)
159 }
160}
161
162impl fmt::Display for Ipv6Addr {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 if self.is_ipv4_mapped() {
165 return write!(
166 f,
167 "::ffff:{}.{}.{}.{}",
168 self.0[12 + 0],
169 self.0[12 + 1],
170 self.0[12 + 2],
171 self.0[12 + 3]
172 );
173 }
174
175 enum State {
177 Head,
178 HeadBody,
179 Tail,
180 TailBody,
181 }
182 let mut words = [0u16; 8];
183 self.write_parts(&mut words);
184 let mut state = State::Head;
185 for word in words.iter() {
186 state = match (*word, &state) {
187 (0, &State::Head) | (0, &State::HeadBody) => {
190 write!(f, "::")?;
191 State::Tail
192 }
193 (0, &State::Tail) => State::Tail,
196 (_, &State::Head) => {
199 write!(f, "{word:x}")?;
200 State::HeadBody
201 }
202 (_, &State::Tail) => {
203 write!(f, "{word:x}")?;
204 State::TailBody
205 }
206 (_, &State::HeadBody) | (_, &State::TailBody) => {
209 write!(f, ":{word:x}")?;
210 state
211 }
212 }
213 }
214 Ok(())
215 }
216}
217
218mod header;
219pub use header::{Ipv6Header, IPV6_HEADER_LEN};
220
221mod packet;
222pub use packet::Ipv6Packet;
223
224pub mod extentions;