stackforge_core/layer/ipv6/
builder.rs1use std::net::Ipv6Addr;
22
23use super::IPV6_HEADER_LEN;
24
25#[derive(Debug, Clone)]
27pub struct Ipv6Builder {
28 traffic_class: u8,
30 flow_label: u32,
32 next_header: u8,
34 hop_limit: u8,
36 src: Ipv6Addr,
38 dst: Ipv6Addr,
40 payload: Vec<u8>,
42 auto_length: bool,
44 payload_len_override: Option<u16>,
46}
47
48impl Default for Ipv6Builder {
49 fn default() -> Self {
50 Self {
51 traffic_class: 0,
52 flow_label: 0,
53 next_header: 59, hop_limit: 64,
55 src: Ipv6Addr::UNSPECIFIED,
56 dst: Ipv6Addr::UNSPECIFIED,
57 payload: Vec::new(),
58 auto_length: true,
59 payload_len_override: None,
60 }
61 }
62}
63
64impl Ipv6Builder {
65 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn src(mut self, src: Ipv6Addr) -> Self {
74 self.src = src;
75 self
76 }
77
78 pub fn dst(mut self, dst: Ipv6Addr) -> Self {
80 self.dst = dst;
81 self
82 }
83
84 pub fn hop_limit(mut self, hlim: u8) -> Self {
86 self.hop_limit = hlim;
87 self
88 }
89
90 pub fn traffic_class(mut self, tc: u8) -> Self {
92 self.traffic_class = tc;
93 self
94 }
95
96 pub fn flow_label(mut self, fl: u32) -> Self {
98 self.flow_label = fl & 0x000F_FFFF;
99 self
100 }
101
102 pub fn next_header(mut self, nh: u8) -> Self {
104 self.next_header = nh;
105 self
106 }
107
108 pub fn payload<T: Into<Vec<u8>>>(mut self, data: T) -> Self {
110 self.payload = data.into();
111 self
112 }
113
114 pub fn auto_length(mut self, auto: bool) -> Self {
116 self.auto_length = auto;
117 self
118 }
119
120 pub fn payload_len(mut self, len: u16) -> Self {
124 self.payload_len_override = Some(len);
125 self.auto_length = false;
126 self
127 }
128
129 pub fn header_size(&self) -> usize {
133 IPV6_HEADER_LEN
134 }
135
136 pub fn packet_size(&self) -> usize {
138 IPV6_HEADER_LEN + self.payload.len()
139 }
140
141 pub fn build(&self) -> Vec<u8> {
156 let total = self.packet_size();
157 let mut buf = vec![0u8; total];
158
159 buf[0] = 0x60 | ((self.traffic_class >> 4) & 0x0F);
161
162 buf[1] = ((self.traffic_class & 0x0F) << 4) | (((self.flow_label >> 16) & 0x0F) as u8);
164
165 buf[2] = ((self.flow_label >> 8) & 0xFF) as u8;
167 buf[3] = (self.flow_label & 0xFF) as u8;
168
169 let plen: u16 = if self.auto_length {
171 self.payload.len() as u16
172 } else {
173 self.payload_len_override
174 .unwrap_or(self.payload.len() as u16)
175 };
176 buf[4] = (plen >> 8) as u8;
177 buf[5] = (plen & 0xFF) as u8;
178
179 buf[6] = self.next_header;
181
182 buf[7] = self.hop_limit;
184
185 buf[8..24].copy_from_slice(&self.src.octets());
187
188 buf[24..40].copy_from_slice(&self.dst.octets());
190
191 if !self.payload.is_empty() {
193 buf[40..40 + self.payload.len()].copy_from_slice(&self.payload);
194 }
195
196 buf
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203
204 #[test]
205 fn test_ipv6_builder_basic() {
206 let src = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
207 let dst = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 2);
208
209 let bytes = Ipv6Builder::new()
210 .src(src)
211 .dst(dst)
212 .hop_limit(64)
213 .next_header(58)
214 .build();
215
216 assert_eq!(bytes.len(), 40);
217 assert_eq!((bytes[0] >> 4) & 0x0F, 6);
219 assert_eq!(bytes[6], 58);
221 assert_eq!(bytes[7], 64);
223 let mut src_bytes = [0u8; 16];
225 src_bytes.copy_from_slice(&bytes[8..24]);
226 assert_eq!(Ipv6Addr::from(src_bytes), src);
227 let mut dst_bytes = [0u8; 16];
229 dst_bytes.copy_from_slice(&bytes[24..40]);
230 assert_eq!(Ipv6Addr::from(dst_bytes), dst);
231 }
232
233 #[test]
234 fn test_ipv6_builder_with_payload() {
235 let payload = b"hello world";
236 let bytes = Ipv6Builder::new()
237 .src(Ipv6Addr::LOCALHOST)
238 .dst(Ipv6Addr::LOCALHOST)
239 .next_header(59)
240 .payload(payload.as_ref())
241 .build();
242
243 assert_eq!(bytes.len(), 40 + payload.len());
244 let plen = u16::from_be_bytes([bytes[4], bytes[5]]);
246 assert_eq!(plen as usize, payload.len());
247 assert_eq!(&bytes[40..], payload.as_ref());
249 }
250
251 #[test]
252 fn test_ipv6_traffic_class() {
253 let bytes = Ipv6Builder::new().traffic_class(0xAB).build();
254
255 assert_eq!(bytes[0], 0x6A);
257 assert_eq!(bytes[1] & 0xF0, 0xB0);
259 let tc = ((bytes[0] & 0x0F) << 4) | ((bytes[1] >> 4) & 0x0F);
261 assert_eq!(tc, 0xAB);
262 }
263
264 #[test]
265 fn test_ipv6_flow_label() {
266 let bytes = Ipv6Builder::new().flow_label(0x12345).build();
267
268 assert_eq!(bytes[1] & 0x0F, 0x01);
270 assert_eq!(bytes[2], 0x23);
272 assert_eq!(bytes[3], 0x45);
274 let fl = ((bytes[1] as u32 & 0x0F) << 16) | ((bytes[2] as u32) << 8) | (bytes[3] as u32);
276 assert_eq!(fl, 0x12345);
277 }
278
279 #[test]
280 fn test_ipv6_manual_payload_len() {
281 let bytes = Ipv6Builder::new()
282 .payload(vec![0u8; 20])
283 .payload_len(100) .build();
285
286 let plen = u16::from_be_bytes([bytes[4], bytes[5]]);
287 assert_eq!(plen, 100);
288 }
289
290 #[test]
291 fn test_ipv6_header_size() {
292 let builder = Ipv6Builder::new();
293 assert_eq!(builder.header_size(), 40);
294 }
295}