#ifndef LLARP_IP_HPP #define LLARP_IP_HPP #include #include #include #include #ifndef _WIN32 // unix, linux #include // FreeBSD needs this for uchar for ip.h #include #include #else // windows nt #include typedef struct ip_hdr { unsigned char ip_header_len : 4; // 4-bit header length (in 32-bit words) normally=5 // (Means 20 Bytes may be 24 also) unsigned char ip_version : 4; // 4-bit IPv4 version unsigned char ip_tos; // IP type of service unsigned short ip_total_length; // Total length unsigned short ip_id; // Unique identifier unsigned char ip_frag_offset : 5; // Fragment offset field unsigned char ip_more_fragment : 1; unsigned char ip_dont_fragment : 1; unsigned char ip_reserved_zero : 1; unsigned char ip_frag_offset1; // fragment offset unsigned char ip_ttl; // Time to live unsigned char ip_protocol; // Protocol(TCP,UDP etc) unsigned short ip_checksum; // IP checksum unsigned int ip_srcaddr; // Source address unsigned int ip_destaddr; // Source address } IPV4_HDR; #define iphdr IPV4_HDR #define saddr ip_srcaddr #define daddr ip_destaddr #define check ip_checksum #define ihl ip_header_len #define ip_version version #endif #include // anything not win32 struct ip_header { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int ihl : 4; unsigned int version : 4; #elif __BYTE_ORDER == __BIG_ENDIAN unsigned int version : 4; unsigned int ihl : 4; #else #error "Please fix " #endif #if defined(__linux__) #define ip_version version #endif uint8_t tos; uint16_t tot_len; uint16_t id; uint16_t frag_off; uint8_t ttl; uint8_t protocol; uint16_t check; uint32_t saddr; uint32_t daddr; }; namespace llarp { namespace net { struct IPv4Packet { static constexpr size_t MaxSize = 1500; llarp_time_t timestamp; size_t sz; byte_t buf[MaxSize]; llarp_buffer_t Buffer(); llarp_buffer_t ConstBuffer() const; bool Load(llarp_buffer_t buf); struct GetTime { llarp_time_t operator()(const IPv4Packet& pkt) const { return pkt.timestamp; } }; struct PutTime { llarp_ev_loop* loop; PutTime(llarp_ev_loop* evloop) : loop(evloop) { } void operator()(IPv4Packet& pkt) const { pkt.timestamp = llarp_ev_loop_time_now_ms(loop); } }; struct GetNow { llarp_ev_loop* loop; GetNow(llarp_ev_loop* evloop) : loop(evloop) { } llarp_time_t operator()() const { return llarp_ev_loop_time_now_ms(loop); } }; struct CompareSize { bool operator()(const IPv4Packet& left, const IPv4Packet& right) { return left.sz < right.sz; } }; struct CompareOrder { bool operator()(const IPv4Packet& left, const IPv4Packet& right) { return left.timestamp < right.timestamp; } }; inline ip_header* Header() { return (ip_header*)&buf[0]; } inline const ip_header* Header() const { return (ip_header*)&buf[0]; } inline huint32_t src() { return huint32_t{ntohl(Header()->saddr)}; } inline huint32_t dst() { return huint32_t{ntohl(Header()->daddr)}; } inline void src(huint32_t ip) { Header()->saddr = htonl(ip.h); } inline void dst(huint32_t ip) { Header()->daddr = htonl(ip.h); } // update ip packet (after packet gets out of network) void UpdateIPv4PacketOnDst(huint32_t newSrcIP, huint32_t newDstIP); // update ip packet (before packet gets inserted into network) void UpdateIPv4PacketOnSrc(); }; } // namespace net } // namespace llarp #endif