trunk/src/emu/cpu/uml.h
| r243258 | r243259 | |
| 305 | 305 | parameter(UINT64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { } |
| 306 | 306 | parameter(operand_size size, memory_scale scale) : m_type(PTYPE_SIZE_SCALE), m_value((scale << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(scale >= SCALE_x1 && scale <= SCALE_x8); } |
| 307 | 307 | parameter(operand_size size, memory_space space) : m_type(PTYPE_SIZE_SPACE), m_value((space << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(space >= SPACE_PROGRAM && space <= SPACE_IO); } |
| 308 | | parameter(code_handle &handle) : m_type(PTYPE_CODE_HANDLE), m_value(static_cast<parameter_value>(reinterpret_cast<FPTR>(&handle))) { } |
| 308 | parameter(code_handle &handle) : m_type(PTYPE_CODE_HANDLE), m_value(reinterpret_cast<parameter_value>(&handle)) { } |
| 309 | 309 | parameter(code_label &label) : m_type(PTYPE_CODE_LABEL), m_value(label) { } |
| 310 | 310 | |
| 311 | 311 | // creators for types that don't safely default |
| r243258 | r243259 | |
| 313 | 313 | static inline parameter make_freg(int regnum) { assert(regnum >= REG_F0 && regnum < REG_F_END); return parameter(PTYPE_FLOAT_REGISTER, regnum); } |
| 314 | 314 | static inline parameter make_vreg(int regnum) { assert(regnum >= REG_V0 && regnum < REG_V_END); return parameter(PTYPE_VECTOR_REGISTER, regnum); } |
| 315 | 315 | static inline parameter make_mapvar(int mvnum) { assert(mvnum >= MAPVAR_M0 && mvnum < MAPVAR_END); return parameter(PTYPE_MAPVAR, mvnum); } |
| 316 | | static inline parameter make_memory(void *base) { return parameter(PTYPE_MEMORY, static_cast<parameter_value>(reinterpret_cast<FPTR>(base))); } |
| 317 | | static inline parameter make_memory(const void *base) { return parameter(PTYPE_MEMORY, static_cast<parameter_value>(reinterpret_cast<FPTR>(const_cast<void *>(base)))); } |
| 316 | static inline parameter make_memory(void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(base)); } |
| 317 | static inline parameter make_memory(const void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(const_cast<void *>(base))); } |
| 318 | 318 | static inline parameter make_size(operand_size size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); return parameter(PTYPE_SIZE, size); } |
| 319 | | static inline parameter make_string(const char *string) { return parameter(PTYPE_STRING, static_cast<parameter_value>(reinterpret_cast<FPTR>(const_cast<char *>(string)))); } |
| 320 | | static inline parameter make_cfunc(c_function func) { return parameter(PTYPE_C_FUNCTION, static_cast<parameter_value>(reinterpret_cast<FPTR>(func))); } |
| 319 | static inline parameter make_string(const char *string) { return parameter(PTYPE_STRING, reinterpret_cast<parameter_value>(const_cast<char *>(string))); } |
| 320 | static inline parameter make_cfunc(c_function func) { return parameter(PTYPE_C_FUNCTION, reinterpret_cast<parameter_value>(func)); } |
| 321 | 321 | static inline parameter make_rounding(float_rounding_mode mode) { assert(mode >= ROUND_TRUNC && mode <= ROUND_DEFAULT); return parameter(PTYPE_ROUNDING, mode); } |
| 322 | 322 | |
| 323 | 323 | // operators |
trunk/src/osd/modules/netdev/pcap.c
| r0 | r243259 | |
| 1 | #ifdef SDLMAME_NET_PCAP |
| 2 | |
| 3 | #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) |
| 4 | |
| 5 | #define WIN32_LEAN_AND_MEAN |
| 6 | #include <windows.h> |
| 7 | #endif |
| 8 | |
| 9 | #include <pcap.h> |
| 10 | |
| 11 | #include "emu.h" |
| 12 | #include "osdnet.h" |
| 13 | #include "netdev_module.h" |
| 14 | #include "modules/osdmodule.h" |
| 15 | |
| 16 | #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) |
| 17 | |
| 18 | #define LIB_NAME L"wpcap.dll" |
| 19 | #define LIB_ERROR_STR "Unable to load winpcap: %lx\n" |
| 20 | typedef DWORD except_type; |
| 21 | |
| 22 | #else |
| 23 | |
| 24 | #include <dlfcn.h> |
| 25 | #ifdef SDLMAME_MACOSX |
| 26 | #include <pthread.h> |
| 27 | #include <libkern/OSAtomic.h> |
| 28 | #endif |
| 29 | |
| 30 | #ifdef SDLMAME_MACOSX |
| 31 | #define LIB_NAME "libpcap.dylib" |
| 32 | #else |
| 33 | #define LIB_NAME "libpcap.so" |
| 34 | #endif |
| 35 | #define LIB_ERROR_STR "Unable to load pcap: %s\n" |
| 36 | |
| 37 | typedef void *HMODULE; |
| 38 | typedef const char *except_type; |
| 39 | #define FreeLibrary(x) dlclose(x) |
| 40 | #define GetLastError() dlerror() |
| 41 | #define GetProcAddress(x, y) dlsym(x, y) |
| 42 | #define LoadLibrary(x) dlopen(x, RTLD_LAZY) |
| 43 | |
| 44 | #endif |
| 45 | |
| 46 | class pcap_module : public osd_module, public netdev_module |
| 47 | { |
| 48 | public: |
| 49 | |
| 50 | pcap_module() |
| 51 | : osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), handle(NULL) |
| 52 | { |
| 53 | } |
| 54 | virtual ~pcap_module() { } |
| 55 | |
| 56 | virtual int init(); |
| 57 | virtual void exit(); |
| 58 | |
| 59 | virtual bool probe(); |
| 60 | |
| 61 | HMODULE handle; |
| 62 | }; |
| 63 | |
| 64 | static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL; |
| 65 | static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL; |
| 66 | static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL; |
| 67 | static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL; |
| 68 | static void (*pcap_close_dl)(pcap_t *) = NULL; |
| 69 | static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL; |
| 70 | static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL; |
| 71 | static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL; |
| 72 | static int (*pcap_dispatch_dl)(pcap_t *, int, pcap_handler callback, u_char *) = NULL; |
| 73 | |
| 74 | |
| 75 | #if 0 |
| 76 | #define pcap_compile_dl pcap_compile |
| 77 | #define pcap_findalldevs_dl pcap_findalldevs |
| 78 | #define pcap_open_live_dl pcap_open_live |
| 79 | #define pcap_next_ex_dl pcap_next_ex |
| 80 | #define pcap_close_dl pcap_close |
| 81 | #define pcap_setfilter_dl pcap_setfilter |
| 82 | #define pcap_sendpacket_dl pcap_sendpacket |
| 83 | #define pcap_set_datalink_dl pcap_set_datalink |
| 84 | #endif |
| 85 | |
| 86 | #ifdef SDLMAME_MACOSX |
| 87 | struct netdev_pcap_context { |
| 88 | UINT8 *pkt; |
| 89 | int len; |
| 90 | pcap_t *p; |
| 91 | |
| 92 | UINT8 packets[32][1600]; |
| 93 | int packetlens[32]; |
| 94 | int head; |
| 95 | int tail; |
| 96 | }; |
| 97 | #endif |
| 98 | |
| 99 | class netdev_pcap : public osd_netdev |
| 100 | { |
| 101 | public: |
| 102 | netdev_pcap(const char *name, class device_network_interface *ifdev, int rate); |
| 103 | ~netdev_pcap(); |
| 104 | |
| 105 | int send(UINT8 *buf, int len); |
| 106 | void set_mac(const char *mac); |
| 107 | protected: |
| 108 | int recv_dev(UINT8 **buf); |
| 109 | private: |
| 110 | pcap_t *m_p; |
| 111 | #ifdef SDLMAME_MACOSX |
| 112 | struct netdev_pcap_context m_ctx; |
| 113 | pthread_t m_thread; |
| 114 | #endif |
| 115 | }; |
| 116 | |
| 117 | #ifdef SDLMAME_MACOSX |
| 118 | static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { |
| 119 | struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user; |
| 120 | |
| 121 | if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) { |
| 122 | printf("buffer full, dropping packet\n"); |
| 123 | return; |
| 124 | } |
| 125 | memcpy(ctx->packets[ctx->head], bytes, h->len); |
| 126 | ctx->packetlens[ctx->head] = h->len; |
| 127 | OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head); |
| 128 | } |
| 129 | |
| 130 | static void *netdev_pcap_blocker(void *arg) { |
| 131 | struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg; |
| 132 | |
| 133 | while(1) { |
| 134 | pcap_dispatch_dl(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx); |
| 135 | } |
| 136 | |
| 137 | return 0; |
| 138 | } |
| 139 | #endif |
| 140 | |
| 141 | netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate) |
| 142 | : osd_netdev(ifdev, rate) |
| 143 | { |
| 144 | char errbuf[PCAP_ERRBUF_SIZE]; |
| 145 | #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) |
| 146 | m_p = pcap_open_live_dl(name, 65535, 1, -1, errbuf); |
| 147 | #else |
| 148 | m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf); |
| 149 | #endif |
| 150 | if(!m_p) |
| 151 | { |
| 152 | logerror("Unable to open %s: %s\n", name, errbuf); |
| 153 | return; |
| 154 | } |
| 155 | if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1) |
| 156 | { |
| 157 | logerror("Unable to set %s to ethernet", name); |
| 158 | pcap_close_dl(m_p); |
| 159 | m_p = NULL; |
| 160 | return; |
| 161 | } |
| 162 | set_mac(get_mac()); |
| 163 | |
| 164 | #ifdef SDLMAME_MACOSX |
| 165 | m_ctx.head = 0; |
| 166 | m_ctx.tail = 0; |
| 167 | m_ctx.p = m_p; |
| 168 | pthread_create(&m_thread, NULL, netdev_pcap_blocker, &m_ctx); |
| 169 | #endif |
| 170 | } |
| 171 | |
| 172 | void netdev_pcap::set_mac(const char *mac) |
| 173 | { |
| 174 | char filter[256]; |
| 175 | struct bpf_program fp; |
| 176 | if(!m_p) return; |
| 177 | #ifdef SDLMAME_MACOSX |
| 178 | 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]); |
| 179 | #else |
| 180 | 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]); |
| 181 | #endif |
| 182 | if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) { |
| 183 | logerror("Error with pcap_compile\n"); |
| 184 | } |
| 185 | if(pcap_setfilter_dl(m_p, &fp) == -1) { |
| 186 | logerror("Error with pcap_setfilter\n"); |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | int netdev_pcap::send(UINT8 *buf, int len) |
| 191 | { |
| 192 | if(!m_p) return 0; |
| 193 | return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; |
| 194 | } |
| 195 | |
| 196 | int netdev_pcap::recv_dev(UINT8 **buf) |
| 197 | { |
| 198 | #ifdef SDLMAME_MACOSX |
| 199 | UINT8 pktbuf[2048]; |
| 200 | int ret; |
| 201 | |
| 202 | // Empty |
| 203 | if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) { |
| 204 | return 0; |
| 205 | } |
| 206 | |
| 207 | memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]); |
| 208 | ret = m_ctx.packetlens[m_ctx.tail]; |
| 209 | OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail); |
| 210 | *buf = pktbuf; |
| 211 | return ret; |
| 212 | #else |
| 213 | struct pcap_pkthdr *header; |
| 214 | if(!m_p) return 0; |
| 215 | return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0; |
| 216 | #endif |
| 217 | } |
| 218 | |
| 219 | netdev_pcap::~netdev_pcap() |
| 220 | { |
| 221 | if(m_p) pcap_close_dl(m_p); |
| 222 | } |
| 223 | |
| 224 | static CREATE_NETDEV(create_pcap) |
| 225 | { |
| 226 | class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate)); |
| 227 | return dynamic_cast<osd_netdev *>(dev); |
| 228 | } |
| 229 | |
| 230 | bool pcap_module::probe() |
| 231 | { |
| 232 | if (handle == NULL) |
| 233 | { |
| 234 | handle = LoadLibrary(LIB_NAME); |
| 235 | return (handle != NULL); |
| 236 | } |
| 237 | return true; |
| 238 | } |
| 239 | |
| 240 | |
| 241 | int pcap_module::init() |
| 242 | { |
| 243 | pcap_if_t *devs; |
| 244 | char errbuf[PCAP_ERRBUF_SIZE]; |
| 245 | |
| 246 | try |
| 247 | { |
| 248 | if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))GetProcAddress(handle, "pcap_findalldevs"))) |
| 249 | throw GetLastError(); |
| 250 | if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))GetProcAddress(handle, "pcap_open_live"))) |
| 251 | throw GetLastError(); |
| 252 | if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))GetProcAddress(handle, "pcap_next_ex"))) |
| 253 | throw GetLastError(); |
| 254 | if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))GetProcAddress(handle, "pcap_compile"))) |
| 255 | throw GetLastError(); |
| 256 | if(!(pcap_close_dl = (void (*)(pcap_t *))GetProcAddress(handle, "pcap_close"))) |
| 257 | throw GetLastError(); |
| 258 | if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))GetProcAddress(handle, "pcap_setfilter"))) |
| 259 | throw GetLastError(); |
| 260 | if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))GetProcAddress(handle, "pcap_sendpacket"))) |
| 261 | throw GetLastError(); |
| 262 | if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))GetProcAddress(handle, "pcap_set_datalink"))) |
| 263 | throw GetLastError(); |
| 264 | if(!(pcap_dispatch_dl = (int (*)(pcap_t *, int, pcap_handler callback, u_char *))GetProcAddress(handle, "pcap_dispatch"))) |
| 265 | throw GetLastError(); |
| 266 | } |
| 267 | catch (except_type e) |
| 268 | { |
| 269 | FreeLibrary(handle); |
| 270 | logerror(LIB_ERROR_STR, e); |
| 271 | return 1; |
| 272 | } |
| 273 | if(pcap_findalldevs_dl(&devs, errbuf) == -1) |
| 274 | { |
| 275 | FreeLibrary(handle); |
| 276 | logerror("Unable to get network devices: %s\n", errbuf); |
| 277 | return 1; |
| 278 | } |
| 279 | |
| 280 | while(devs) |
| 281 | { |
| 282 | add_netdev(devs->name, devs->description, create_pcap); |
| 283 | devs = devs->next; |
| 284 | } |
| 285 | return 0; |
| 286 | } |
| 287 | |
| 288 | void pcap_module::exit() |
| 289 | { |
| 290 | clear_netdev(); |
| 291 | FreeLibrary(handle); |
| 292 | handle = NULL; |
| 293 | } |
| 294 | #else |
| 295 | #include "modules/osdmodule.h" |
| 296 | #include "netdev_module.h" |
| 297 | |
| 298 | MODULE_NOT_SUPPORTED(pcap_module, OSD_NETDEV_PROVIDER, "pcap") |
| 299 | #endif |
| 300 | |
| 301 | |
| 302 | MODULE_DEFINITION(NETDEV_PCAP, pcap_module) |
| 303 | |
trunk/src/osd/modules/netdev/taptun.c
| r0 | r243259 | |
| 1 | #if defined(SDLMAME_NET_TAPTUN) |
| 2 | |
| 3 | #include <unistd.h> |
| 4 | #include <fcntl.h> |
| 5 | #include <sys/ioctl.h> |
| 6 | #include <net/if.h> |
| 7 | #include <errno.h> |
| 8 | |
| 9 | #include "emu.h" |
| 10 | #include "osdnet.h" |
| 11 | #include "modules/osdmodule.h" |
| 12 | #include "netdev_module.h" |
| 13 | |
| 14 | #ifdef __linux__ |
| 15 | #define IFF_TAP 0x0002 |
| 16 | #define IFF_NO_PI 0x1000 |
| 17 | #define TUNSETIFF _IOW('T', 202, int) |
| 18 | #endif |
| 19 | |
| 20 | class taptun_module : public osd_module, public netdev_module |
| 21 | { |
| 22 | public: |
| 23 | |
| 24 | taptun_module() |
| 25 | : osd_module(OSD_NETDEV_PROVIDER, "taptun"), netdev_module() |
| 26 | { |
| 27 | } |
| 28 | virtual ~taptun_module() { } |
| 29 | |
| 30 | virtual int init(); |
| 31 | virtual void exit(); |
| 32 | |
| 33 | virtual bool probe() { return true; } |
| 34 | }; |
| 35 | |
| 36 | |
| 37 | |
| 38 | class netdev_tap : public osd_netdev |
| 39 | { |
| 40 | public: |
| 41 | netdev_tap(const char *name, class device_network_interface *ifdev, int rate); |
| 42 | ~netdev_tap(); |
| 43 | |
| 44 | int send(UINT8 *buf, int len); |
| 45 | void set_mac(const char *mac); |
| 46 | protected: |
| 47 | int recv_dev(UINT8 **buf); |
| 48 | private: |
| 49 | int m_fd; |
| 50 | char m_ifname[10]; |
| 51 | char m_mac[6]; |
| 52 | UINT8 m_buf[2048]; |
| 53 | }; |
| 54 | |
| 55 | netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate) |
| 56 | : osd_netdev(ifdev, rate) |
| 57 | { |
| 58 | #ifdef __linux__ |
| 59 | struct ifreq ifr; |
| 60 | |
| 61 | m_fd = -1; |
| 62 | if((m_fd = open("/dev/net/tun", O_RDWR)) == -1) { |
| 63 | osd_printf_verbose("tap: open failed %d\n", errno); |
| 64 | return; |
| 65 | } |
| 66 | |
| 67 | memset(&ifr, 0, sizeof(ifr)); |
| 68 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
| 69 | sprintf(ifr.ifr_name, "tap-mess-%d-0", getuid()); |
| 70 | if(ioctl(m_fd, TUNSETIFF, (void *)&ifr) == -1) { |
| 71 | osd_printf_verbose("tap: ioctl failed %d\n", errno); |
| 72 | close(m_fd); |
| 73 | m_fd = -1; |
| 74 | return; |
| 75 | } |
| 76 | osd_printf_verbose("netdev_tap: network up!\n"); |
| 77 | strncpy(m_ifname, ifr.ifr_name, 10); |
| 78 | fcntl(m_fd, F_SETFL, O_NONBLOCK); |
| 79 | |
| 80 | #else |
| 81 | m_fd = -1; |
| 82 | #endif |
| 83 | } |
| 84 | |
| 85 | netdev_tap::~netdev_tap() |
| 86 | { |
| 87 | close(m_fd); |
| 88 | } |
| 89 | |
| 90 | void netdev_tap::set_mac(const char *mac) |
| 91 | { |
| 92 | memcpy(m_mac, mac, 6); |
| 93 | } |
| 94 | |
| 95 | int netdev_tap::send(UINT8 *buf, int len) |
| 96 | { |
| 97 | if(m_fd == -1) return 0; |
| 98 | len = write(m_fd, buf, len); |
| 99 | return (len == -1)?0:len; |
| 100 | } |
| 101 | |
| 102 | int netdev_tap::recv_dev(UINT8 **buf) |
| 103 | { |
| 104 | int len; |
| 105 | if(m_fd == -1) return 0; |
| 106 | // exit if we didn't receive anything, got an error, got a broadcast or multicast packet, |
| 107 | // are in promiscuous mode or got a packet with our mac. |
| 108 | do { |
| 109 | len = read(m_fd, m_buf, sizeof(m_buf)); |
| 110 | } while((len > 0) && memcmp(get_mac(), m_buf, 6) && !get_promisc() && !(m_buf[0] & 1)); |
| 111 | *buf = m_buf; |
| 112 | return (len == -1)?0:len; |
| 113 | } |
| 114 | |
| 115 | static CREATE_NETDEV(create_tap) |
| 116 | { |
| 117 | class netdev_tap *dev = global_alloc(netdev_tap(ifname, ifdev, rate)); |
| 118 | return dynamic_cast<osd_netdev *>(dev); |
| 119 | } |
| 120 | |
| 121 | int taptun_module::init() |
| 122 | { |
| 123 | add_netdev("tap", "TAP/TUN Device", create_tap); |
| 124 | return 0; |
| 125 | } |
| 126 | |
| 127 | void taptun_module::exit() |
| 128 | { |
| 129 | clear_netdev(); |
| 130 | } |
| 131 | |
| 132 | |
| 133 | #else |
| 134 | #include "modules/osdmodule.h" |
| 135 | #include "netdev_module.h" |
| 136 | |
| 137 | MODULE_NOT_SUPPORTED(taptun_module, OSD_NETDEV_PROVIDER, "taptun") |
| 138 | #endif |
| 139 | |
| 140 | |
| 141 | MODULE_DEFINITION(NETDEV_TAPTUN, taptun_module) |
trunk/src/osd/osdnet.c
| r243258 | r243259 | |
| 1 | 1 | #include "emu.h" |
| 2 | 2 | #include "osdnet.h" |
| 3 | 3 | |
| 4 | | static class simple_list<netdev_entry_t> netdev_list; |
| 4 | static class simple_list<osd_netdev::entry_t> netdev_list; |
| 5 | 5 | |
| 6 | 6 | void add_netdev(const char *name, const char *description, create_netdev func) |
| 7 | 7 | { |
| 8 | | netdev_entry_t *entry = global_alloc_clear(netdev_entry_t); |
| 8 | osd_netdev::entry_t *entry = global_alloc_clear(osd_netdev::entry_t); |
| 9 | 9 | entry->id = netdev_list.count(); |
| 10 | 10 | strncpy(entry->name, name, 255); |
| 11 | 11 | entry->name[255] = '\0'; |
| r243258 | r243259 | |
| 20 | 20 | netdev_list.reset(); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | | const netdev_entry_t *netdev_first() { |
| 23 | const osd_netdev::entry_t *netdev_first() { |
| 24 | 24 | return netdev_list.first(); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | | class netdev *open_netdev(int id, class device_network_interface *ifdev, int rate) |
| 27 | class osd_netdev *open_netdev(int id, class device_network_interface *ifdev, int rate) |
| 28 | 28 | { |
| 29 | | netdev_entry_t *entry = netdev_list.first(); |
| 29 | osd_netdev::entry_t *entry = netdev_list.first(); |
| 30 | 30 | while(entry) { |
| 31 | 31 | if(entry->id==id) |
| 32 | 32 | return entry->func(entry->name, ifdev, rate); |
| r243258 | r243259 | |
| 36 | 36 | return NULL; |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | | netdev::netdev(class device_network_interface *ifdev, int rate) |
| 39 | osd_netdev::osd_netdev(class device_network_interface *ifdev, int rate) |
| 40 | 40 | { |
| 41 | 41 | m_dev = ifdev; |
| 42 | | ifdev->device().machine().scheduler().timer_pulse(attotime::from_hz(rate), timer_expired_delegate(FUNC(netdev::recv), this)); |
| 42 | ifdev->device().machine().scheduler().timer_pulse(attotime::from_hz(rate), timer_expired_delegate(FUNC(osd_netdev::recv), this)); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | | netdev::~netdev() |
| 45 | osd_netdev::~osd_netdev() |
| 46 | 46 | { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | | int netdev::send(UINT8 *buf, int len) |
| 49 | int osd_netdev::send(UINT8 *buf, int len) |
| 50 | 50 | { |
| 51 | 51 | return 0; |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | | void netdev::recv(void *ptr, int param) |
| 54 | void osd_netdev::recv(void *ptr, int param) |
| 55 | 55 | { |
| 56 | 56 | UINT8 *buf; |
| 57 | 57 | int len; |
| r243258 | r243259 | |
| 74 | 74 | } |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | | int netdev::recv_dev(UINT8 **buf) |
| 77 | int osd_netdev::recv_dev(UINT8 **buf) |
| 78 | 78 | { |
| 79 | 79 | return 0; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | | void netdev::set_mac(const char *mac) |
| 82 | void osd_netdev::set_mac(const char *mac) |
| 83 | 83 | { |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | | void netdev::set_promisc(bool promisc) |
| 86 | void osd_netdev::set_promisc(bool promisc) |
| 87 | 87 | { |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | | bool netdev::get_promisc() |
| 90 | bool osd_netdev::get_promisc() |
| 91 | 91 | { |
| 92 | 92 | if(m_dev) |
| 93 | 93 | return m_dev->get_promisc(); |
| 94 | 94 | return false; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | | const char *netdev::get_mac() |
| 97 | const char *osd_netdev::get_mac() |
| 98 | 98 | { |
| 99 | 99 | if(m_dev) |
| 100 | 100 | return m_dev->get_mac(); |
| r243258 | r243259 | |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | 120 | printf("Available network adapters:\n"); |
| 121 | | const netdev_entry_t *entry = netdev_first(); |
| 121 | const osd_netdev::entry_t *entry = netdev_first(); |
| 122 | 122 | while(entry) { |
| 123 | 123 | printf(" %s\n", entry->description); |
| 124 | 124 | entry = entry->m_next; |
trunk/src/osd/sdl/netdev_pcap.c
| r243258 | r243259 | |
| 1 | | #ifdef SDLMAME_WIN32 |
| 2 | | #include "../windows/netdev_pcap.c" |
| 3 | | #else |
| 4 | | |
| 5 | | #include <pcap.h> |
| 6 | | |
| 7 | | static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL; |
| 8 | | static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL; |
| 9 | | static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL; |
| 10 | | static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL; |
| 11 | | static void (*pcap_close_dl)(pcap_t *) = NULL; |
| 12 | | static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL; |
| 13 | | static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL; |
| 14 | | static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL; |
| 15 | | |
| 16 | | #include <dlfcn.h> |
| 17 | | |
| 18 | | #include "emu.h" |
| 19 | | #include "osdnet.h" |
| 20 | | |
| 21 | | static void *handle = NULL; |
| 22 | | |
| 23 | | class netdev_pcap : public netdev |
| 24 | | { |
| 25 | | public: |
| 26 | | netdev_pcap(const char *name, class device_network_interface *ifdev, int rate); |
| 27 | | ~netdev_pcap(); |
| 28 | | |
| 29 | | int send(UINT8 *buf, int len); |
| 30 | | void set_mac(const char *mac); |
| 31 | | protected: |
| 32 | | int recv_dev(UINT8 **buf); |
| 33 | | private: |
| 34 | | pcap_t *m_p; |
| 35 | | }; |
| 36 | | |
| 37 | | netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate) |
| 38 | | : netdev(ifdev, rate) |
| 39 | | { |
| 40 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 41 | | m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf); |
| 42 | | if(!m_p) |
| 43 | | { |
| 44 | | osd_printf_verbose("Unable to open %s: %s\n", name, errbuf); |
| 45 | | return; |
| 46 | | } |
| 47 | | if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1) |
| 48 | | { |
| 49 | | osd_printf_verbose("Unable to set %s to ethernet\n", name); |
| 50 | | pcap_close_dl(m_p); |
| 51 | | m_p = NULL; |
| 52 | | return; |
| 53 | | } |
| 54 | | set_mac(get_mac()); |
| 55 | | } |
| 56 | | |
| 57 | | void netdev_pcap::set_mac(const char *mac) |
| 58 | | { |
| 59 | | char filter[256]; |
| 60 | | struct bpf_program fp; |
| 61 | | if(!m_p) return; |
| 62 | | 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]); |
| 63 | | if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) { |
| 64 | | osd_printf_verbose("Error with pcap_compile\n"); |
| 65 | | } |
| 66 | | if(pcap_setfilter_dl(m_p, &fp) == -1) { |
| 67 | | osd_printf_verbose("Error with pcap_setfilter\n"); |
| 68 | | } |
| 69 | | } |
| 70 | | |
| 71 | | int netdev_pcap::send(UINT8 *buf, int len) |
| 72 | | { |
| 73 | | if(!m_p) return 0; |
| 74 | | return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; |
| 75 | | } |
| 76 | | |
| 77 | | int netdev_pcap::recv_dev(UINT8 **buf) |
| 78 | | { |
| 79 | | struct pcap_pkthdr *header; |
| 80 | | if(!m_p) return 0; |
| 81 | | return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0; |
| 82 | | } |
| 83 | | |
| 84 | | netdev_pcap::~netdev_pcap() |
| 85 | | { |
| 86 | | if(m_p) pcap_close_dl(m_p); |
| 87 | | } |
| 88 | | |
| 89 | | static CREATE_NETDEV(create_pcap) |
| 90 | | { |
| 91 | | class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate)); |
| 92 | | return dynamic_cast<netdev *>(dev); |
| 93 | | } |
| 94 | | |
| 95 | | void init_pcap() |
| 96 | | { |
| 97 | | pcap_if_t *devs; |
| 98 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 99 | | handle = NULL; |
| 100 | | |
| 101 | | try |
| 102 | | { |
| 103 | | if(!(handle = dlopen("libpcap.so", RTLD_LAZY))) throw dlerror(); |
| 104 | | if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))dlsym(handle, "pcap_findalldevs"))) |
| 105 | | throw dlerror(); |
| 106 | | if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))dlsym(handle, "pcap_open_live"))) |
| 107 | | throw dlerror(); |
| 108 | | if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))dlsym(handle, "pcap_next_ex"))) |
| 109 | | throw dlerror(); |
| 110 | | if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))dlsym(handle, "pcap_compile"))) |
| 111 | | throw dlerror(); |
| 112 | | if(!(pcap_close_dl = (void (*)(pcap_t *))dlsym(handle, "pcap_close"))) |
| 113 | | throw dlerror(); |
| 114 | | if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))dlsym(handle, "pcap_setfilter"))) |
| 115 | | throw dlerror(); |
| 116 | | if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))dlsym(handle, "pcap_sendpacket"))) |
| 117 | | throw dlerror(); |
| 118 | | if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))dlsym(handle, "pcap_set_datalink"))) |
| 119 | | throw dlerror(); |
| 120 | | } |
| 121 | | catch (const char *e) |
| 122 | | { |
| 123 | | dlclose(handle); |
| 124 | | osd_printf_verbose("Unable to load winpcap: %s\n", e); |
| 125 | | return; |
| 126 | | } |
| 127 | | if(pcap_findalldevs_dl(&devs, errbuf) == -1) |
| 128 | | { |
| 129 | | dlclose(handle); |
| 130 | | osd_printf_verbose("Unable to get network devices: %s\n", errbuf); |
| 131 | | return; |
| 132 | | } |
| 133 | | |
| 134 | | while(devs) |
| 135 | | { |
| 136 | | add_netdev(devs->name, devs->description, create_pcap); |
| 137 | | devs = devs->next; |
| 138 | | } |
| 139 | | } |
| 140 | | |
| 141 | | void deinit_pcap() |
| 142 | | { |
| 143 | | clear_netdev(); |
| 144 | | dlclose(handle); |
| 145 | | handle = NULL; |
| 146 | | } |
| 147 | | |
| 148 | | #endif // SDLMAME_WIN32 |
trunk/src/osd/sdl/netdev_pcap_osx.c
| r243258 | r243259 | |
| 1 | | #ifdef SDLMAME_WIN32 |
| 2 | | #include "../windows/netdev_pcap.c" |
| 3 | | #else |
| 4 | | |
| 5 | | #include <pcap.h> |
| 6 | | #include "emu.h" |
| 7 | | #include "osdnet.h" |
| 8 | | #include <pthread.h> |
| 9 | | #include <libkern/OSAtomic.h> |
| 10 | | |
| 11 | | #define pcap_compile_dl pcap_compile |
| 12 | | #define pcap_findalldevs_dl pcap_findalldevs |
| 13 | | #define pcap_open_live_dl pcap_open_live |
| 14 | | #define pcap_next_ex_dl pcap_next_ex |
| 15 | | #define pcap_close_dl pcap_close |
| 16 | | #define pcap_setfilter_dl pcap_setfilter |
| 17 | | #define pcap_sendpacket_dl pcap_sendpacket |
| 18 | | #define pcap_set_datalink_dl pcap_set_datalink |
| 19 | | |
| 20 | | struct netdev_pcap_context { |
| 21 | | UINT8 *pkt; |
| 22 | | int len; |
| 23 | | pcap_t *p; |
| 24 | | |
| 25 | | UINT8 packets[32][1600]; |
| 26 | | int packetlens[32]; |
| 27 | | int head; |
| 28 | | int tail; |
| 29 | | }; |
| 30 | | |
| 31 | | class netdev_pcap : public netdev |
| 32 | | { |
| 33 | | public: |
| 34 | | netdev_pcap(const char *name, class device_network_interface *ifdev, int rate); |
| 35 | | ~netdev_pcap(); |
| 36 | | |
| 37 | | int send(UINT8 *buf, int len); |
| 38 | | void set_mac(const char *mac); |
| 39 | | protected: |
| 40 | | int recv_dev(UINT8 **buf); |
| 41 | | private: |
| 42 | | pcap_t *m_p; |
| 43 | | struct netdev_pcap_context m_ctx; |
| 44 | | pthread_t m_thread; |
| 45 | | }; |
| 46 | | |
| 47 | | static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { |
| 48 | | struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user; |
| 49 | | |
| 50 | | if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) { |
| 51 | | printf("buffer full, dropping packet\n"); |
| 52 | | return; |
| 53 | | } |
| 54 | | memcpy(ctx->packets[ctx->head], bytes, h->len); |
| 55 | | ctx->packetlens[ctx->head] = h->len; |
| 56 | | OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head); |
| 57 | | } |
| 58 | | |
| 59 | | static void *netdev_pcap_blocker(void *arg) { |
| 60 | | struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg; |
| 61 | | |
| 62 | | while(1) { |
| 63 | | pcap_dispatch(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx); |
| 64 | | } |
| 65 | | |
| 66 | | return 0; |
| 67 | | } |
| 68 | | |
| 69 | | netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate) |
| 70 | | : netdev(ifdev, rate) |
| 71 | | { |
| 72 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 73 | | m_p = pcap_open_live_dl(name, 65535, 1, 1, errbuf); |
| 74 | | if(!m_p) |
| 75 | | { |
| 76 | | osd_printf_verbose("Unable to open %s: %s\n", name, errbuf); |
| 77 | | return; |
| 78 | | } |
| 79 | | if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1) |
| 80 | | { |
| 81 | | osd_printf_verbose("Unable to set %s to ethernet\n", name); |
| 82 | | pcap_close_dl(m_p); |
| 83 | | m_p = NULL; |
| 84 | | return; |
| 85 | | } |
| 86 | | set_mac(get_mac()); |
| 87 | | |
| 88 | | m_ctx.head = 0; |
| 89 | | m_ctx.tail = 0; |
| 90 | | m_ctx.p = m_p; |
| 91 | | pthread_create(&m_thread, NULL, netdev_pcap_blocker, &m_ctx); |
| 92 | | } |
| 93 | | |
| 94 | | void netdev_pcap::set_mac(const char *mac) |
| 95 | | { |
| 96 | | char filter[256]; |
| 97 | | struct bpf_program fp; |
| 98 | | if(!m_p) return; |
| 99 | | 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]); |
| 100 | | if(pcap_compile_dl(m_p, &fp, filter, 1, 0) == -1) { |
| 101 | | osd_printf_verbose("Error with pcap_compile\n"); |
| 102 | | } |
| 103 | | if(pcap_setfilter_dl(m_p, &fp) == -1) { |
| 104 | | osd_printf_verbose("Error with pcap_setfilter\n"); |
| 105 | | } |
| 106 | | } |
| 107 | | |
| 108 | | int netdev_pcap::send(UINT8 *buf, int len) |
| 109 | | { |
| 110 | | if(!m_p) return 0; |
| 111 | | return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; |
| 112 | | } |
| 113 | | |
| 114 | | int netdev_pcap::recv_dev(UINT8 **buf) |
| 115 | | { |
| 116 | | UINT8 pktbuf[2048]; |
| 117 | | int ret; |
| 118 | | |
| 119 | | // Empty |
| 120 | | if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) { |
| 121 | | return 0; |
| 122 | | } |
| 123 | | |
| 124 | | memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]); |
| 125 | | ret = m_ctx.packetlens[m_ctx.tail]; |
| 126 | | OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail); |
| 127 | | *buf = pktbuf; |
| 128 | | return ret; |
| 129 | | } |
| 130 | | |
| 131 | | netdev_pcap::~netdev_pcap() |
| 132 | | { |
| 133 | | if(m_p) pcap_close_dl(m_p); |
| 134 | | } |
| 135 | | |
| 136 | | static CREATE_NETDEV(create_pcap) |
| 137 | | { |
| 138 | | class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate)); |
| 139 | | return dynamic_cast<netdev *>(dev); |
| 140 | | } |
| 141 | | |
| 142 | | void init_pcap() |
| 143 | | { |
| 144 | | pcap_if_t *devs; |
| 145 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 146 | | if(pcap_findalldevs_dl(&devs, errbuf) == -1) |
| 147 | | { |
| 148 | | osd_printf_verbose("Unable to get network devices: %s\n", errbuf); |
| 149 | | return; |
| 150 | | } |
| 151 | | |
| 152 | | #if 1 |
| 153 | | while(devs) |
| 154 | | { |
| 155 | | add_netdev(devs->name, devs->description, create_pcap); |
| 156 | | devs = devs->next; |
| 157 | | } |
| 158 | | #else |
| 159 | | if (devs) |
| 160 | | { |
| 161 | | while(devs->next) |
| 162 | | { |
| 163 | | add_netdev(devs->name, devs->description ? devs->description : devs->name, create_pcap); |
| 164 | | devs = devs->next; |
| 165 | | } |
| 166 | | } |
| 167 | | #endif |
| 168 | | } |
| 169 | | |
| 170 | | void deinit_pcap() |
| 171 | | { |
| 172 | | clear_netdev(); |
| 173 | | } |
| 174 | | |
| 175 | | #endif // SDLMAME_WIN32 |
trunk/src/osd/sdl/netdev_tap.c
| r243258 | r243259 | |
| 1 | | #include <unistd.h> |
| 2 | | #include <fcntl.h> |
| 3 | | #include <sys/ioctl.h> |
| 4 | | #include <net/if.h> |
| 5 | | #include <errno.h> |
| 6 | | |
| 7 | | #include "emu.h" |
| 8 | | #include "osdnet.h" |
| 9 | | |
| 10 | | #ifdef __linux__ |
| 11 | | #define IFF_TAP 0x0002 |
| 12 | | #define IFF_NO_PI 0x1000 |
| 13 | | #define TUNSETIFF _IOW('T', 202, int) |
| 14 | | #endif |
| 15 | | |
| 16 | | class netdev_tap : public netdev |
| 17 | | { |
| 18 | | public: |
| 19 | | netdev_tap(const char *name, class device_network_interface *ifdev, int rate); |
| 20 | | ~netdev_tap(); |
| 21 | | |
| 22 | | int send(UINT8 *buf, int len); |
| 23 | | void set_mac(const char *mac); |
| 24 | | protected: |
| 25 | | int recv_dev(UINT8 **buf); |
| 26 | | private: |
| 27 | | int m_fd; |
| 28 | | char m_ifname[10]; |
| 29 | | char m_mac[6]; |
| 30 | | UINT8 m_buf[2048]; |
| 31 | | }; |
| 32 | | |
| 33 | | netdev_tap::netdev_tap(const char *name, class device_network_interface *ifdev, int rate) |
| 34 | | : netdev(ifdev, rate) |
| 35 | | { |
| 36 | | #ifdef __linux__ |
| 37 | | struct ifreq ifr; |
| 38 | | |
| 39 | | m_fd = -1; |
| 40 | | if((m_fd = open("/dev/net/tun", O_RDWR)) == -1) { |
| 41 | | osd_printf_verbose("tap: open failed %d\n", errno); |
| 42 | | return; |
| 43 | | } |
| 44 | | |
| 45 | | memset(&ifr, 0, sizeof(ifr)); |
| 46 | | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
| 47 | | sprintf(ifr.ifr_name, "tap-mess-%d-0", getuid()); |
| 48 | | if(ioctl(m_fd, TUNSETIFF, (void *)&ifr) == -1) { |
| 49 | | osd_printf_verbose("tap: ioctl failed %d\n", errno); |
| 50 | | close(m_fd); |
| 51 | | m_fd = -1; |
| 52 | | return; |
| 53 | | } |
| 54 | | osd_printf_verbose("netdev_tap: network up!\n"); |
| 55 | | strncpy(m_ifname, ifr.ifr_name, 10); |
| 56 | | fcntl(m_fd, F_SETFL, O_NONBLOCK); |
| 57 | | |
| 58 | | #else |
| 59 | | m_fd = -1; |
| 60 | | #endif |
| 61 | | } |
| 62 | | |
| 63 | | netdev_tap::~netdev_tap() |
| 64 | | { |
| 65 | | close(m_fd); |
| 66 | | } |
| 67 | | |
| 68 | | void netdev_tap::set_mac(const char *mac) |
| 69 | | { |
| 70 | | memcpy(m_mac, mac, 6); |
| 71 | | } |
| 72 | | |
| 73 | | int netdev_tap::send(UINT8 *buf, int len) |
| 74 | | { |
| 75 | | if(m_fd == -1) return 0; |
| 76 | | len = write(m_fd, buf, len); |
| 77 | | return (len == -1)?0:len; |
| 78 | | } |
| 79 | | |
| 80 | | int netdev_tap::recv_dev(UINT8 **buf) |
| 81 | | { |
| 82 | | int len; |
| 83 | | if(m_fd == -1) return 0; |
| 84 | | // exit if we didn't receive anything, got an error, got a broadcast or multicast packet, |
| 85 | | // are in promiscuous mode or got a packet with our mac. |
| 86 | | do { |
| 87 | | len = read(m_fd, m_buf, sizeof(m_buf)); |
| 88 | | } while((len > 0) && memcmp(get_mac(), m_buf, 6) && !get_promisc() && !(m_buf[0] & 1)); |
| 89 | | *buf = m_buf; |
| 90 | | return (len == -1)?0:len; |
| 91 | | } |
| 92 | | |
| 93 | | static CREATE_NETDEV(create_tap) |
| 94 | | { |
| 95 | | class netdev_tap *dev = global_alloc(netdev_tap(ifname, ifdev, rate)); |
| 96 | | return dynamic_cast<netdev *>(dev); |
| 97 | | } |
| 98 | | |
| 99 | | void init_tap() |
| 100 | | { |
| 101 | | add_netdev("tap", "TAP/TUN Device", create_tap); |
| 102 | | } |
| 103 | | |
| 104 | | void deinit_tap() |
| 105 | | { |
| 106 | | clear_netdev(); |
| 107 | | } |
trunk/src/osd/sdl/sdl.mak
| r243258 | r243259 | |
| 403 | 403 | $(OSDOBJ)/modules/lib \ |
| 404 | 404 | $(OSDOBJ)/modules/midi \ |
| 405 | 405 | $(OSDOBJ)/modules/font \ |
| 406 | $(OSDOBJ)/modules/netdev \ |
| 406 | 407 | |
| 407 | 408 | #------------------------------------------------- |
| 408 | 409 | # OSD core library |
| r243258 | r243259 | |
| 445 | 446 | $(OSDOBJ)/modules/font/font_windows.o \ |
| 446 | 447 | $(OSDOBJ)/modules/font/font_osx.o \ |
| 447 | 448 | $(OSDOBJ)/modules/font/font_none.o \ |
| 449 | $(OSDOBJ)/modules/netdev/taptun.o \ |
| 450 | $(OSDOBJ)/modules/netdev/pcap.o \ |
| 448 | 451 | |
| 449 | 452 | ifdef NO_USE_MIDI |
| 450 | 453 | OSDOBJS += $(OSDOBJ)/modules/midi/none.o |
| r243258 | r243259 | |
| 452 | 455 | OSDOBJS += $(OSDOBJ)/modules/midi/portmidi.o |
| 453 | 456 | endif |
| 454 | 457 | |
| 455 | | ifeq ($(BASE_TARGETOS),win32) |
| 456 | | OSDOBJS += $(OSDOBJ)/modules/sound/direct_sound.o |
| 457 | | endif |
| 458 | | |
| 459 | 458 | # Add SDL2.0 support |
| 460 | 459 | |
| 461 | 460 | ifeq ($(SDL_LIBVER),sdl2) |
| r243258 | r243259 | |
| 465 | 464 | # add an ARCH define |
| 466 | 465 | DEFS += -DSDLMAME_ARCH="$(ARCHOPTS)" -DSYNC_IMPLEMENTATION=$(SYNC_IMPLEMENTATION) |
| 467 | 466 | |
| 468 | | # Add JavaScript sound module for Emscripten compiles |
| 469 | | |
| 470 | | ifeq ($(TARGETOS),emscripten) |
| 471 | | OSDOBJS += $(OSDOBJ)/modules/sound/js_sound.o |
| 472 | | endif |
| 473 | | |
| 474 | 467 | #------------------------------------------------- |
| 475 | 468 | # Generic defines and additions |
| 476 | 469 | #------------------------------------------------- |
| r243258 | r243259 | |
| 828 | 821 | # Network (TAP/TUN) |
| 829 | 822 | #------------------------------------------------- |
| 830 | 823 | |
| 831 | | OSDOBJS += $(SDLOBJ)/netdev.o |
| 832 | | |
| 833 | 824 | ifndef DONT_USE_NETWORK |
| 834 | 825 | |
| 835 | 826 | ifeq ($(SDL_NETWORK),taptun) |
| 836 | | OSDOBJS += $(SDLOBJ)/netdev_tap.o |
| 837 | 827 | |
| 838 | | DEFS += -DSDLMAME_NETWORK -DSDLMAME_NET_TAPTUN |
| 828 | DEFS += -DSDLMAME_NET_TAPTUN |
| 839 | 829 | endif |
| 840 | 830 | |
| 841 | 831 | ifeq ($(SDL_NETWORK),pcap) |
| 842 | 832 | |
| 843 | | ifeq ($(TARGETOS),macosx) |
| 844 | | OSDOBJS += $(SDLOBJ)/netdev_pcap_osx.o |
| 845 | | else |
| 846 | | OSDOBJS += $(SDLOBJ)/netdev_pcap.o |
| 847 | | endif |
| 833 | DEFS += -DSDLMAME_NET_PCAP |
| 848 | 834 | |
| 849 | | DEFS += -DSDLMAME_NETWORK -DSDLMAME_NET_PCAP |
| 835 | # dynamically linked ... |
| 836 | #ifneq ($(TARGETOS),win32) |
| 837 | #LIBS += -lpcap |
| 838 | #endif |
| 850 | 839 | |
| 851 | | ifneq ($(TARGETOS),win32) |
| 852 | | LIBS += -lpcap |
| 853 | | endif |
| 854 | | |
| 855 | 840 | endif # ifeq ($(SDL_NETWORK),pcap) |
| 856 | 841 | |
| 857 | 842 | endif # ifndef DONT_USE_NETWORK |
trunk/src/osd/windows/netdev_pcap.c
| r243258 | r243259 | |
| 1 | | #define WIN32_LEAN_AND_MEAN |
| 2 | | #include <windows.h> |
| 3 | | #include <pcap.h> |
| 4 | | |
| 5 | | static int (*pcap_compile_dl)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32) = NULL; |
| 6 | | static int (*pcap_findalldevs_dl)(pcap_if_t **, char *) = NULL; |
| 7 | | static pcap_t *(*pcap_open_live_dl)(const char *name, int, int, int, char *) = NULL; |
| 8 | | static int (*pcap_next_ex_dl)(pcap_t *, struct pcap_pkthdr **, const u_char **) = NULL; |
| 9 | | static void (*pcap_close_dl)(pcap_t *) = NULL; |
| 10 | | static int (*pcap_setfilter_dl)(pcap_t *, struct bpf_program *) = NULL; |
| 11 | | static int (*pcap_sendpacket_dl)(pcap_t *, u_char *, int) = NULL; |
| 12 | | static int (*pcap_set_datalink_dl)(pcap_t *, int) = NULL; |
| 13 | | static HMODULE handle = NULL; |
| 14 | | |
| 15 | | #include "emu.h" |
| 16 | | #include "osdnet.h" |
| 17 | | |
| 18 | | class netdev_pcap : public netdev |
| 19 | | { |
| 20 | | public: |
| 21 | | netdev_pcap(const char *name, class device_network_interface *ifdev, int rate); |
| 22 | | ~netdev_pcap(); |
| 23 | | |
| 24 | | int send(UINT8 *buf, int len); |
| 25 | | void set_mac(const char *mac); |
| 26 | | protected: |
| 27 | | int recv_dev(UINT8 **buf); |
| 28 | | private: |
| 29 | | pcap_t *m_p; |
| 30 | | }; |
| 31 | | |
| 32 | | netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate) |
| 33 | | : netdev(ifdev, rate) |
| 34 | | { |
| 35 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 36 | | m_p = pcap_open_live_dl(name, 65535, 1, -1, errbuf); |
| 37 | | if(!m_p) |
| 38 | | { |
| 39 | | logerror("Unable to open %s: %s\n", name, errbuf); |
| 40 | | return; |
| 41 | | } |
| 42 | | if(pcap_set_datalink_dl(m_p, DLT_EN10MB) == -1) |
| 43 | | { |
| 44 | | logerror("Unable to set %s to ethernet", name); |
| 45 | | pcap_close_dl(m_p); |
| 46 | | m_p = NULL; |
| 47 | | return; |
| 48 | | } |
| 49 | | set_mac(get_mac()); |
| 50 | | } |
| 51 | | |
| 52 | | void netdev_pcap::set_mac(const char *mac) |
| 53 | | { |
| 54 | | char filter[256]; |
| 55 | | struct bpf_program fp; |
| 56 | | if(!m_p) return; |
| 57 | | 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]); |
| 58 | | pcap_compile_dl(m_p, &fp, filter, 1, 0); |
| 59 | | pcap_setfilter_dl(m_p, &fp); |
| 60 | | } |
| 61 | | |
| 62 | | int netdev_pcap::send(UINT8 *buf, int len) |
| 63 | | { |
| 64 | | if(!m_p) return 0; |
| 65 | | return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; |
| 66 | | } |
| 67 | | |
| 68 | | int netdev_pcap::recv_dev(UINT8 **buf) |
| 69 | | { |
| 70 | | struct pcap_pkthdr *header; |
| 71 | | if(!m_p) return 0; |
| 72 | | return (pcap_next_ex_dl(m_p, &header, (const u_char **)buf) == 1)?header->len:0; |
| 73 | | } |
| 74 | | |
| 75 | | netdev_pcap::~netdev_pcap() |
| 76 | | { |
| 77 | | if(m_p && handle) pcap_close_dl(m_p); |
| 78 | | } |
| 79 | | |
| 80 | | static CREATE_NETDEV(create_pcap) |
| 81 | | { |
| 82 | | class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate)); |
| 83 | | return dynamic_cast<netdev *>(dev); |
| 84 | | } |
| 85 | | |
| 86 | | void init_pcap() |
| 87 | | { |
| 88 | | pcap_if_t *devs; |
| 89 | | char errbuf[PCAP_ERRBUF_SIZE]; |
| 90 | | handle = NULL; |
| 91 | | |
| 92 | | try |
| 93 | | { |
| 94 | | if(!(handle = LoadLibrary(L"wpcap.dll"))) throw GetLastError(); |
| 95 | | if(!(pcap_findalldevs_dl = (int (*)(pcap_if_t **, char *))GetProcAddress(handle, "pcap_findalldevs"))) |
| 96 | | throw GetLastError(); |
| 97 | | if(!(pcap_open_live_dl = (pcap_t* (*)(const char *, int, int, int, char *))GetProcAddress(handle, "pcap_open_live"))) |
| 98 | | throw GetLastError(); |
| 99 | | if(!(pcap_next_ex_dl = (int (*)(pcap_t *, struct pcap_pkthdr **, const u_char **))GetProcAddress(handle, "pcap_next_ex"))) |
| 100 | | throw GetLastError(); |
| 101 | | if(!(pcap_compile_dl = (int (*)(pcap_t *, struct bpf_program *, char *, int, bpf_u_int32))GetProcAddress(handle, "pcap_compile"))) |
| 102 | | throw GetLastError(); |
| 103 | | if(!(pcap_close_dl = (void (*)(pcap_t *))GetProcAddress(handle, "pcap_close"))) |
| 104 | | throw GetLastError(); |
| 105 | | if(!(pcap_setfilter_dl = (int (*)(pcap_t *, struct bpf_program *))GetProcAddress(handle, "pcap_setfilter"))) |
| 106 | | throw GetLastError(); |
| 107 | | if(!(pcap_sendpacket_dl = (int (*)(pcap_t *, u_char *, int))GetProcAddress(handle, "pcap_sendpacket"))) |
| 108 | | throw GetLastError(); |
| 109 | | if(!(pcap_set_datalink_dl = (int (*)(pcap_t *, int))GetProcAddress(handle, "pcap_set_datalink"))) |
| 110 | | throw GetLastError(); |
| 111 | | } |
| 112 | | catch (DWORD e) |
| 113 | | { |
| 114 | | FreeLibrary(handle); |
| 115 | | osd_printf_verbose("Unable to load winpcap: %lx\n", e); |
| 116 | | return; |
| 117 | | } |
| 118 | | if(pcap_findalldevs_dl(&devs, errbuf) == -1) |
| 119 | | { |
| 120 | | FreeLibrary(handle); |
| 121 | | osd_printf_verbose("Unable to get network devices: %s\n", errbuf); |
| 122 | | return; |
| 123 | | } |
| 124 | | |
| 125 | | while(devs) |
| 126 | | { |
| 127 | | add_netdev(devs->name, devs->description, create_pcap); |
| 128 | | devs = devs->next; |
| 129 | | } |
| 130 | | } |
| 131 | | |
| 132 | | void deinit_pcap() |
| 133 | | { |
| 134 | | clear_netdev(); |
| 135 | | FreeLibrary(handle); |
| 136 | | handle = NULL; |
| 137 | | } |