From f708d192fbeb1d1c19bc5947672eb7834f25b27d Mon Sep 17 00:00:00 2001 From: WerWolv Date: Thu, 17 Mar 2022 22:45:18 +0100 Subject: [PATCH] patterns: Added Ethernet II Frame pattern --- README.md | 1 + patterns/ip.hexpat | 270 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 patterns/ip.hexpat diff --git a/README.md b/README.md index 964f650..17da7ee 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed | TGA | `image/tga` | `patterns/tga.hexpat` | Truevision TGA/TARGA image | | ISO | | `patterns/iso.hexpat` | ISO 9660 file system | | VDF | | `patterns/vdf.hexpat` | Binary Value Data Format (.vdf) files | +| IP | | `patterns/ip.hexpat` | Ethernet II Frames (IP Packets) | ### Scripts diff --git a/patterns/ip.hexpat b/patterns/ip.hexpat new file mode 100644 index 0000000..1df8c36 --- /dev/null +++ b/patterns/ip.hexpat @@ -0,0 +1,270 @@ + #pragma endian big + #pragma bitfield_order left_to_right + +#include +#include + +struct MAC { + u8 octets[6]; +} [[format("mac_formatter")]]; + +fn mac_formatter(MAC mac) { + return std::format("{0:02X}:{1:02X}:{2:02X}:{3:02X}:{4:02X}:{5:02X}", + mac.octets[0], + mac.octets[1], + mac.octets[2], + mac.octets[3], + mac.octets[4], + mac.octets[5]); +}; + +enum EtherType : u16 { + IPv4 = 0x0800, + ARP = 0x0806, + WakeOnLAN = 0x0842, + AVTP = 0x22F0, + IETF_TRILL = 0x22F3, + SRP = 0x22EA, + DEC_MOP_RC = 0x6002, + DECnet = 0x6003, + DEC_LAT = 0x6004, + RARP = 0x8035, + AppleTalk = 0x809B, + AppleTalk_AARP = 0x80F3, + VLANTaggedFrame = 0x8100, + SLPP = 0x8102, + VLACP = 0x8103, + IPX = 0x8137, + QNX_Qnet = 0x8204, + IPv6 = 0x860D, + EthernetFlowControl = 0x8808, + EthernetSlowProtocols = 0x8809, + CobraNet = 0x8819, + MPLS_Unicast = 0x8847, + MPLS_Multicast = 0x8848, + PPPoE_Discovery = 0x8863, + PPPoE_Session = 0x8864, + HomePlug = 0x887B, + EAPOverLAN = 0x888E, + PROFINET = 0x8892, + HyperSCSI = 0x889A, + ATAOverEthernet = 0x88A2, + EtherCAT = 0x88A4, + ServiceVLANTagIdentifier = 0x88A8, + EthernetPowerlink = 0x88AB, + GOOSE = 0x88B8, + GSE = 0x88B9, + SV = 0x88BA, + MikroTik_RoMON = 0x88BF, + LLDP = 0x88CC, + SERCOS_III = 0x88CD, + HomePlugGreenPHY = 0x88E1, + MRP = 0x88E3, + IEEE802_1AE = 0x88E5, + PBB = 0x88E7, + PTP = 0x88F7, + NC_SI = 0x88F8, + PRP = 0x88FB, + CFM = 0x8902, + FCoE = 0x8906, + FCoEIP = 0x8914, + RoCE = 0x8915, + TTE = 0x891D, + IEEE_1905_1 = 0x893A, + HSR = 0x892F, + ECTP = 0x9000, + RedundancyTag = 0xF1C1 +}; + +namespace ip { + + enum Protocol : u8 { + ICMP = 1, + IGMP = 2, + TCP = 6, + UDP = 17, + ENCAP = 41, + OSPF = 89, + SCTP = 132 + }; + + namespace udp { + + struct Packet { + u16 source_port; + u16 destination_port; + u16 length; + std::assert(length >= 8, "UDP Packet has invalid length"); + u16 checksum; + u8 data[length - 8]; + }; + + } + + namespace tcp { + + bitfield Flags { + data_offset : 4; + padding : 3; + ns : 1; + cwr : 1; + ece : 1; + urg : 1; + ack : 1; + psh : 1; + rst : 1; + syn : 1; + fin : 1; + }; + + struct Packet { + u16 source_port; + u16 destination_port; + u32 sequence_number; + u32 ack_number; + Flags flags [[inline]]; + u16 window_size; + u16 checksum; + u16 urgent_pointer; + + if (flags.data_offset > 5) + u8 options[(flags.data_offset - 5) * sizeof(u32)]; + + u8 data[parent.parent.header.total_length - 40]; + }; + + } + + struct Payload { + if (parent.protocol == ip::Protocol::UDP) + udp::Packet packet [[inline]]; + else if (parent.protocol == ip::Protocol::TCP) + tcp::Packet packet [[inline]]; + else + std::error(std::format("Unknown protocol: {}", parent.protocol)); + }; + +} + +namespace ipv4 { + + struct Address { + u8 octets[4]; + } [[format("ipv4::address_formatter")]]; + + fn address_formatter(Address addr) { + return std::format("{0}.{1}.{2}.{3}", + addr.octets[0], + addr.octets[1], + addr.octets[2], + addr.octets[3]); + }; + + bitfield Header { + version : 4; + ihl : 4; + tos : 8; + total_length : 16; + }; + + bitfield Flags { + reserved : 1; + df : 1; + mf : 1; + fragment_offset : 13; + }; + + + struct Packet { + Header header [[inline]]; + u16 identification; + Flags flags [[inline]]; + u8 time_to_live; + ip::Protocol protocol; + u16 header_checksum; + + Address source_ip_address; + Address destination_ip_address; + + if (header.ihl > 5) + u8 options[(header.ihl - 5) * sizeof(u32)]; + + ip::Payload payload; + }; + +} + + +namespace ipv6 { + + struct Address { + u16 segments[8]; + } [[format("ipv6::address_formatter")]]; + + fn address_formatter(Address addr) { + return std::format("{0:04X}:{1:04X}:{2:04X}:{3:04X}:{4:04X}:{5:04X}:{6:04X}:{7:04X}", + addr.segments[0], + addr.segments[1], + addr.segments[2], + addr.segments[3], + addr.segments[4], + addr.segments[5], + addr.segments[6], + addr.segments[7]); + }; + + bitfield Header { + version : 4; + ds : 6; + ecn : 2; + flow_label : 20; + }; + + struct Packet { + Header header [[inline]]; + u16 payload_length; + ip::Protocol next_header; + u8 hop_limit; + + Address source_address; + Address destination_address; + + ip::Payload payload; + }; + +} + + + +struct Payload { + if (parent.type == EtherType::IPv4) + ipv4::Packet packet [[inline]]; + else + std::error(std::format("Unknown payload type: 0x{:04X}", parent.type)); +}; + +bitfield TCI { + pcp : 3; + dei : 1; + vid : 12; +}; + +struct EthernetIIFrame { + MAC destination_address; + MAC source_address; + + u16 possible_tpid [[no_unique_address, hidden]]; + if (possible_tpid == EtherType::VLANTaggedFrame) { + u16 tpid; + TCI tci [[inline]]; + } + + EtherType type; + + Payload payload; + std::assert(sizeof(payload) >= 40 && sizeof(payload) <= 1500, std::format("Payload size out of range: {}", sizeof(payload))); + + u32 frame_check_sequence; +}; + +EthernetIIFrame frame @ 0x00;