调整项目结构、尝试支持安卓

This commit is contained in:
lubeilin
2023-01-08 15:38:45 +08:00
parent d956e493af
commit 292893e9dd
76 changed files with 1132 additions and 588 deletions
+250
View File
@@ -0,0 +1,250 @@
use std::fmt;
use std::net::Ipv4Addr;
use byteorder::{BigEndian, ReadBytesExt};
use crate::cal_checksum;
use crate::error::*;
use crate::ip::ipv4::protocol::Protocol;
/// ip协议
/*
RFC: 791 https://www.ietf.org/rfc/rfc791.txt
0 15 31
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 版本(4) | 头部长度(4) | 服务类型(8) | 总字节数(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 标识(16) | 标志(3) | 片偏移(13) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 生存时间(8) | 协议(8) | 头部校验和(16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 目的ip地址(32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项 + 填充 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
数据体
注:头部长度单位是4字节,所以ip头最长60字节,选项最长40字节,选项填充按4字节对齐
*/
pub struct IpV4Packet<B> {
pub buffer: B,
}
impl<B: AsRef<[u8]>> IpV4Packet<B> {
pub fn unchecked(buffer: B) -> Self {
Self { buffer }
}
pub fn new(buffer: B) -> Result<Self> {
if buffer.as_ref()[0] >> 4 != 4 {
Err(Error::Unimplemented)?
}
if buffer.as_ref().len() < 20 {
Err(Error::SmallBuffer)?
}
let packet = Self::unchecked(buffer);
if packet.buffer.as_ref().len() < packet.header_len() as usize * 4 {
Err(Error::SmallBuffer)?
}
Ok(packet)
}
}
impl<B: AsRef<[u8]>> IpV4Packet<B> {
pub fn header(&self) -> &[u8] {
&self.buffer.as_ref()[..(self.header_len() as usize * 4)]
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[(self.header_len() as usize * 4)..]
// match self.protocol() {
// Protocol::Udp => {
// let udp = UdpPacket::new(IpAddr::V4(self.source_ip()),
// IpAddr::V4(self.destination_ip()),
// &self.buffer.as_ref()[(self.header_len() as usize * 4)..])?;
// Ok(crate::IpUpperLayer::UDP(udp))
// }
// _ => {
// Ok(crate::IpUpperLayer::Unknown(self.buffer.as_ref()));
// }
// }
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> IpV4Packet<B> {
pub fn header_mut(&mut self) -> &mut [u8] {
let len = self.header_len() as usize * 4;
&mut self.buffer.as_mut()[..len]
}
pub fn payload_mut(&mut self) -> &mut [u8] {
let len = self.header_len() as usize * 4;
&mut self.buffer.as_mut()[len..]
}
pub fn set_source_ip(&mut self, value: Ipv4Addr) {
self.header_mut()[12..16].copy_from_slice(&value.octets());
}
pub fn set_destination_ip(&mut self, value: Ipv4Addr) {
self.header_mut()[16..20].copy_from_slice(&value.octets());
}
fn set_checksum(&mut self, value: u16) {
self.header_mut()[10..12].copy_from_slice(&value.to_be_bytes())
}
/// 更新校验和
pub fn update_checksum(&mut self) {
//先将校验和置0
self.set_checksum(0);
self.set_checksum(cal_checksum(self.header()))
}
}
impl<B: AsRef<[u8]>> IpV4Packet<B> {
/// 版本号,ipv4的为4
pub fn version(&self) -> u8 {
self.buffer.as_ref()[0] >> 4
}
/// 头部长度,以4字节为单位
pub fn header_len(&self) -> u8 {
self.buffer.as_ref()[0] & 0b1111
}
/// 差异化服务编码点
///
/// 类别(3)+丢失概率(2)+用途(1)
///
///
/// 类别子字段值 | 名称
/// ---|:---
/// 000 | 常规(Routine)
/// 001 | 优先(Priority)
/// 010 | 立即(Immediate)
/// 011 | 瞬间(Flash)
/// 100 | 瞬间覆盖(Flash Override)
/// 101 | 严重(CRITIC/ECP)
/// 110 | 网间控制(Internetwork Control)
/// 111 | 网络控制(Network Control)
///
///
/// 参考:https://www.modb.pro/db/477116
pub fn dscp(&self) -> u8 {
self.buffer.as_ref()[1] >> 2
}
/// 显示拥塞 00:发送主机不支持ECN 01或者10:发送主机支持ECN 11:路由器正在经历拥塞
pub fn ecn(&self) -> u8 {
self.buffer.as_ref()[1] & 0b11
}
/// ip报总字节数
pub fn length(&self) -> u16 {
(&self.buffer.as_ref()[2..])
.read_u16::<BigEndian>()
.unwrap()
}
/// 标识. ip报文在数据链路层可能会被拆分,同一报文的不同分组标识字段相同
pub fn id(&self) -> u16 {
(&self.buffer.as_ref()[4..])
.read_u16::<BigEndian>()
.unwrap()
}
/// 标志 3位.
/// 第1位没有使用
/// 第2位表示不分段位(DF
/// 0:允许数据报分段
/// 1:数据报不能分段
/// 置1之后路由器不能对其分段处理,如果超过MTU值则路由器不能对其转发将其丢弃,并向源点发送错误消息
/// 第3位表示更多段位
/// 0:数据包后面没有包,该包为最后的包
/// 1:数据包后面有更多的包
pub fn flags(&self) -> u8 {
self.buffer.as_ref()[6] >> 5
}
/// 片偏移 13位.
/// 以字节为单位,用于指明分段起始点相对于包头起始点的偏移量
/// 由于分段到达时可能错序,所以分段的偏移字段可以使接收者按照正确的顺序重组数据包
pub fn offset(&self) -> u16 {
(&self.buffer.as_ref()[6..])
.read_u16::<BigEndian>()
.unwrap()
& 0x1fff
}
/// 生存时间.
/// 每一跳 减1 到0了则会被丢弃
pub fn ttl(&self) -> u8 {
self.buffer.as_ref()[8]
}
/// 协议.
pub fn protocol(&self) -> Protocol {
self.buffer.as_ref()[9].into()
}
/// 首部校验和
pub fn checksum(&self) -> u16 {
(&self.buffer.as_ref()[10..])
.read_u16::<BigEndian>()
.unwrap()
}
/// 验证校验和
///
/// TCP/IP协议栈不会自己计算校验和,而是简单地将一个空的校验和字段(零或随机填充)交给网卡硬件。
/// 所以抓到发出去的包校验和可能是错误的
pub fn is_valid(&self) -> bool {
self.checksum() == 0 || cal_checksum(self.header()) == 0
}
/// 源ip.
pub fn source_ip(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[12],
self.buffer.as_ref()[13],
self.buffer.as_ref()[14],
self.buffer.as_ref()[15],
)
}
/// 目标ip.
pub fn destination_ip(&self) -> Ipv4Addr {
Ipv4Addr::new(
self.buffer.as_ref()[16],
self.buffer.as_ref()[17],
self.buffer.as_ref()[18],
self.buffer.as_ref()[19],
)
}
/// 选项.
pub fn options(&self) -> &[u8] {
&self.buffer.as_ref()[20..(self.header_len() as usize * 4)]
}
}
impl<B: AsRef<[u8]>> fmt::Debug for IpV4Packet<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ip::v4::Packet")
.field("version", &self.version())
.field("header_len", &self.header_len())
.field("dscp", &self.dscp())
.field("ecn", &self.ecn())
.field("length", &self.length())
.field("id", &self.id())
.field("flags", &self.flags())
.field("offset", &self.offset())
.field("ttl", &self.ttl())
.field("protocol", &self.protocol())
.field("checksum", &self.checksum())
.field("is_valid", &self.is_valid())
.field("source", &self.source_ip())
.field("destination", &self.destination_ip())
.field("options", &self.options())
.field("payload", &self.payload())
.finish()
}
}