From a9c8f705fb4702ed153bcc79f5d53f83a0799805 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <vital.had@gmail.com>
Date: Wed, 29 Jan 2025 20:58:12 +0800
Subject: [PATCH] Hack it to compile for now

---
 llarp/vpn/apple.hpp | 87 +++++++++++++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 30 deletions(-)

diff --git llarp/vpn/apple.hpp llarp/vpn/apple.hpp
index f20c50ce3..0f3bdb51d 100644
--- llarp/vpn/apple.hpp
+++ llarp/vpn/apple.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <llarp/ev/vpn.hpp>
+#include "platform.hpp"
 #include "common.hpp"
 
 #include <sys/kern_control.h>
@@ -34,30 +34,28 @@
 {
   class AppleInterface : public NetworkInterface
   {
-    const int m_FD;
-    const InterfaceInfo m_Info;
+    const int m_fd;
     std::string m_IfName;
 
     static void
     Exec(std::string cmd)
     {
-      LogDebug(cmd);
       system(cmd.c_str());
     }
 
    public:
     AppleInterface(InterfaceInfo info)
-        : m_FD{::socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL)}, m_Info{std::move(info)}
+        : NetworkInterface{std::move(info)}, m_fd{::socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL)}
     {
-      if (m_FD == -1)
+      if (m_fd == -1)
         throw std::invalid_argument{"cannot open control socket: " + std::string{strerror(errno)}};
 
       ctl_info cinfo{};
       const std::string apple_utun = "com.apple.net.utun_control";
       std::copy_n(apple_utun.c_str(), apple_utun.size(), cinfo.ctl_name);
-      if (::ioctl(m_FD, CTLIOCGINFO, &cinfo) < 0)
+      if (::ioctl(m_fd, CTLIOCGINFO, &cinfo) < 0)
       {
-        ::close(m_FD);
+        ::close(m_fd);
         throw std::runtime_error{"ioctl CTLIOCGINFO call failed: " + std::string{strerror(errno)}};
       }
       sockaddr_ctl addr{};
@@ -68,21 +66,28 @@
       addr.ss_sysaddr = AF_SYS_CONTROL;
       addr.sc_unit = 0;
 
-      if (connect(m_FD, (sockaddr*)&addr, sizeof(addr)) < 0)
+      if (connect(m_fd, (sockaddr*)&addr, sizeof(addr)) < 0)
       {
-        ::close(m_FD);
+        ::close(m_fd);
         throw std::runtime_error{
             "cannot connect to control socket address: " + std::string{strerror(errno)}};
       }
       uint32_t namesz = IFNAMSIZ;
       char name[IFNAMSIZ + 1]{};
-      if (getsockopt(m_FD, SYSPROTO_CONTROL, 2, name, &namesz) < 0)
+      if (getsockopt(m_fd, SYSPROTO_CONTROL, 2, name, &namesz) < 0)
       {
-        ::close(m_FD);
+        ::close(m_fd);
         throw std::runtime_error{
             "cannot query for interface name: " + std::string{strerror(errno)}};
       }
       m_IfName = name;
+      int flags = ::fcntl(m_fd, F_GETFL, 0);
+      if (flags == -1 || ::fcntl(m_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+      {
+        ::close(m_fd);
+        throw std::runtime_error{
+        "cannot set non-blocking on utun fd: " + std::string{strerror(errno)}};
+      }
       for (const auto& ifaddr : m_Info.addrs)
       {
         if (ifaddr.fam == AF_INET)
@@ -107,38 +112,34 @@
 
     ~AppleInterface()
     {
-      ::close(m_FD);
-    }
-
-    std::string
-    IfName() const override
-    {
-      return m_IfName;
+      ::close(m_fd);
     }
 
     int
     PollFD() const override
     {
-      return m_FD;
+      return m_fd;
     }
 
     net::IPPacket
     ReadNextPacket() override
     {
       constexpr int uintsize = sizeof(unsigned int);
-      net::IPPacket pkt{};
       unsigned int pktinfo = 0;
+      std::vector<byte_t> buf(net::IPPacket::MaxSize);
       const struct iovec vecs[2] = {
           {.iov_base = &pktinfo, .iov_len = uintsize},
-          {.iov_base = pkt.buf, .iov_len = sizeof(pkt.buf)}};
-      int sz = readv(m_FD, vecs, 2);
+          {.iov_base = buf.data(), .iov_len = buf.size()}
+      };
+      int sz = readv(m_fd, vecs, 2);
       if (sz >= uintsize)
-        pkt.sz = sz - uintsize;
+        sz -= sizeof(unsigned int);
       else if (sz >= 0 || errno == EAGAIN || errno == EWOULDBLOCK)
-        pkt.sz = 0;
+        sz = 0;
       else
         throw std::error_code{errno, std::system_category()};
-      return pkt;
+      buf.resize(static_cast<size_t>(sz));
+      return net::IPPacket{std::move(buf)};
     }
 
     bool
@@ -149,25 +150,59 @@
 
       const struct iovec vecs[2] = {
           {.iov_base = pkt.IsV6() ? &af6 : &af4, .iov_len = sizeof(unsigned int)},
-          {.iov_base = pkt.buf, .iov_len = pkt.sz}};
+          {.iov_base = pkt.data(), .iov_len = pkt.size()}
+        };
 
-      ssize_t n = writev(m_FD, vecs, 2);
-      if (n >= (int)sizeof(unsigned int))
+      ssize_t sz = writev(m_fd, vecs, 2);
+      if (sz >= (int)sizeof(unsigned int))
       {
-        n -= sizeof(unsigned int);
-        return static_cast<size_t>(n) == pkt.sz;
+        sz -= sizeof(unsigned int);
+        return static_cast<size_t>(sz) == pkt.size();
       }
       return false;
     }
   };
 
+  class AppleRouteManager : public IRouteManager
+  {
+    void AddRoute(net::ipaddr_t, net::ipaddr_t) override{};
+
+    void DelRoute(net::ipaddr_t, net::ipaddr_t) override{};
+
+    void
+    AddDefaultRouteViaInterface(NetworkInterface&) override{};
+
+    void
+    DelDefaultRouteViaInterface(NetworkInterface&) override{};
+
+    void
+    AddRouteViaInterface(NetworkInterface&, IPRange) override{};
+
+    void
+    DelRouteViaInterface(NetworkInterface&, IPRange) override{};
+
+    std::vector<net::ipaddr_t>
+    GetGatewaysNotOnInterface(NetworkInterface&) override
+    {
+      return std::vector<net::ipaddr_t>{};
+    };
+  };
+
   class ApplePlatform : public Platform
   {
+    AppleRouteManager _routeManager{};
+
    public:
     std::shared_ptr<NetworkInterface>
-    ObtainInterface(InterfaceInfo info) override
+    ObtainInterface(InterfaceInfo info, AbstractRouter*) override
     {
       return std::make_shared<AppleInterface>(std::move(info));
+    };
+
+    IRouteManager&
+    RouteManager() override
+    {
+      return _routeManager;
     }
   };
 }  // namespace llarp::vpn
