summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/API/POSIX/sys/socket.h2
-rw-r--r--Kernel/Net/IPv4Socket.cpp2
-rw-r--r--Kernel/Net/Socket.cpp16
-rw-r--r--Kernel/Net/Socket.h2
4 files changed, 20 insertions, 2 deletions
diff --git a/Kernel/API/POSIX/sys/socket.h b/Kernel/API/POSIX/sys/socket.h
index c32dc92c34..9dce41f43f 100644
--- a/Kernel/API/POSIX/sys/socket.h
+++ b/Kernel/API/POSIX/sys/socket.h
@@ -109,6 +109,7 @@ enum {
SO_BROADCAST,
SO_LINGER,
SO_ACCEPTCONN,
+ SO_DONTROUTE,
};
#define SO_RCVTIMEO SO_RCVTIMEO
#define SO_SNDTIMEO SO_SNDTIMEO
@@ -125,6 +126,7 @@ enum {
#define SO_RCVBUF SO_RCVBUF
#define SO_LINGER SO_LINGER
#define SO_ACCEPTCONN SO_ACCEPTCONN
+#define SO_DONTROUTE SO_DONTROUTE
enum {
SCM_TIMESTAMP,
diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp
index 1b0445d94a..fb0a19052a 100644
--- a/Kernel/Net/IPv4Socket.cpp
+++ b/Kernel/Net/IPv4Socket.cpp
@@ -210,7 +210,7 @@ ErrorOr<size_t> IPv4Socket::sendto(OpenFileDescription&, const UserOrKernelBuffe
if (!is_connected() && m_peer_address.is_zero())
return set_so_error(EPIPE);
- auto allow_using_gateway = (flags & MSG_DONTROUTE) ? AllowUsingGateway::No : AllowUsingGateway::Yes;
+ auto allow_using_gateway = ((flags & MSG_DONTROUTE) || m_routing_disabled) ? AllowUsingGateway::No : AllowUsingGateway::Yes;
auto routing_decision = route_to(m_peer_address, m_local_address, bound_interface(), allow_using_gateway);
if (routing_decision.is_zero())
return set_so_error(EHOSTUNREACH);
diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp
index da99bfd724..b3187c585e 100644
--- a/Kernel/Net/Socket.cpp
+++ b/Kernel/Net/Socket.cpp
@@ -123,6 +123,14 @@ ErrorOr<void> Socket::setsockopt(int level, int option, Userspace<const void*> u
return ENOTSUP;
}
return {};
+ case SO_DONTROUTE: {
+ int routing_disabled;
+ if (user_value_size != sizeof(routing_disabled))
+ return EINVAL;
+ TRY(copy_from_user(&routing_disabled, static_ptr_cast<const int*>(user_value)));
+ m_routing_disabled = routing_disabled != 0;
+ return {};
+ }
default:
dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option);
return ENOPROTOOPT;
@@ -216,6 +224,14 @@ ErrorOr<void> Socket::getsockopt(OpenFileDescription&, int level, int option, Us
size = sizeof(accepting_connections);
return copy_to_user(value_size, &size);
}
+ case SO_DONTROUTE: {
+ int routing_disabled = m_routing_disabled ? 1 : 0;
+ if (size < sizeof(routing_disabled))
+ return EINVAL;
+ TRY(copy_to_user(static_ptr_cast<int*>(value), &routing_disabled));
+ size = sizeof(routing_disabled);
+ return copy_to_user(value_size, &size);
+ }
default:
dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option);
return ENOPROTOOPT;
diff --git a/Kernel/Net/Socket.h b/Kernel/Net/Socket.h
index b7d069c6bf..e3cff41cb4 100644
--- a/Kernel/Net/Socket.h
+++ b/Kernel/Net/Socket.h
@@ -154,9 +154,9 @@ protected:
void set_role(Role role) { m_role = role; }
-protected:
ucred m_origin { 0, 0, 0 };
ucred m_acceptor { 0, 0, 0 };
+ bool m_routing_disabled { false };
private:
virtual bool is_socket() const final { return true; }