#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { struct IPv4Header { uint8_t version_IHL; uint8_t DSCP_ECN; BAN::NetworkEndian total_length { 0 }; BAN::NetworkEndian identification { 0 }; BAN::NetworkEndian flags_frament { 0 }; uint8_t time_to_live; uint8_t protocol; BAN::NetworkEndian checksum { 0 }; BAN::IPv4Address src_address; BAN::IPv4Address dst_address; }; static_assert(sizeof(IPv4Header) == 20); class IPv4Layer final : public NetworkLayer { BAN_NON_COPYABLE(IPv4Layer); BAN_NON_MOVABLE(IPv4Layer); public: static BAN::ErrorOr> create(); ~IPv4Layer(); ARPTable& arp_table() { return *m_arp_table; } void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan); virtual void unbind_socket(BAN::RefPtr, uint16_t port) override; virtual BAN::ErrorOr bind_socket_to_unused(BAN::RefPtr, const sockaddr* send_address, socklen_t send_address_len) override; virtual BAN::ErrorOr bind_socket_to_address(BAN::RefPtr, const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override; virtual size_t header_size() const override { return sizeof(IPv4Header); } private: IPv4Layer(); void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const; void packet_handle_task(); BAN::ErrorOr handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan); private: struct PendingIPv4Packet { NetworkInterface& interface; }; private: RecursiveSpinLock m_bound_socket_lock; BAN::UniqPtr m_arp_table; Process* m_process { nullptr }; static constexpr size_t pending_packet_buffer_size = 128 * PAGE_SIZE; BAN::UniqPtr m_pending_packet_buffer; BAN::CircularQueue m_pending_packets; Semaphore m_pending_semaphore; size_t m_pending_total_size { 0 }; BAN::HashMap> m_bound_sockets; friend class BAN::UniqPtr; }; }