mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-28 23:39:02 +00:00
IPv4: Begin fleshing out TCP support.
This commit is contained in:
parent
ef5d0a397c
commit
c588653f76
Notes:
sideshowbarker
2024-07-19 15:04:02 +09:00
Author: https://github.com/awesomekling
Commit: c588653f76
4 changed files with 112 additions and 6 deletions
|
@ -93,7 +93,11 @@ KResult IPv4Socket::connect(const sockaddr* address, socklen_t address_size)
|
||||||
if (address->sa_family != AF_INET)
|
if (address->sa_family != AF_INET)
|
||||||
return KResult(-EINVAL);
|
return KResult(-EINVAL);
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
auto& ia = *(const sockaddr_in*)address;
|
||||||
|
m_destination_address = IPv4Address((const byte*)&ia.sin_addr.s_addr);
|
||||||
|
m_destination_port = ntohs(ia.sin_port);
|
||||||
|
|
||||||
|
return KSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPv4Socket::attach_fd(SocketRole)
|
void IPv4Socket::attach_fd(SocketRole)
|
||||||
|
@ -177,9 +181,11 @@ ssize_t IPv4Socket::sendto(const void* data, size_t data_length, int flags, cons
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& ia = *(const sockaddr_in*)addr;
|
if (addr) {
|
||||||
m_destination_address = IPv4Address((const byte*)&ia.sin_addr.s_addr);
|
auto& ia = *(const sockaddr_in*)addr;
|
||||||
m_destination_port = ntohs(ia.sin_port);
|
m_destination_address = IPv4Address((const byte*)&ia.sin_addr.s_addr);
|
||||||
|
m_destination_port = ntohs(ia.sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
allocate_source_port_if_needed();
|
allocate_source_port_if_needed();
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Kernel/ARP.h>
|
#include <Kernel/ARP.h>
|
||||||
#include <Kernel/ICMP.h>
|
#include <Kernel/ICMP.h>
|
||||||
#include <Kernel/UDP.h>
|
#include <Kernel/UDP.h>
|
||||||
|
#include <Kernel/TCP.h>
|
||||||
#include <Kernel/IPv4.h>
|
#include <Kernel/IPv4.h>
|
||||||
#include <Kernel/IPv4Socket.h>
|
#include <Kernel/IPv4Socket.h>
|
||||||
#include <Kernel/Process.h>
|
#include <Kernel/Process.h>
|
||||||
|
@ -10,14 +11,16 @@
|
||||||
#include <AK/Lock.h>
|
#include <AK/Lock.h>
|
||||||
|
|
||||||
//#define ETHERNET_DEBUG
|
//#define ETHERNET_DEBUG
|
||||||
//#define IPV4_DEBUG
|
#define IPV4_DEBUG
|
||||||
//#define ICMP_DEBUG
|
//#define ICMP_DEBUG
|
||||||
#define UDP_DEBUG
|
#define UDP_DEBUG
|
||||||
|
#define TCP_DEBUG
|
||||||
|
|
||||||
static void handle_arp(const EthernetFrameHeader&, int frame_size);
|
static void handle_arp(const EthernetFrameHeader&, int frame_size);
|
||||||
static void handle_ipv4(const EthernetFrameHeader&, int frame_size);
|
static void handle_ipv4(const EthernetFrameHeader&, int frame_size);
|
||||||
static void handle_icmp(const EthernetFrameHeader&, int frame_size);
|
static void handle_icmp(const EthernetFrameHeader&, int frame_size);
|
||||||
static void handle_udp(const EthernetFrameHeader&, int frame_size);
|
static void handle_udp(const EthernetFrameHeader&, int frame_size);
|
||||||
|
static void handle_tcp(const EthernetFrameHeader&, int frame_size);
|
||||||
|
|
||||||
Lockable<HashMap<IPv4Address, MACAddress>>& arp_table()
|
Lockable<HashMap<IPv4Address, MACAddress>>& arp_table()
|
||||||
{
|
{
|
||||||
|
@ -152,6 +155,8 @@ void handle_ipv4(const EthernetFrameHeader& eth, int frame_size)
|
||||||
return handle_icmp(eth, frame_size);
|
return handle_icmp(eth, frame_size);
|
||||||
case IPv4Protocol::UDP:
|
case IPv4Protocol::UDP:
|
||||||
return handle_udp(eth, frame_size);
|
return handle_udp(eth, frame_size);
|
||||||
|
case IPv4Protocol::TCP:
|
||||||
|
return handle_tcp(eth, frame_size);
|
||||||
default:
|
default:
|
||||||
kprintf("handle_ipv4: Unhandled protocol %u\n", packet.protocol());
|
kprintf("handle_ipv4: Unhandled protocol %u\n", packet.protocol());
|
||||||
break;
|
break;
|
||||||
|
@ -244,3 +249,44 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
ASSERT(socket->source_port() == udp_packet.destination_port());
|
ASSERT(socket->source_port() == udp_packet.destination_port());
|
||||||
socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_tcp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
|
{
|
||||||
|
(void)frame_size;
|
||||||
|
auto& ipv4_packet = *static_cast<const IPv4Packet*>(eth.payload());
|
||||||
|
|
||||||
|
auto* adapter = NetworkAdapter::from_ipv4_address(ipv4_packet.destination());
|
||||||
|
if (!adapter) {
|
||||||
|
kprintf("handle_tcp: this packet is not for me, it's for %s\n", ipv4_packet.destination().to_string().characters());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& tcp_packet = *static_cast<const TCPPacket*>(ipv4_packet.payload());
|
||||||
|
#ifdef TCP_DEBUG
|
||||||
|
kprintf("handle_tcp: source=%s:%u, destination=%s:%u seq=%u, ack=%u, flags=%w, window_size=%u\n",
|
||||||
|
ipv4_packet.source().to_string().characters(),
|
||||||
|
tcp_packet.source_port(),
|
||||||
|
ipv4_packet.destination().to_string().characters(),
|
||||||
|
tcp_packet.destination_port(),
|
||||||
|
tcp_packet.sequence_number(),
|
||||||
|
tcp_packet.ack_number(),
|
||||||
|
tcp_packet.flags(),
|
||||||
|
tcp_packet.window_size()
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RetainPtr<IPv4Socket> socket;
|
||||||
|
{
|
||||||
|
LOCKER(IPv4Socket::sockets_by_tcp_port().lock());
|
||||||
|
auto it = IPv4Socket::sockets_by_tcp_port().resource().find(tcp_packet.destination_port());
|
||||||
|
if (it == IPv4Socket::sockets_by_tcp_port().resource().end())
|
||||||
|
return;
|
||||||
|
ASSERT((*it).value);
|
||||||
|
socket = *(*it).value;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCKER(socket->lock());
|
||||||
|
ASSERT(socket->type() == SOCK_STREAM);
|
||||||
|
ASSERT(socket->source_port() == tcp_packet.destination_port());
|
||||||
|
socket->did_receive(ByteBuffer::copy((const byte*)&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
|
}
|
||||||
|
|
49
Kernel/TCP.h
Normal file
49
Kernel/TCP.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Kernel/IPv4.h>
|
||||||
|
|
||||||
|
class [[gnu::packed]] TCPPacket {
|
||||||
|
public:
|
||||||
|
TCPPacket() { }
|
||||||
|
~TCPPacket() { }
|
||||||
|
|
||||||
|
word source_port() const { return m_source_port; }
|
||||||
|
void set_source_port(word port) { m_source_port = port; }
|
||||||
|
|
||||||
|
word destination_port() const { return m_destination_port; }
|
||||||
|
void set_destination_port(word port) { m_destination_port = port; }
|
||||||
|
|
||||||
|
dword sequence_number() const { return m_sequence_number; }
|
||||||
|
void set_sequence_number(dword number) { m_sequence_number = number; }
|
||||||
|
|
||||||
|
dword ack_number() const { return m_ack_number; }
|
||||||
|
void set_ack_number(dword number) { m_ack_number = number; }
|
||||||
|
|
||||||
|
word flags() const { return m_flags; }
|
||||||
|
void set_flags(word flags) { m_flags = flags; }
|
||||||
|
|
||||||
|
word window_size() const { return m_window_size; }
|
||||||
|
void set_window_size(word window_size) { m_window_size = window_size; }
|
||||||
|
|
||||||
|
word checksum() const { return m_checksum; }
|
||||||
|
void set_checksum(word checksum) { m_checksum = checksum; }
|
||||||
|
|
||||||
|
word urgent() const { return m_urgent; }
|
||||||
|
void set_urgent(word urgent) { m_urgent = urgent; }
|
||||||
|
|
||||||
|
const void* payload() const { return this + 1; }
|
||||||
|
void* payload() { return this + 1; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NetworkOrdered<word> m_source_port;
|
||||||
|
NetworkOrdered<word> m_destination_port;
|
||||||
|
NetworkOrdered<dword> m_sequence_number;
|
||||||
|
NetworkOrdered<dword> m_ack_number;
|
||||||
|
|
||||||
|
NetworkOrdered<word> m_flags;
|
||||||
|
NetworkOrdered<word> m_window_size;
|
||||||
|
NetworkOrdered<word> m_checksum;
|
||||||
|
NetworkOrdered<word> m_urgent;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(UDPPacket) == 8);
|
|
@ -11,6 +11,11 @@ elif [ "$1" = "qtap" ]; then
|
||||||
sudo qemu-system-i386 -s -m 32 -object filter-dump,id=hue,netdev=br0,file=e1000.pcap -netdev tap,ifname=tap0,id=br0 -device e1000,netdev=br0 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents
|
sudo qemu-system-i386 -s -m 32 -object filter-dump,id=hue,netdev=br0,file=e1000.pcap -netdev tap,ifname=tap0,id=br0 -device e1000,netdev=br0 -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents
|
||||||
else
|
else
|
||||||
# ./run: qemu with user networking
|
# ./run: qemu with user networking
|
||||||
qemu-system-i386 -s -m 32 -object filter-dump,id=hue,netdev=breh,file=e1000.pcap -netdev user,id=breh -device e1000,netdev=breh -drive format=raw,file=.floppy-image,if=floppy -drive format=raw,file=_fs_contents
|
qemu-system-i386 -s -m 32 \
|
||||||
|
-object filter-dump,id=hue,netdev=breh,file=e1000.pcap \
|
||||||
|
-netdev user,id=breh,hostfwd=tcp:127.0.0.1:8888-192.168.5.2:8888 \
|
||||||
|
-device e1000,netdev=breh \
|
||||||
|
-drive format=raw,file=.floppy-image,if=floppy \
|
||||||
|
-drive format=raw,file=_fs_contents
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue