SmartOS/Net/Ethernet.h

416 lines
11 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _Ethernet_H_
#define _Ethernet_H_
#include "Kernel\Sys.h"
// TCP/IP协议头部结构体
// 字节序
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1
#endif
#pragma pack(push) // 保存对齐状态
// 强制结构体紧凑分配空间
#pragma pack(1)
// IP地址
typedef uint IPAddr;
// Mac地址。结构体和类都可以
//typedef struct _MacAddress MacAddr;
//struct _MacAddress
class MacAddr
{
public:
// 长整型转为Mac地址取内存前6字节。因为是小字节序需要v4在前v2在后
// 比如Mac地址12-34-56-78-90-12v4是12-34-56-78v2是90-12ulong是0x0000129078563412
uint v4;
ushort v2;
MacAddr(UInt64 v = 0)
{
v4 = v & 0xFFFFFFFF;
v2 = (v >> 32) & 0xFFFF;
}
// 是否广播地址全0或全1
bool IsBroadcast() { return (!v4 && !v2) || (v4 == 0xFFFFFFFF && v2 == 0xFFFF); }
MacAddr& operator=(UInt64 v)
{
v4 = v & 0xFFFFFFFF;
v2 = (v >> 32) & 0xFFFF;
return *this;
}
UInt64 Value()
{
UInt64 v = v4;
v |= ((UInt64)v2) << 32;
return v;
}
MacAddr& operator=(const MacAddress& v) { *this = v.Value; return *this; }
friend bool operator==(MacAddr& addr1, MacAddr& addr2)
{
return addr1.v4 == addr2.v4 && addr1.v2 == addr2.v2;
}
friend bool operator!=(MacAddr& addr1, MacAddr& addr2)
{
return addr1.v4 != addr2.v4 || addr1.v2 != addr2.v2;
}
};
//}MacAddr;
#define IP_FULL 0xFFFFFFFF
#define MAC_FULL 0xFFFFFFFFFFFFFFFFull
// 以太网协议类型
typedef enum
{
ETH_ARP = 0x0608,
ETH_IP = 0x0008,
ETH_IPv6 = 0xDD86,
}ETH_TYPE;
#define IS_ETH_TYPE(type) (type == ETH_ARP || type == ETH_IP || type == ETH_IPv6)
//Mac头部总长度14字节
typedef struct _ETH_HEADER
{
MacAddr DestMac; // 目标mac地址
MacAddr SrcMac; // 源mac地址
ETH_TYPE Type; // 以太网类型
uint Size() { return sizeof(this[0]); }
uint Offset() { return Size(); }
byte* Next() { return (byte*)this + Size(); }
}ETH_HEADER;
// IP协议类型
typedef enum
{
IP_NONE = 0,
IP_ICMP = 1,
IP_IGMP = 2,
IP_TCP = 6,
IP_UDP = 17,
}IP_TYPE;
#define IS_IP_TYPE(type) (type == IP_ICMP || type == IP_IGMP || type == IP_TCP || type == IP_UDP)
// IP头部总长度20=0x14字节偏移14=0x0E。后面可能有可选数据Length决定头部总长度4的倍数
typedef struct _IP_HEADER
{
#if LITTLE_ENDIAN
byte Length : 4; // 首部长度
byte Version : 4; // 版本
#else
byte Version : 4; // 版本
byte Length : 4; // 首部长度。每个单位4个字节
#endif
byte TypeOfService; // 服务类型
ushort TotalLength; // 总长度
ushort Identifier; // 标志
byte Flags; // 标识是否对数据包进行分段
byte FragmentOffset; // 记录分段的偏移值。接收者会根据这个值进行数据包的重新组和
byte TTL; // 生存时间
IP_TYPE Protocol; // 协议
ushort Checksum; // 检验和
IPAddr SrcIP; // 源IP地址
IPAddr DestIP; // 目的IP地址
void Init(IP_TYPE type, bool recursion = false)
{
Version = 4;
Length = sizeof(this[0]) >> 2;
TypeOfService = 0;
Flags = 0;
FragmentOffset = 0;
TTL = 64;
Protocol = type;
if (recursion) Prev()->Type = ETH_IP;
}
uint Size() { return (Length <= 5) ? sizeof(this[0]) : (Length << 2); }
uint Offset() { return Prev()->Offset() + Size(); }
ETH_HEADER* Prev() { return (ETH_HEADER*)((byte*)this - sizeof(ETH_HEADER)); }
//byte* Next() { return (byte*)this + sizeof(&this[0]); }
byte* Next() { return (byte*)this + Size(); }
}IP_HEADER;
typedef enum
{
TCP_FLAGS_FIN = 1, // 结束连接请求标志位。为1表示结束连接请求数据包
TCP_FLAGS_SYN = 2, // 连接请求标志位。为1表示发起连接的请求数据包
TCP_FLAGS_RST = 4,
TCP_FLAGS_PUSH = 8, // 标志位为1表示此数据包应立即进行传递
TCP_FLAGS_ACK = 0x10, // 应答标志位为1表示确认数据包为应答数据包
TCP_FLAGS_URG = 0x20,
}TCP_FLAGS;
//TCP头部总长度20=0x14字节偏移34=0x22。后面可能有可选数据Length决定头部总长度4的倍数
typedef struct _TCP_HEADER
{
ushort SrcPort; // 源端口号
ushort DestPort; // 目的端口号
uint Seq; // 序列号
uint Ack; // 确认号
#if LITTLE_ENDIAN
byte reserved_1 : 4; // 保留6位中的4位首部长度
byte Length : 4; // tcp头部长度
byte Flags : 6; // 6位标志
byte reserved_2 : 2; // 保留6位中的2位
#else
byte Length : 4; // tcp头部长度
byte reserved_1 : 4; // 保留6位中的4位首部长度
byte reserved_2 : 2; // 保留6位中的2位
byte Flags : 6; // 6位标志
#endif
ushort WindowSize; // 16位窗口大小
ushort Checksum; // 16位TCP检验和
ushort urgt_p; // 16为紧急指针
void Init(bool recursion = false)
{
Length = sizeof(this[0]) >> 2;
reserved_1 = 0;
reserved_2 = 0;
//WindowSize = _REV16(8192);
WindowSize = _REV16(1024);
urgt_p = 0;
if (recursion) Prev()->Init(IP_TCP, recursion);
}
uint Size() { return (Length <= 5) ? sizeof(this[0]) : (Length << 2); }
uint Offset() { return Prev()->Offset() + Size(); }
IP_HEADER* Prev() { return (IP_HEADER*)((byte*)this - sizeof(IP_HEADER)); }
byte* Next() { return (byte*)this + Size(); }
}TCP_HEADER;
//UDP头部总长度8字节偏移34=0x22
typedef struct _UDP_HEADER
{
ushort SrcPort; // 远端口号
ushort DestPort; // 目的端口号
ushort Length; // 头部加上负载的总长度
ushort Checksum; // 检验和
void Init(bool recursion = false)
{
Length = sizeof(this[0]);
if (recursion) Prev()->Init(IP_UDP, recursion);
}
uint Size() { return sizeof(this[0]); }
uint Offset() { return Prev()->Offset() + Size(); }
IP_HEADER* Prev() { return (IP_HEADER*)((byte*)this - sizeof(IP_HEADER)); }
byte* Next() { return (byte*)this + Size(); }
}UDP_HEADER;
//ICMP头部总长度8字节偏移34=0x22
typedef struct _ICMP_HEADER
{
byte Type; // 类型
byte Code; // 代码
ushort Checksum; // 16位检验和
ushort Identifier; // 标识仅用于Ping
ushort Sequence; // 序列号仅用于Ping
void Init(bool recursion = false)
{
Type = 8;
Code = 0;
if (recursion) Prev()->Init(IP_ICMP, recursion);
}
uint Size() { return sizeof(this[0]); }
uint Offset() { return Prev()->Offset() + Size(); }
IP_HEADER* Prev() { return (IP_HEADER*)((byte*)this - sizeof(IP_HEADER)); }
byte* Next() { return (byte*)this + Size(); }
}ICMP_HEADER;
// ARP头部总长度28=0x1C字节偏移14=0x0E可能加18字节填充
typedef struct _ARP_HEADER
{
ushort HardType; // 硬件类型
ushort NetType; // 协议类型
byte HardLength; // 硬件地址长度
byte ProtocolLength; // 协议地址长度
ushort Option; // 选项
MacAddr SrcMac;
IPAddr SrcIP; // 源IP地址
MacAddr DestMac;
IPAddr DestIP; // 目的IP地址
//byte Padding[18]; // 填充凑够60字节
void Init(bool recursion = false)
{
HardType = 0x0100;
NetType = 0x08;
HardLength = 6;
ProtocolLength = 4;
if (recursion) Prev()->Type = ETH_ARP;
}
uint Size() { return sizeof(this[0]); }
uint Offset() { return Prev()->Offset() + Size(); }
ETH_HEADER* Prev() { return (ETH_HEADER*)((byte*)this - sizeof(ETH_HEADER)); }
byte* Next() { return (byte*)this + Size(); }
}ARP_HEADER;
// DHCP头部总长度240=0xF0字节偏移42=0x2A后面可选数据偏移282=0x11A
typedef struct _DHCP_HEADER
{
byte MsgType; // 若是client送给server的封包设为1反向为2
byte HardType; // 以太网1
byte HardLength; // 以太网6
byte Hops; // 若数据包需经过router传送每站加1若在同一网内为0
uint TransID; // 事务ID是个随机数用于客户和服务器之间匹配请求和相应消息
ushort Seconds; // 由用户指定的时间,指开始地址获取和更新进行后的时间
ushort Flags; // 从0-15bits最左一bit为1时表示server将以广播方式传送封包给 client其余尚未使用
IPAddr ClientIP; // 客户机IP
IPAddr YourIP; // 你的IP
IPAddr ServerIP; // 服务器IP
IPAddr RelayIP; // 中继代理IP
byte ClientMac[16]; // 客户端硬件地址
byte ServerName[64]; // 服务器名
byte BootFile[128]; // 启动文件名
uint Magic; // 幻数0x63825363小端0x63538263
void Init(uint dhcpid, bool recursion = false)
{
// 为了安全,清空一次
Buffer(this, sizeof(this[0])).Clear();
MsgType = 1;
HardType = 1;
HardLength = 6;
Hops = 0;
TransID = _REV(dhcpid);
//Flags = 0x80; // 从0-15bits最左一bit为1时表示server将以广播方式传送封包给 client其余尚未使用
SetMagic();
if (recursion) Prev()->Init(recursion);
}
uint Size() { return sizeof(this[0]); }
uint Offset() { return Prev()->Offset() + Size(); }
UDP_HEADER* Prev() { return (UDP_HEADER*)((byte*)this - sizeof(UDP_HEADER)); }
byte* Next() { return (byte*)this + Size(); }
void SetMagic() { Magic = 0x63538263; }
bool Valid() { return Magic == 0x63538263; }
}DHCP_HEADER;
// DHCP后面可选数据格式为“代码+长度+数据”
typedef enum
{
DHCP_OPT_Mask = 1,
DHCP_OPT_Router = 3,
DHCP_OPT_TimeServer = 4,
DHCP_OPT_NameServer = 5,
DHCP_OPT_DNSServer = 6,
DHCP_OPT_LOGServer = 7,
DHCP_OPT_HostName = 12,
DHCP_OPT_MTU = 26, // 0x1A
DHCP_OPT_StaticRout = 33, // 0x21
DHCP_OPT_ARPCacheTimeout = 35, // 0x23
DHCP_OPT_NTPServer = 42, // 0x2A
DHCP_OPT_RequestedIP = 50, // 0x32
DHCP_OPT_IPLeaseTime = 51, // 0x33
DHCP_OPT_MessageType = 53, // 0x35
DHCP_OPT_DHCPServer = 54, // 0x36
DHCP_OPT_ParameterList = 55, // 0x37
DHCP_OPT_Message = 56, // 0x38
DHCP_OPT_MaxMessageSize = 57, // 0x39
DHCP_OPT_Vendor = 60, // 0x3C
DHCP_OPT_ClientIdentifier = 61, // 0x3D
DHCP_OPT_End = 255,
}DHCP_OPTION;
typedef enum
{
DHCP_TYPE_Discover = 1,
DHCP_TYPE_Offer = 2,
DHCP_TYPE_Request = 3,
DHCP_TYPE_Decline = 4,
DHCP_TYPE_Ack = 5,
DHCP_TYPE_Nak = 6,
DHCP_TYPE_Release = 7,
DHCP_TYPE_Inform = 8,
}DHCP_MSGTYPE;
typedef struct _DHCP_OPT
{
DHCP_OPTION Option; // 代码
byte Length; // 长度
byte Data; // 数据
struct _DHCP_OPT* Next() { return (struct _DHCP_OPT*)((byte*)this + 2 + Length); }
struct _DHCP_OPT* SetType(DHCP_MSGTYPE type)
{
Option = DHCP_OPT_MessageType;
Length = 1;
Data = type;
return this;
}
struct _DHCP_OPT* SetData(DHCP_OPTION option, const Buffer& bs)
{
Option = option;
Length = bs.Length();
bs.CopyTo(0, &Data, -1);
return this;
}
/*struct _DHCP_OPT* SetData(DHCP_OPTION option, String& str)
{
ByteArray bs(str);
return SetData(option, bs);
}*/
struct _DHCP_OPT* SetData(DHCP_OPTION option, uint value)
{
Option = option;
Length = 4;
Buffer(&Data, 4) = &value;
return this;
}
struct _DHCP_OPT* SetClientId(MacAddress& mac)
{
Option = DHCP_OPT_ClientIdentifier;
Length = 1 + 6;
Data = 1; // 类型ETHERNET=1
mac.CopyTo(&Data + 1);
return this;
}
struct _DHCP_OPT* End()
{
Option = DHCP_OPT_End;
return this;
}
}DHCP_OPT;
#pragma pack(pop) // 恢复对齐状态
#endif