summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/netdev/taptun.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/netdev/taptun.cpp')
-rw-r--r--src/osd/modules/netdev/taptun.cpp170
1 files changed, 104 insertions, 66 deletions
diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp
index 91ca323a178..b765a667ae7 100644
--- a/src/osd/modules/netdev/taptun.cpp
+++ b/src/osd/modules/netdev/taptun.cpp
@@ -1,8 +1,23 @@
// license:BSD-3-Clause
// copyright-holders:Carl
+#include "netdev_module.h"
+
+#include "modules/osdmodule.h"
+
#if defined(OSD_NET_USE_TAPTUN)
-#if defined(WIN32)
+#include "netdev_common.h"
+
+#include "osdcore.h" // osd_printf_verbose
+#include "osdfile.h" // PATH_SEPARATOR
+
+#include "util/hashing.h" // crc32_creator
+#include "util/unicode.h"
+
+#include <memory>
+#include <vector>
+
+#if defined(_WIN32)
#include <windows.h>
#include <winioctl.h>
#else
@@ -10,19 +25,14 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/if.h>
-#include <errno.h>
+#include <cerrno>
#endif
-#include "emu.h"
-#include "osdnet.h"
-#include "modules/osdmodule.h"
-#include "netdev_module.h"
-
#ifdef __linux__
#define IFF_TAP 0x0002
#define IFF_NO_PI 0x1000
#define TUNSETIFF _IOW('T', 202, int)
-#elif defined(WIN32)
+#elif defined(_WIN32)
#include "tap-windows6/tap-windows.h"
// for some reason this isn't defined in the header, and presumably it changes
@@ -30,6 +40,10 @@
#define PRODUCT_TAP_WIN_COMPONENT_ID "tap0901"
#endif
+namespace osd {
+
+namespace {
+
// Ethernet minimum frame length
static constexpr int ETHERNET_MIN_FRAME = 64;
@@ -42,26 +56,39 @@ public:
}
virtual ~taptun_module() { }
- virtual int init(const osd_options &options);
- virtual void exit();
+ virtual int init(osd_interface &osd, const osd_options &options) override;
+ virtual void exit() override;
+
+ virtual bool probe() override { return true; }
+
+ virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override;
+ virtual std::vector<network_device_info> list_devices() override;
+
+private:
+ struct device_info
+ {
+ std::string name;
+ std::string description;
+ };
- virtual bool probe() { return true; }
+ std::vector<device_info> m_devices;
};
-class netdev_tap : public osd_netdev
+class netdev_tap : public network_device_base
{
public:
- netdev_tap(const char *name, class device_network_interface *ifdev, int rate);
+ netdev_tap(const char *name, network_handler &handler);
~netdev_tap();
- int send(uint8_t *buf, int len) override;
- void set_mac(const char *mac) override;
+ int send(void const *buf, int len) override;
+
protected:
int recv_dev(uint8_t **buf) override;
+
private:
-#if defined(WIN32)
+#if defined(_WIN32)
HANDLE m_handle = INVALID_HANDLE_VALUE;
OVERLAPPED m_overlapped;
bool m_receive_pending;
@@ -69,22 +96,20 @@ private:
int m_fd = -1;
char m_ifname[10];
#endif
- char m_mac[6];
uint8_t m_buf[2048];
};
-netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate)
- : osd_netdev(ifdev, rate)
+netdev_tap::netdev_tap(const char *name, network_handler &handler)
+ : network_device_base(handler)
{
-#ifdef __linux__
- struct ifreq ifr;
-
+#if defined(__linux__)
m_fd = -1;
if((m_fd = open("/dev/net/tun", O_RDWR)) == -1) {
osd_printf_verbose("tap: open failed %d\n", errno);
return;
}
+ struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
sprintf(ifr.ifr_name, "tap-mess-%d-0", getuid());
@@ -97,7 +122,7 @@ netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev,
osd_printf_verbose("netdev_tap: network up!\n");
strncpy(m_ifname, ifr.ifr_name, 10);
fcntl(m_fd, F_SETFL, O_NONBLOCK);
-#elif defined(WIN32)
+#elif defined(_WIN32)
std::wstring device_path(L"" USERMODEDEVICEDIR);
device_path.append(wstring_from_utf8(name));
device_path.append(L"" TAP_WIN_SUFFIX);
@@ -120,7 +145,7 @@ netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev,
netdev_tap::~netdev_tap()
{
-#if defined(WIN32)
+#if defined(_WIN32)
if (m_handle != INVALID_HANDLE_VALUE)
{
if (m_receive_pending)
@@ -133,11 +158,6 @@ netdev_tap::~netdev_tap()
#endif
}
-void netdev_tap::set_mac(const char *mac)
-{
- memcpy(m_mac, mac, 6);
-}
-
static u32 finalise_frame(u8 buf[], u32 length)
{
/*
@@ -168,8 +188,8 @@ static u32 finalise_frame(u8 buf[], u32 length)
return length;
}
-#if defined(WIN32)
-int netdev_tap::send(uint8_t *buf, int len)
+#if defined(_WIN32)
+int netdev_tap::send(void const *buf, int len)
{
OVERLAPPED overlapped = {};
@@ -233,7 +253,7 @@ static std::wstring safe_string(WCHAR value[], int length)
}
// find the friendly name for an adapter in the registry
-static std::wstring get_connection_name(std::wstring &id)
+static std::wstring get_connection_name(std::wstring const &id)
{
std::wstring result;
@@ -285,16 +305,21 @@ static std::vector<std::wstring> get_tap_adapters()
// check if the ComponentId value indicates a TAP-Windows adapter
if (RegQueryValueExW(unit_key, L"ComponentId", NULL, &data_type, LPBYTE(component_id), &component_id_len) == ERROR_SUCCESS
- && data_type == REG_SZ
- && safe_string(component_id, component_id_len) == L"" PRODUCT_TAP_WIN_COMPONENT_ID)
+ && data_type == REG_SZ)
{
- WCHAR net_cfg_instance_id[MAX_PATH];
- DWORD net_cfg_instance_id_len = sizeof(net_cfg_instance_id);
-
- // add the adapter to the result
- if (RegQueryValueExW(unit_key, L"NetCfgInstanceId", NULL, &data_type, LPBYTE(net_cfg_instance_id), &net_cfg_instance_id_len) == ERROR_SUCCESS
- && data_type == REG_SZ)
- result.push_back(safe_string(net_cfg_instance_id, net_cfg_instance_id_len));
+ std::wstring const value(safe_string(component_id, component_id_len));
+
+ // some older versions may not set the "root\" prefix
+ if (value == L"root\\" PRODUCT_TAP_WIN_COMPONENT_ID || value == L"" PRODUCT_TAP_WIN_COMPONENT_ID)
+ {
+ WCHAR net_cfg_instance_id[MAX_PATH];
+ DWORD net_cfg_instance_id_len = sizeof(net_cfg_instance_id);
+
+ // add the adapter to the result
+ if (RegQueryValueExW(unit_key, L"NetCfgInstanceId", NULL, &data_type, LPBYTE(net_cfg_instance_id), &net_cfg_instance_id_len) == ERROR_SUCCESS
+ && data_type == REG_SZ)
+ result.push_back(safe_string(net_cfg_instance_id, net_cfg_instance_id_len));
+ }
}
RegCloseKey(unit_key);
@@ -310,7 +335,7 @@ static std::vector<std::wstring> get_tap_adapters()
return result;
}
#else
-int netdev_tap::send(uint8_t *buf, int len)
+int netdev_tap::send(void const *buf, int len)
{
if(m_fd == -1) return 0;
len = write(m_fd, buf, len);
@@ -319,51 +344,64 @@ int netdev_tap::send(uint8_t *buf, int len)
int netdev_tap::recv_dev(uint8_t **buf)
{
- int len;
- if(m_fd == -1) return 0;
- // exit if we didn't receive anything, got an error, got a broadcast or multicast packet,
- // are in promiscuous mode or got a packet with our mac.
- do {
- len = read(m_fd, m_buf, sizeof(m_buf));
- } while((len > 0) && memcmp(get_mac(), m_buf, 6) && !get_promisc() && !(m_buf[0] & 1));
+ if (0 > m_fd)
+ return 0;
+
+ int len = read(m_fd, m_buf, sizeof(m_buf));
if (len > 0)
len = finalise_frame(m_buf, len);
*buf = m_buf;
- return (len == -1)?0:len;
+ return (len == -1) ? 0 : len;
}
#endif
-static CREATE_NETDEV(create_tap)
-{
- class netdev_tap *dev = global_alloc(netdev_tap(ifname, ifdev, rate));
- return dynamic_cast<osd_netdev *>(dev);
-}
-
-int taptun_module::init(const osd_options &options)
+int taptun_module::init(osd_interface &osd, const osd_options &options)
{
-#if defined(WIN32)
- for (std::wstring &id : get_tap_adapters())
- add_netdev(utf8_from_wstring(id).c_str(), utf8_from_wstring(get_connection_name(id)).c_str(), create_tap);
+#if defined(_WIN32)
+ auto const adapters = get_tap_adapters();
+ m_devices.reserve(adapters.size());
+ for (std::wstring const &id : adapters)
+ m_devices.emplace_back(device_info{ utf8_from_wstring(id), utf8_from_wstring(get_connection_name(id)) });
#else
- add_netdev("tap", "TAP/TUN Device", create_tap);
+ m_devices.emplace_back(device_info{ "tap", "TUN/TAP Device" });
#endif
return 0;
}
void taptun_module::exit()
{
- clear_netdev();
+ m_devices.clear();
}
+std::unique_ptr<network_device> taptun_module::open_device(int id, network_handler &handler)
+{
+ if ((0 > id) || (m_devices.size() <= id))
+ return nullptr;
+
+ return std::make_unique<netdev_tap>(m_devices[id].name.c_str(), handler);
+}
+
+std::vector<network_device_info> taptun_module::list_devices()
+{
+ std::vector<network_device_info> result;
+ result.reserve(m_devices.size());
+ for (int id = 0; m_devices.size() > id; ++id)
+ result.emplace_back(network_device_info{ id, m_devices[id].description });
+ return result;
+}
+
+} // anonymous namespace
+
+} // namespace osd
+
#else
- #include "modules/osdmodule.h"
- #include "netdev_module.h"
- MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun")
+namespace osd { namespace { MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun") } }
+
#endif
-MODULE_DEFINITION(NETDEV_TAPTUN, taptun_module)
+MODULE_DEFINITION(NETDEV_TAPTUN, osd::taptun_module)