Files
psopeeps-newserv/src/IPFrameInfo.hh
T
2023-10-13 00:45:27 -07:00

122 lines
3.1 KiB
C++

#pragma once
#include <stdint.h>
#include <phosg/Encoding.hh>
#include "Text.hh"
struct EthernetHeader {
parray<uint8_t, 6> dest_mac;
parray<uint8_t, 6> src_mac;
be_uint16_t protocol;
} __attribute__((packed));
struct ARPHeader {
be_uint16_t hardware_type;
be_uint16_t protocol_type; // same as EthernetHeader::protocol
uint8_t hwaddr_len;
uint8_t paddr_len;
be_uint16_t operation;
} __attribute__((packed));
struct IPv4Header {
uint8_t version_ihl;
uint8_t tos;
be_uint16_t size;
be_uint16_t id;
be_uint16_t frag_offset;
uint8_t ttl;
uint8_t protocol;
be_uint16_t checksum;
be_uint32_t src_addr;
be_uint32_t dest_addr;
} __attribute__((packed));
struct UDPHeader {
be_uint16_t src_port;
be_uint16_t dest_port;
be_uint16_t size;
be_uint16_t checksum;
} __attribute__((packed));
struct TCPHeader {
enum Flag {
NS = 0x0100,
CWR = 0x0080, // congestion window reduced
ECE = 0x0040, // ECN capable / congestion experienced
URG = 0x0020, // urgent pointer used
ACK = 0x0010, // ack_num is valid
PSH = 0x0008, // sending data
RST = 0x0004, // reset (hard disconnect)
SYN = 0x0002, // synchronize sequence numbers (open connection)
FIN = 0x0001, // close (normal disconnect)
};
be_uint16_t src_port;
be_uint16_t dest_port;
be_uint32_t seq_num;
be_uint32_t ack_num;
be_uint16_t flags;
be_uint16_t window;
be_uint16_t checksum;
be_uint16_t urgent_ptr;
} __attribute__((packed));
struct DHCPHeader {
uint8_t opcode = 0;
uint8_t hardware_type = 1; // 1 = Ethernet
uint8_t hardware_address_length = 6; // 6 for Ethernet
uint8_t hops = 0;
be_uint32_t transaction_id = 0;
be_uint16_t seconds_elapsed = 0;
be_uint16_t flags = 0;
be_uint32_t client_ip_address = 0;
be_uint32_t your_ip_address = 0;
be_uint32_t server_ip_address = 0;
be_uint32_t gateway_ip_address = 0;
parray<uint8_t, 0x10> client_hardware_address;
parray<uint8_t, 0xC0> unused_bootp_legacy;
be_uint32_t magic = 0x63825363;
// Options follow here, terminated with FF
} __attribute__((packed));
struct FrameInfo {
// This is always valid
const EthernetHeader* ether;
uint16_t ether_protocol;
// At most one of these is not null
const IPv4Header* ipv4;
const ARPHeader* arp;
// One of these may be not null if this->ipv4 is not null
const UDPHeader* udp;
const TCPHeader* tcp;
const void* header_start;
const void* payload;
size_t total_size;
size_t tcp_options_size;
size_t payload_size;
FrameInfo();
FrameInfo(const std::string& data);
FrameInfo(const void* data, size_t size);
std::string header_str() const;
void truncate(size_t new_total_size);
size_t size_from_header() const;
static uint16_t computed_ipv4_header_checksum(const IPv4Header& ipv4);
uint16_t computed_ipv4_header_checksum() const;
static uint16_t computed_udp4_checksum(
const IPv4Header& ipv4, const UDPHeader& udp, const void* data, size_t size);
uint16_t computed_udp4_checksum() const;
static uint16_t computed_tcp4_checksum(
const IPv4Header& ip, const TCPHeader& tcp, const void* data, size_t size);
uint16_t computed_tcp4_checksum() const;
};