summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/netdev/taptun.cpp
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
commit7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch)
treef310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/osd/modules/netdev/taptun.cpp
parenta57b46ae933badd7441ce1644711dbb851e2b504 (diff)
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/osd/modules/netdev/taptun.cpp')
-rw-r--r--src/osd/modules/netdev/taptun.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp
new file mode 100644
index 00000000000..393c791cd0a
--- /dev/null
+++ b/src/osd/modules/netdev/taptun.cpp
@@ -0,0 +1,143 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl
+#if defined(OSD_NET_USE_TAPTUN)
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+
+#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)
+#endif
+
+class taptun_module : public osd_module, public netdev_module
+{
+public:
+
+ taptun_module()
+ : osd_module(OSD_NETDEV_PROVIDER, "taptun"), netdev_module()
+ {
+ }
+ virtual ~taptun_module() { }
+
+ virtual int init(const osd_options &options);
+ virtual void exit();
+
+ virtual bool probe() { return true; }
+};
+
+
+
+class netdev_tap : public osd_netdev
+{
+public:
+ netdev_tap(const char *name, class device_network_interface *ifdev, int rate);
+ ~netdev_tap();
+
+ int send(UINT8 *buf, int len);
+ void set_mac(const char *mac);
+protected:
+ int recv_dev(UINT8 **buf);
+private:
+ int m_fd;
+ char m_ifname[10];
+ char m_mac[6];
+ UINT8 m_buf[2048];
+};
+
+netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate)
+ : osd_netdev(ifdev, rate)
+{
+#ifdef __linux__
+ struct ifreq ifr;
+
+ m_fd = -1;
+ if((m_fd = open("/dev/net/tun", O_RDWR)) == -1) {
+ osd_printf_verbose("tap: open failed %d\n", errno);
+ return;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ sprintf(ifr.ifr_name, "tap-mess-%d-0", getuid());
+ if(ioctl(m_fd, TUNSETIFF, (void *)&ifr) == -1) {
+ osd_printf_verbose("tap: ioctl failed %d\n", errno);
+ close(m_fd);
+ m_fd = -1;
+ return;
+ }
+ osd_printf_verbose("netdev_tap: network up!\n");
+ strncpy(m_ifname, ifr.ifr_name, 10);
+ fcntl(m_fd, F_SETFL, O_NONBLOCK);
+
+#else
+ m_fd = -1;
+#endif
+}
+
+netdev_tap::~netdev_tap()
+{
+ close(m_fd);
+}
+
+void netdev_tap::set_mac(const char *mac)
+{
+ memcpy(m_mac, mac, 6);
+}
+
+int netdev_tap::send(UINT8 *buf, int len)
+{
+ if(m_fd == -1) return 0;
+ len = write(m_fd, buf, len);
+ return (len == -1)?0:len;
+}
+
+int netdev_tap::recv_dev(UINT8 **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));
+ *buf = m_buf;
+ return (len == -1)?0:len;
+}
+
+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)
+{
+ add_netdev("tap", "TAP/TUN Device", create_tap);
+ return 0;
+}
+
+void taptun_module::exit()
+{
+ clear_netdev();
+}
+
+
+#else
+ #include "modules/osdmodule.h"
+ #include "netdev_module.h"
+
+ MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun")
+#endif
+
+
+MODULE_DEFINITION(NETDEV_TAPTUN, taptun_module)