1pub mod flag;
17pub use self::flag::Flags;
18
19pub mod option;
21pub use self::option::Option;
22
23mod packet;
24pub use self::packet::Packet;
25
26mod builder;
27pub use self::builder::Builder;
28
29use crate::ip;
30use crate::ip::Protocol;
31
32pub fn checksum<B: AsRef<[u8]>>(ip: &ip::Packet<B>, buffer: &[u8]) -> u16 {
39 use std::io::Cursor;
40 use byteorder::{WriteBytesExt, ReadBytesExt, BigEndian};
41
42 let mut prefix = [0u8; 40];
43 match *ip {
44 ip::Packet::V4(ref packet) => {
45 prefix[0 .. 4].copy_from_slice(&packet.source().octets());
46 prefix[4 .. 8].copy_from_slice(&packet.destination().octets());
47
48 prefix[9] = Protocol::Tcp.into();
49 Cursor::new(&mut prefix[10 ..])
50 .write_u16::<BigEndian>(buffer.len() as u16).unwrap();
51 }
52
53 ip::Packet::V6(ref _packet) => {
54 unimplemented!();
55 }
56 };
57
58 let mut result = 0xffffu32;
59 let mut buffer = Cursor::new(buffer);
60 let mut prefix = match *ip {
61 ip::Packet::V4(_) =>
62 Cursor::new(&prefix[0 .. 12]),
63
64 ip::Packet::V6(_) =>
65 Cursor::new(&prefix[0 .. 40]),
66 };
67
68 while let Ok(value) = prefix.read_u16::<BigEndian>() {
69 result += u32::from(value);
70
71 if result > 0xffff {
72 result -= 0xffff;
73 }
74 }
75
76 while let Ok(value) = buffer.read_u16::<BigEndian>() {
77 if buffer.position() == 18 {
79 continue;
80 }
81
82 result += u32::from(value);
83
84 if result > 0xffff {
85 result -= 0xffff;
86 }
87 }
88
89 !result as u16
90}