Explorar o código

Kernel: Implement the SO_DONTROUTE SOL_SOCKET-level option

Idan Horowitz %!s(int64=3) %!d(string=hai) anos
pai
achega
613ade9dec
Modificáronse 4 ficheiros con 20 adicións e 2 borrados
  1. 2 0
      Kernel/API/POSIX/sys/socket.h
  2. 1 1
      Kernel/Net/IPv4Socket.cpp
  3. 16 0
      Kernel/Net/Socket.cpp
  4. 1 1
      Kernel/Net/Socket.h

+ 2 - 0
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,

+ 1 - 1
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);

+ 16 - 0
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;

+ 1 - 1
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; }