diff options
| author | 2015-11-08 12:56:12 +0100 | |
|---|---|---|
| committer | 2015-11-08 12:56:12 +0100 | |
| commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
| tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/osd/modules/netdev/taptun.cpp | |
| parent | a57b46ae933badd7441ce1644711dbb851e2b504 (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.cpp | 143 |
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) |
