mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:54:58 +00:00
Kernel+LibC: Add support for the IPv4 TOS field via the IP_TOS sockopt
This commit is contained in:
parent
20c7fcfedf
commit
adc9939a7b
9 changed files with 37 additions and 8 deletions
|
@ -22,6 +22,7 @@ typedef uint32_t in_addr_t;
|
|||
|
||||
#define IN_LOOPBACKNET 127
|
||||
|
||||
#define IP_TOS 1
|
||||
#define IP_TTL 2
|
||||
#define IP_MULTICAST_LOOP 3
|
||||
#define IP_ADD_MEMBERSHIP 4
|
||||
|
@ -29,6 +30,10 @@ typedef uint32_t in_addr_t;
|
|||
#define IP_MULTICAST_IF 6
|
||||
#define IP_MULTICAST_TTL 7
|
||||
|
||||
#define IPTOS_LOWDELAY 16
|
||||
#define IPTOS_THROUGHPUT 8
|
||||
#define IPTOS_RELIABILITY 4
|
||||
|
||||
/* Make sure these don't overlap with any other IPv4 and IPv6 options */
|
||||
#define MCAST_JOIN_SOURCE_GROUP 100
|
||||
#define MCAST_LEAVE_SOURCE_GROUP 101
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
u8 version() const { return (m_version_and_ihl >> 4) & 0xf; }
|
||||
void set_version(u8 version) { m_version_and_ihl = (m_version_and_ihl & 0x0f) | (version << 4); }
|
||||
|
||||
u8 dscp_and_ecn() const { return m_dscp_and_ecn; }
|
||||
void set_dscp_and_ecn(u8 dscp_and_ecn) { m_dscp_and_ecn = dscp_and_ecn; }
|
||||
|
||||
u8 internet_header_length() const { return m_version_and_ihl & 0xf; }
|
||||
void set_internet_header_length(u8 ihl) { m_version_and_ihl = (m_version_and_ihl & 0xf0) | (ihl & 0x0f); }
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ KResultOr<size_t> IPv4Socket::sendto(OpenFileDescription&, const UserOrKernelBuf
|
|||
if (!packet)
|
||||
return set_so_error(ENOMEM);
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet, local_address(), routing_decision.next_hop,
|
||||
m_peer_address, (IPv4Protocol)protocol(), data_length, m_ttl);
|
||||
m_peer_address, (IPv4Protocol)protocol(), data_length, m_type_of_service, m_ttl);
|
||||
if (auto result = data.read(packet->buffer->data() + ipv4_payload_offset, data_length); result.is_error()) {
|
||||
routing_decision.adapter->release_packet_buffer(*packet);
|
||||
return set_so_error(result);
|
||||
|
@ -504,6 +504,16 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
|
|||
m_ttl = value;
|
||||
return KSuccess;
|
||||
}
|
||||
case IP_TOS: {
|
||||
if (user_value_size < sizeof(int))
|
||||
return EINVAL;
|
||||
int value;
|
||||
TRY(copy_from_user(&value, static_ptr_cast<const int*>(user_value)));
|
||||
if (value < 0 || value > 255)
|
||||
return EINVAL;
|
||||
m_type_of_service = value;
|
||||
return KSuccess;
|
||||
}
|
||||
case IP_MULTICAST_LOOP: {
|
||||
if (user_value_size != 1)
|
||||
return EINVAL;
|
||||
|
@ -559,6 +569,14 @@ KResult IPv4Socket::getsockopt(OpenFileDescription& description, int level, int
|
|||
size = sizeof(int);
|
||||
return copy_to_user(value_size, &size);
|
||||
}
|
||||
case IP_TOS: {
|
||||
if (size < sizeof(int))
|
||||
return EINVAL;
|
||||
int type_of_service = m_type_of_service;
|
||||
TRY(copy_to_user(static_ptr_cast<int*>(value), (int*)&type_of_service));
|
||||
size = sizeof(int);
|
||||
return copy_to_user(value_size, &size);
|
||||
}
|
||||
case IP_MULTICAST_LOOP: {
|
||||
if (size < 1)
|
||||
return EINVAL;
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
|
||||
String absolute_path(const OpenFileDescription& description) const override;
|
||||
|
||||
u8 type_of_service() const { return m_type_of_service; }
|
||||
u8 ttl() const { return m_ttl; }
|
||||
|
||||
enum class BufferMode {
|
||||
|
@ -123,6 +124,7 @@ private:
|
|||
|
||||
u32 m_bytes_received { 0 };
|
||||
|
||||
u8 m_type_of_service { IPTOS_LOWDELAY };
|
||||
u8 m_ttl { 64 };
|
||||
|
||||
bool m_can_read { false };
|
||||
|
|
|
@ -47,7 +47,7 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet
|
|||
send_packet({ (const u8*)eth, size_in_bytes });
|
||||
}
|
||||
|
||||
void NetworkAdapter::fill_in_ipv4_header(PacketWithTimestamp& packet, IPv4Address const& source_ipv4, MACAddress const& destination_mac, IPv4Address const& destination_ipv4, IPv4Protocol protocol, size_t payload_size, u8 ttl)
|
||||
void NetworkAdapter::fill_in_ipv4_header(PacketWithTimestamp& packet, IPv4Address const& source_ipv4, MACAddress const& destination_mac, IPv4Address const& destination_ipv4, IPv4Protocol protocol, size_t payload_size, u8 type_of_service, u8 ttl)
|
||||
{
|
||||
size_t ipv4_packet_size = sizeof(IPv4Packet) + payload_size;
|
||||
VERIFY(ipv4_packet_size <= mtu());
|
||||
|
@ -62,6 +62,7 @@ void NetworkAdapter::fill_in_ipv4_header(PacketWithTimestamp& packet, IPv4Addres
|
|||
auto& ipv4 = *(IPv4Packet*)eth.payload();
|
||||
ipv4.set_version(4);
|
||||
ipv4.set_internet_header_length(5);
|
||||
ipv4.set_dscp_and_ecn(type_of_service);
|
||||
ipv4.set_source(source_ipv4);
|
||||
ipv4.set_destination(destination_ipv4);
|
||||
ipv4.set_protocol((u8)protocol);
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
void set_ipv4_gateway(const IPv4Address&);
|
||||
|
||||
void send(const MACAddress&, const ARPPacket&);
|
||||
void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8);
|
||||
void fill_in_ipv4_header(PacketWithTimestamp&, IPv4Address const&, MACAddress const&, IPv4Address const&, IPv4Protocol, size_t, u8 type_of_service, u8 ttl);
|
||||
|
||||
size_t dequeue_packet(u8* buffer, size_t buffer_size, Time& packet_timestamp);
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ void handle_icmp(EthernetFrameHeader const& eth, IPv4Packet const& ipv4_packet,
|
|||
dbgln("Could not allocate packet buffer while sending ICMP packet");
|
||||
return;
|
||||
}
|
||||
adapter->fill_in_ipv4_header(*packet, adapter->ipv4_address(), eth.source(), ipv4_packet.source(), IPv4Protocol::ICMP, icmp_packet_size, 64);
|
||||
adapter->fill_in_ipv4_header(*packet, adapter->ipv4_address(), eth.source(), ipv4_packet.source(), IPv4Protocol::ICMP, icmp_packet_size, 0, 64);
|
||||
memset(packet->buffer->data() + ipv4_payload_offset, 0, sizeof(ICMPEchoPacket));
|
||||
auto& response = *(ICMPEchoPacket*)(packet->buffer->data() + ipv4_payload_offset);
|
||||
response.header.set_type(ICMPType::EchoReply);
|
||||
|
@ -351,7 +351,7 @@ void send_tcp_rst(IPv4Packet const& ipv4_packet, TCPPacket const& tcp_packet, Re
|
|||
return;
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet, ipv4_packet.destination(),
|
||||
routing_decision.next_hop, ipv4_packet.source(), IPv4Protocol::TCP,
|
||||
buffer_size - ipv4_payload_offset, 64);
|
||||
buffer_size - ipv4_payload_offset, 0, 64);
|
||||
|
||||
auto& rst_packet = *(TCPPacket*)(packet->buffer->data() + ipv4_payload_offset);
|
||||
rst_packet = {};
|
||||
|
|
|
@ -207,7 +207,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload,
|
|||
return set_so_error(ENOMEM);
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet, local_address(),
|
||||
routing_decision.next_hop, peer_address(), IPv4Protocol::TCP,
|
||||
buffer_size - ipv4_payload_offset, ttl());
|
||||
buffer_size - ipv4_payload_offset, type_of_service(), ttl());
|
||||
memset(packet->buffer->data() + ipv4_payload_offset, 0, sizeof(TCPPacket));
|
||||
auto& tcp_packet = *(TCPPacket*)(packet->buffer->data() + ipv4_payload_offset);
|
||||
VERIFY(local_port());
|
||||
|
@ -587,7 +587,7 @@ void TCPSocket::retransmit_packets()
|
|||
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet.buffer,
|
||||
local_address(), routing_decision.next_hop, peer_address(),
|
||||
IPv4Protocol::TCP, packet_buffer.size() - ipv4_payload_offset, ttl());
|
||||
IPv4Protocol::TCP, packet_buffer.size() - ipv4_payload_offset, type_of_service(), ttl());
|
||||
routing_decision.adapter->send_packet(packet_buffer);
|
||||
m_packets_out++;
|
||||
m_bytes_out += packet_buffer.size();
|
||||
|
|
|
@ -87,7 +87,7 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_
|
|||
udp_packet.set_length(udp_buffer_size);
|
||||
SOCKET_TRY(data.read(udp_packet.payload(), data_length));
|
||||
routing_decision.adapter->fill_in_ipv4_header(*packet, local_address(), routing_decision.next_hop,
|
||||
peer_address(), IPv4Protocol::UDP, udp_buffer_size, ttl());
|
||||
peer_address(), IPv4Protocol::UDP, udp_buffer_size, type_of_service(), ttl());
|
||||
routing_decision.adapter->send_packet(packet->bytes());
|
||||
return data_length;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue