mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:57:35 +00:00
IPv4: Add simple pseudorandom ephemeral port allocators for TCP and UDP.
This commit is contained in:
parent
77a782a67e
commit
c24d4b07db
8 changed files with 54 additions and 20 deletions
|
@ -112,11 +112,15 @@ bool IPv4Socket::can_write(SocketRole) const
|
|||
return true;
|
||||
}
|
||||
|
||||
void IPv4Socket::allocate_source_port_if_needed()
|
||||
int IPv4Socket::allocate_source_port_if_needed()
|
||||
{
|
||||
if (m_source_port)
|
||||
return;
|
||||
protocol_allocate_source_port();
|
||||
return m_source_port;
|
||||
int port = protocol_allocate_source_port();
|
||||
if (port < 0)
|
||||
return port;
|
||||
m_source_port = (word)port;
|
||||
return port;
|
||||
}
|
||||
|
||||
ssize_t IPv4Socket::sendto(const void* data, size_t data_length, int flags, const sockaddr* addr, socklen_t addr_length)
|
||||
|
@ -142,7 +146,9 @@ ssize_t IPv4Socket::sendto(const void* data, size_t data_length, int flags, cons
|
|||
m_destination_port = ntohs(ia.sin_port);
|
||||
}
|
||||
|
||||
allocate_source_port_if_needed();
|
||||
int rc = allocate_source_port_if_needed();
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
kprintf("sendto: destination=%s:%u\n", m_destination_address.to_string().characters(), m_destination_port);
|
||||
|
||||
|
|
|
@ -45,12 +45,12 @@ public:
|
|||
protected:
|
||||
IPv4Socket(int type, int protocol);
|
||||
|
||||
void allocate_source_port_if_needed();
|
||||
int allocate_source_port_if_needed();
|
||||
|
||||
virtual int protocol_receive(const ByteBuffer&, void*, size_t, int, sockaddr*, socklen_t*) { return -ENOTIMPL; }
|
||||
virtual int protocol_send(const void*, int) { return -ENOTIMPL; }
|
||||
virtual KResult protocol_connect() { return KSuccess; }
|
||||
virtual void protocol_allocate_source_port() { }
|
||||
virtual int protocol_allocate_source_port() { return 0; }
|
||||
virtual bool protocol_is_disconnected() const { return false; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -16,12 +16,17 @@ RandomDevice::~RandomDevice()
|
|||
static unsigned long next = 1;
|
||||
|
||||
#define MY_RAND_MAX 32767
|
||||
static int myrand()
|
||||
int RandomDevice::random_value()
|
||||
{
|
||||
next = next * 1103515245 + 12345;
|
||||
return((unsigned)(next/((MY_RAND_MAX + 1) * 2)) % (MY_RAND_MAX + 1));
|
||||
}
|
||||
|
||||
float RandomDevice::random_percentage()
|
||||
{
|
||||
return (float)random_value() / (float)MY_RAND_MAX;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void mysrand(unsigned seed)
|
||||
{
|
||||
|
@ -39,7 +44,7 @@ ssize_t RandomDevice::read(Process&, byte* buffer, ssize_t size)
|
|||
const int range = 'z' - 'a';
|
||||
ssize_t nread = min(size, GoodBufferSize);
|
||||
for (ssize_t i = 0; i < nread; ++i) {
|
||||
dword r = myrand() % range;
|
||||
dword r = random_value() % range;
|
||||
buffer[i] = (byte)('a' + r);
|
||||
}
|
||||
return nread;
|
||||
|
|
|
@ -8,6 +8,9 @@ public:
|
|||
RandomDevice();
|
||||
virtual ~RandomDevice() override;
|
||||
|
||||
static int random_value();
|
||||
static float random_percentage();
|
||||
|
||||
private:
|
||||
// ^CharacterDevice
|
||||
virtual ssize_t read(Process&, byte*, ssize_t) override;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <Kernel/TCP.h>
|
||||
#include <Kernel/NetworkAdapter.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/RandomDevice.h>
|
||||
|
||||
Lockable<HashMap<word, TCPSocket*>>& TCPSocket::sockets_by_port()
|
||||
{
|
||||
|
@ -173,19 +174,28 @@ KResult TCPSocket::protocol_connect()
|
|||
return KSuccess;
|
||||
}
|
||||
|
||||
void TCPSocket::protocol_allocate_source_port()
|
||||
int TCPSocket::protocol_allocate_source_port()
|
||||
{
|
||||
// This is not a very efficient allocation algorithm.
|
||||
// FIXME: Replace it with a bitmap or some other fast-paced looker-upper.
|
||||
static const word first_ephemeral_port = 32768;
|
||||
static const word last_ephemeral_port = 60999;
|
||||
static const word ephemeral_port_range_size = last_ephemeral_port - first_ephemeral_port;
|
||||
word first_scan_port = first_ephemeral_port + (word)(RandomDevice::random_percentage() * ephemeral_port_range_size);
|
||||
|
||||
LOCKER(sockets_by_port().lock());
|
||||
for (word port = 2000; port < 60000; ++port) {
|
||||
for (word port = first_scan_port;;) {
|
||||
auto it = sockets_by_port().resource().find(port);
|
||||
if (it == sockets_by_port().resource().end()) {
|
||||
set_source_port(port);
|
||||
sockets_by_port().resource().set(port, this);
|
||||
return;
|
||||
return port;
|
||||
}
|
||||
++port;
|
||||
if (port > last_ephemeral_port)
|
||||
port = first_ephemeral_port;
|
||||
if (port == first_scan_port)
|
||||
break;
|
||||
}
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
||||
bool TCPSocket::protocol_is_disconnected() const
|
||||
|
|
|
@ -35,7 +35,7 @@ private:
|
|||
virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags, sockaddr* addr, socklen_t* addr_length) override;
|
||||
virtual int protocol_send(const void*, int) override;
|
||||
virtual KResult protocol_connect() override;
|
||||
virtual void protocol_allocate_source_port() override;
|
||||
virtual int protocol_allocate_source_port() override;
|
||||
virtual bool protocol_is_disconnected() const override;
|
||||
|
||||
dword m_sequence_number { 0 };
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <Kernel/UDP.h>
|
||||
#include <Kernel/NetworkAdapter.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/RandomDevice.h>
|
||||
|
||||
Lockable<HashMap<word, UDPSocket*>>& UDPSocket::sockets_by_port()
|
||||
{
|
||||
|
@ -83,17 +84,26 @@ KResult UDPSocket::protocol_connect()
|
|||
return KSuccess;
|
||||
}
|
||||
|
||||
void UDPSocket::protocol_allocate_source_port()
|
||||
int UDPSocket::protocol_allocate_source_port()
|
||||
{
|
||||
// This is not a very efficient allocation algorithm.
|
||||
// FIXME: Replace it with a bitmap or some other fast-paced looker-upper.
|
||||
static const word first_ephemeral_port = 32768;
|
||||
static const word last_ephemeral_port = 60999;
|
||||
static const word ephemeral_port_range_size = last_ephemeral_port - first_ephemeral_port;
|
||||
word first_scan_port = first_ephemeral_port + (word)(RandomDevice::random_percentage() * ephemeral_port_range_size);
|
||||
|
||||
LOCKER(sockets_by_port().lock());
|
||||
for (word port = 2000; port < 60000; ++port) {
|
||||
for (word port = first_scan_port;;) {
|
||||
auto it = sockets_by_port().resource().find(port);
|
||||
if (it == sockets_by_port().resource().end()) {
|
||||
set_source_port(port);
|
||||
sockets_by_port().resource().set(port, this);
|
||||
return;
|
||||
return port;
|
||||
}
|
||||
++port;
|
||||
if (port > last_ephemeral_port)
|
||||
port = first_ephemeral_port;
|
||||
if (port == first_scan_port)
|
||||
break;
|
||||
}
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ private:
|
|||
virtual int protocol_receive(const ByteBuffer&, void* buffer, size_t buffer_size, int flags, sockaddr* addr, socklen_t* addr_length) override;
|
||||
virtual int protocol_send(const void*, int) override;
|
||||
virtual KResult protocol_connect() override;
|
||||
virtual void protocol_allocate_source_port() override;
|
||||
virtual int protocol_allocate_source_port() override;
|
||||
};
|
||||
|
||||
class UDPSocketHandle : public SocketHandle {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue