diff options
Diffstat (limited to 'src/osd/modules/netdev')
-rw-r--r-- | src/osd/modules/netdev/netdev_common.cpp | 39 | ||||
-rw-r--r-- | src/osd/modules/netdev/netdev_common.h | 36 | ||||
-rw-r--r-- | src/osd/modules/netdev/netdev_module.h | 23 | ||||
-rw-r--r-- | src/osd/modules/netdev/none.cpp | 35 | ||||
-rw-r--r-- | src/osd/modules/netdev/pcap.cpp | 248 | ||||
-rw-r--r-- | src/osd/modules/netdev/taptun.cpp | 170 |
6 files changed, 355 insertions, 196 deletions
diff --git a/src/osd/modules/netdev/netdev_common.cpp b/src/osd/modules/netdev/netdev_common.cpp new file mode 100644 index 00000000000..b6a2328c7a6 --- /dev/null +++ b/src/osd/modules/netdev/netdev_common.cpp @@ -0,0 +1,39 @@ +// license:BSD-3-Clause +// copyright-holders:Carl + +#include "netdev_common.h" + + +namespace osd { + +network_device_base::network_device_base(network_handler &handler) + : m_handler(handler) + , m_stopped(true) +{ +} + +network_device_base::~network_device_base() +{ +} + +void network_device_base::start() +{ + m_stopped = false; +} + +void network_device_base::stop() +{ + m_stopped = true; +} + +void network_device_base::poll() +{ + uint8_t *buf; + int len; + while (!m_stopped && (len = recv_dev(&buf))) + { + m_handler.recv_cb(buf, len); + } +} + +} // namespace osd diff --git a/src/osd/modules/netdev/netdev_common.h b/src/osd/modules/netdev/netdev_common.h new file mode 100644 index 00000000000..95d961a438a --- /dev/null +++ b/src/osd/modules/netdev/netdev_common.h @@ -0,0 +1,36 @@ +// license:BSD-3-Clause +// copyright-holders:Carl +#ifndef MAME_OSD_NETDEV_NETDEV_COMMON_H +#define MAME_OSD_NETDEV_NETDEV_COMMON_H + +#pragma once + +#include "interface/nethandler.h" + +#include <cstdint> + + +namespace osd { + +class network_device_base : public network_device +{ +public: + virtual ~network_device_base(); + + virtual void start() override; + virtual void stop() override; + virtual void poll() override; + +protected: + network_device_base(network_handler &handler); + + virtual int recv_dev(uint8_t **buf) = 0; + +private: + network_handler &m_handler; + bool m_stopped; +}; + +} // namespace osd + +#endif // MAME_OSD_NETDEV_NETDEV_COMMON_H diff --git a/src/osd/modules/netdev/netdev_module.h b/src/osd/modules/netdev/netdev_module.h index b1d537cacf5..3636c3a23cb 100644 --- a/src/osd/modules/netdev/netdev_module.h +++ b/src/osd/modules/netdev/netdev_module.h @@ -4,25 +4,30 @@ * netdev_module.h * */ +#ifndef MAME_OSD_NETDEV_NETDEV_MODULE_H +#define MAME_OSD_NETDEV_NETDEV_MODULE_H -#ifndef NETDEV_MODULE_H_ -#define NETDEV_MODULE_H_ +#pragma once + +#include "interface/nethandler.h" + +#include <memory> +#include <vector> -#include "osdepend.h" -#include "modules/osdmodule.h" //============================================================ // CONSTANTS //============================================================ -#define OSD_NETDEV_PROVIDER "netdevprovider" +#define OSD_NETDEV_PROVIDER "networkprovider" class netdev_module { public: - virtual ~netdev_module() { } - // no specific routines below ... may change -}; + virtual ~netdev_module() = default; + virtual std::unique_ptr<osd::network_device> open_device(int id, osd::network_handler &handler) = 0; + virtual std::vector<osd::network_device_info> list_devices() = 0; +}; -#endif /* NETDEV_MODULE_H_ */ +#endif // MAME_OSD_NETDEV_NETDEV_MODULE_H diff --git a/src/osd/modules/netdev/none.cpp b/src/osd/modules/netdev/none.cpp index a5b520f26a5..284ff51a962 100644 --- a/src/osd/modules/netdev/none.cpp +++ b/src/osd/modules/netdev/none.cpp @@ -4,20 +4,45 @@ * none.c * */ - #include "netdev_module.h" + #include "modules/osdmodule.h" +#include <memory> +#include <vector> + + +namespace osd { + +namespace { + class netdev_none : public osd_module, public netdev_module { public: - netdev_none() - : osd_module(OSD_NETDEV_PROVIDER, "none"), netdev_module() + netdev_none() : osd_module(OSD_NETDEV_PROVIDER, "none"), netdev_module() { } virtual ~netdev_none() { } - virtual int init(const osd_options &options) override { return 0; } + + virtual int init(osd_interface &osd, const osd_options &options) override + { + return 0; + } + + virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override + { + return std::unique_ptr<network_device>(); + } + + virtual std::vector<network_device_info> list_devices() override + { + return std::vector<network_device_info>(); + } }; -MODULE_DEFINITION(NETDEV_NONE, netdev_none) +} // anonymous namespace + +} // namespace osd + +MODULE_DEFINITION(NETDEV_NONE, osd::netdev_none) diff --git a/src/osd/modules/netdev/pcap.cpp b/src/osd/modules/netdev/pcap.cpp index 68e9512b14a..8ad62773d58 100644 --- a/src/osd/modules/netdev/pcap.cpp +++ b/src/osd/modules/netdev/pcap.cpp @@ -1,22 +1,31 @@ // license:BSD-3-Clause // copyright-holders:Carl -#if defined(OSD_NET_USE_PCAP) - -#include "emu.h" -#include "osdnet.h" #include "netdev_module.h" + #include "modules/osdmodule.h" + +#if defined(OSD_NET_USE_PCAP) + +#include "netdev_common.h" + #include "modules/lib/osdlib.h" +#include "osdcore.h" // osd_printf_* + +#include "util/strformat.h" // string_format + +#include <memory> +#include <vector> + #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) #include <windows.h> #undef interface #define LIB_NAME "wpcap.dll" #elif defined(SDLMAME_MACOSX) +#include <atomic> #include <pthread.h> -#include <libkern/OSAtomic.h> #define LIB_NAME "libpcap.dylib" #else @@ -25,6 +34,10 @@ #include <pcap.h> +namespace osd { + +namespace { + // Typedefs for dynamically loaded functions typedef int (*pcap_findalldevs_fn)(pcap_if_t **, char *); typedef pcap_t *(*pcap_open_live_fn)(const char *, int, int, int, char *); @@ -39,16 +52,16 @@ typedef int (*pcap_dispatch_fn)(pcap_t *, int, pcap_handler, u_char *); class pcap_module : public osd_module, public netdev_module { public: - pcap_module() - : osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), - pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr), - pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr) + pcap_module() : + osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), + pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr), + pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr) { } virtual ~pcap_module() { } - virtual int init(const osd_options &options) override; + virtual int init(osd_interface &osd, const osd_options &options) override; virtual void exit() override; virtual bool probe() override @@ -76,6 +89,20 @@ public: 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; + }; + + class netdev_pcap; + + std::vector<device_info> m_devices; + osd::dynamic_module::ptr pcap_dll; pcap_findalldevs_fn pcap_findalldevs_dl; @@ -89,192 +116,161 @@ public: pcap_dispatch_fn pcap_dispatch_dl; }; -// FIXME: bridge between pcap_module and netdev_pcap -static pcap_module *module = nullptr; - -#ifdef SDLMAME_MACOSX -struct netdev_pcap_context { - uint8_t *pkt; - int len; - pcap_t *p; - - uint8_t packets[32][1600]; - int packetlens[32]; - int head; - int tail; -}; -#endif - -class netdev_pcap : public osd_netdev +class pcap_module::netdev_pcap : public network_device_base { public: - netdev_pcap(const char *name, class device_network_interface *ifdev, int rate); + netdev_pcap(pcap_module &module, const char *name, network_handler &handler); ~netdev_pcap(); - virtual int send(uint8_t *buf, int len) override; - virtual void set_mac(const char *mac) override; + virtual int send(void const *buf, int len) override; + protected: virtual int recv_dev(uint8_t **buf) override; + private: + pcap_module &m_module; pcap_t *m_p; #ifdef SDLMAME_MACOSX - struct netdev_pcap_context m_ctx; pthread_t m_thread; + uint8_t *pkt; + int len; + pcap_t *p; + uint8_t m_pktbuf[2048]; + + uint8_t m_packets[32][1600]; + int m_packetlens[32]; + std::atomic<int> m_head; + std::atomic<int> m_tail; + + static void pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); + static void *pcap_blocker(void *arg); #endif }; #ifdef SDLMAME_MACOSX -static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { - struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user; +void pcap_module::netdev_pcap::pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) +{ + netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(user); - if(!ctx->p) return; + if (!ctx->p) + return; - if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) { + int const curr = ctx->m_head.load(std::memory_order_relaxed); + int const next = (curr + 1) & 0x1f; + if (ctx->m_tail.load(std::memory_order_acquire) == next) + { printf("buffer full, dropping packet\n"); return; } - memcpy(ctx->packets[ctx->head], bytes, h->len); - ctx->packetlens[ctx->head] = h->len; - OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head); + memcpy(ctx->m_packets[curr], bytes, h->len); + ctx->m_packetlens[curr] = h->len; + ctx->m_head.store(next, std::memory_order_release); } -static void *netdev_pcap_blocker(void *arg) { - struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg; +void *pcap_module::netdev_pcap::pcap_blocker(void *arg) +{ + netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(arg); - while(ctx && ctx->p) { - (*module->pcap_dispatch_dl)(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx); - } + while (ctx && ctx->p) + (*ctx->m_module.pcap_dispatch_dl)(ctx->p, 1, &netdev_pcap::pcap_handler, reinterpret_cast<u_char *>(ctx)); - return 0; + return nullptr; } #endif -netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate) - : osd_netdev(ifdev, rate) +pcap_module::netdev_pcap::netdev_pcap(pcap_module &module, const char *name, network_handler &handler) : + network_device_base(handler), + m_module(module), + m_p(nullptr) { char errbuf[PCAP_ERRBUF_SIZE]; #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) - m_p = (*module->pcap_open_live_dl)(name, 65535, 1, -1, errbuf); + m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, -1, errbuf); #else - m_p = (*module->pcap_open_live_dl)(name, 65535, 1, 1, errbuf); + m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, 1, errbuf); #endif if(!m_p) { osd_printf_error("Unable to open %s: %s\n", name, errbuf); return; } - if ((*module->pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1) + if ((*m_module.pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1) { osd_printf_error("Unable to set %s to ethernet", name); - (*module->pcap_close_dl)(m_p); + (*m_module.pcap_close_dl)(m_p); m_p = nullptr; return; } - netdev_pcap::set_mac(get_mac()); #ifdef SDLMAME_MACOSX - m_ctx.head = 0; - m_ctx.tail = 0; - m_ctx.p = m_p; - pthread_create(&m_thread, nullptr, netdev_pcap_blocker, &m_ctx); + m_head = 0; + m_tail = 0; + p = m_p; + pthread_create(&m_thread, nullptr, &netdev_pcap::pcap_blocker, this); #endif } -void netdev_pcap::set_mac(const char *mac) +int pcap_module::netdev_pcap::send(void const *buf, int len) { - char filter[256]; - struct bpf_program fp; - if(!m_p) return; -#ifdef SDLMAME_MACOSX - sprintf(filter, "not ether src %.2X:%.2X:%.2X:%.2X:%.2X:%.2X and (ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X or ether multicast or ether broadcast or ether dst 09:00:07:ff:ff:ff)", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5], (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]); -#else - sprintf(filter, "ether dst %.2X:%.2X:%.2X:%.2X:%.2X:%.2X or ether multicast or ether broadcast", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]); -#endif - if ((*module->pcap_compile_dl)(m_p, &fp, filter, 1, 0) == -1) { - osd_printf_error("Error with pcap_compile\n"); - } - if ((*module->pcap_setfilter_dl)(m_p, &fp) == -1) { - osd_printf_error("Error with pcap_setfilter\n"); - } -} - -int netdev_pcap::send(uint8_t *buf, int len) -{ - int ret; - if(!m_p) { + if (!m_p) + { printf("send invoked, but no pcap context\n"); return 0; } - ret = (*module->pcap_sendpacket_dl)(m_p, buf, len); + int ret = (*m_module.pcap_sendpacket_dl)(m_p, reinterpret_cast<const u_char *>(buf), len); printf("sent packet length %d, returned %d\n", len, ret); return ret ? len : 0; - //return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; + //return (!pcap_sendpacket_dl(m_p, reinterpret_cast<const u_char *>(buf), len)) ? len : 0; } -int netdev_pcap::recv_dev(uint8_t **buf) +int pcap_module::netdev_pcap::recv_dev(uint8_t **buf) { -#ifdef SDLMAME_MACOSX - uint8_t pktbuf[2048]; - int ret; - // no device open? - if(!m_p) return 0; + if (!m_p) + return 0; +#ifdef SDLMAME_MACOSX // Empty - if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) { + int const curr = m_tail.load(std::memory_order_relaxed); + if (m_head.load(std::memory_order_acquire) == curr) return 0; - } - memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]); - ret = m_ctx.packetlens[m_ctx.tail]; - OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail); - *buf = pktbuf; + memcpy(m_pktbuf, m_packets[curr], m_packetlens[curr]); + int ret = m_packetlens[curr]; + m_tail.store((curr + 1) & 0x1f, std::memory_order_release); + *buf = m_pktbuf; return ret; #else struct pcap_pkthdr *header; - if(!m_p) return 0; - return ((*module->pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0; + return ((*m_module.pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0; #endif } -netdev_pcap::~netdev_pcap() +pcap_module::netdev_pcap::~netdev_pcap() { #ifdef SDLMAME_MACOSX - m_ctx.p = nullptr; + p = nullptr; pthread_cancel(m_thread); pthread_join(m_thread, nullptr); #endif - if(m_p) (*module->pcap_close_dl)(m_p); + if(m_p) (*m_module.pcap_close_dl)(m_p); m_p = nullptr; } -static CREATE_NETDEV(create_pcap) -{ - class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate)); - return dynamic_cast<osd_netdev *>(dev); -} - -int pcap_module::init(const osd_options &options) +int pcap_module::init(osd_interface &osd, const osd_options &options) { pcap_if_t *devs; char errbuf[PCAP_ERRBUF_SIZE]; - // FIXME: bridge between pcap_module and netdev_pcap - module = this; - if ((*pcap_findalldevs_dl)(&devs, errbuf) == -1) { osd_printf_error("Unable to get network devices: %s\n", errbuf); return 1; } - while(devs) + while (devs) { - if(devs->description) { - add_netdev(devs->name, devs->description, create_pcap); - } else { - add_netdev(devs->name, devs->name, create_pcap); - } + m_devices.emplace_back(device_info{ devs->name, devs->description ? devs->description : devs->name }); devs = devs->next; } return 0; @@ -282,15 +278,35 @@ int pcap_module::init(const osd_options &options) void pcap_module::exit() { - clear_netdev(); + m_devices.clear(); } +std::unique_ptr<network_device> pcap_module::open_device(int id, network_handler &handler) +{ + if ((0 > id) || (m_devices.size() <= id)) + return nullptr; + + return std::make_unique<netdev_pcap>(*this, m_devices[id].name.c_str(), handler); +} + +std::vector<network_device_info> pcap_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(pcap_module, OSD_NETDEV_PROVIDER, "pcap") +namespace osd { namespace { MODULE_NOT_SUPPORTED(pcap_module, OSD_NETDEV_PROVIDER, "pcap") } } + #endif -MODULE_DEFINITION(NETDEV_PCAP, pcap_module) +MODULE_DEFINITION(NETDEV_PCAP, osd::pcap_module) 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) |