Previous 199869 Revisions Next

r21457 Wednesday 27th February, 2013 at 02:14:55 UTC by R. Belmont
Ethernet: Make pcap work on Mac OS X & disable unnecessary packet filtering. [Rob Braun]
[src/osd/sdl]netdev_pcap_osx.c* sdl.mak

trunk/src/osd/sdl/sdl.mak
r21456r21457
731731endif
732732
733733ifeq ($(SDL_NETWORK),pcap)
734OSDOBJS += \
735   $(SDLOBJ)/netdev.o \
736   $(SDLOBJ)/netdev_pcap.o
734OSDOBJS += $(SDLOBJ)/netdev.o
737735
736ifeq ($(TARGETOS),macosx)
737OSDOBJS += $(SDLOBJ)/netdev_pcap_osx.o
738else
739OSDOBJS += $(SDLOBJ)/netdev_pcap.o
740endif
741
738742DEFS += -DSDLMAME_NETWORK -DSDLMAME_NET_PCAP
739743ifneq ($(TARGETOS),win32)
740744LIBS += -lpcap
trunk/src/osd/sdl/netdev_pcap_osx.c
r0r21457
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
11struct netdev_pcap_context {
12   UINT8 *pkt;
13   int len;
14   pcap_t *p;
15
16   UINT8 packets[32][1600];
17   int packetlens[32];
18   int head;
19   int tail;
20};
21
22class netdev_pcap : public netdev
23{
24public:
25   netdev_pcap(const char *name, class device_network_interface *ifdev, int rate);
26   ~netdev_pcap();
27
28   int send(UINT8 *buf, int len);
29   void set_mac(const char *mac);
30protected:
31   int recv_dev(UINT8 **buf);
32private:
33   pcap_t *m_p;
34   struct netdev_pcap_context m_ctx;
35   pthread_t m_thread;
36};
37
38static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) {
39   struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user;
40
41   if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) {
42      printf("buffer full, dropping packet\n");
43      return;
44   }
45   memcpy(ctx->packets[ctx->head], bytes, h->len);
46   ctx->packetlens[ctx->head] = h->len;
47   OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head);
48}
49
50static void *netdev_pcap_blocker(void *arg) {
51   struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg;
52
53   while(1) {
54      pcap_dispatch(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx);
55   }
56
57   return 0;
58}
59
60netdev_pcap::netdev_pcap(const char *name, class device_network_interface *ifdev, int rate)
61   : netdev(ifdev, rate)
62{
63   char errbuf[PCAP_ERRBUF_SIZE];
64   m_p = pcap_open_live(name, 65535, 1, 1, errbuf);
65   if(!m_p)
66   {
67      mame_printf_verbose("Unable to open %s: %s\n", name, errbuf);
68      return;
69   }
70   if(pcap_set_datalink(m_p, DLT_EN10MB) == -1)
71   {
72      mame_printf_verbose("Unable to set %s to ethernet", name);
73      pcap_close(m_p);
74      m_p = NULL;
75      return;
76   }
77   set_mac(get_mac());
78
79   m_ctx.head = 0;
80   m_ctx.tail = 0;
81   m_ctx.p = m_p;
82   pthread_create(&m_thread, NULL, netdev_pcap_blocker, &m_ctx);
83}
84
85void netdev_pcap::set_mac(const char *mac)
86{
87   char filter[256];
88   struct bpf_program fp;
89   if(!m_p) return;
90   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]);
91   if(pcap_compile(m_p, &fp, filter, 1, 0) == -1) {
92      mame_printf_verbose("Error with pcap_compile");
93   }
94   if(pcap_setfilter(m_p, &fp) == -1) {
95      mame_printf_verbose("Error with pcap_setfilter");
96   }
97}
98
99int netdev_pcap::send(UINT8 *buf, int len)
100{
101   if(!m_p) return 0;
102   return (!pcap_sendpacket(m_p, buf, len))?len:0;
103}
104
105int netdev_pcap::recv_dev(UINT8 **buf)
106{
107   UINT8 pktbuf[2048];
108   int ret;
109
110   // Empty
111   if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) {
112      return 0;
113   }
114
115   memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]);
116   ret = m_ctx.packetlens[m_ctx.tail];
117   OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail);
118   *buf = pktbuf;
119   return ret;
120}
121
122netdev_pcap::~netdev_pcap()
123{
124   if(m_p) pcap_close(m_p);
125}
126
127static CREATE_NETDEV(create_pcap)
128{
129   class netdev_pcap *dev = global_alloc(netdev_pcap(ifname, ifdev, rate));
130   return dynamic_cast<netdev *>(dev);
131}
132
133void init_pcap()
134{
135   pcap_if_t *devs;
136   char errbuf[PCAP_ERRBUF_SIZE];
137   if(pcap_findalldevs(&devs, errbuf) == -1)
138   {
139      mame_printf_verbose("Unable to get network devices: %s\n", errbuf);
140      return;
141   }
142
143   if (devs)
144   {
145      while(devs->next)
146      {
147         add_netdev(devs->name, devs->description ? devs->description : devs->name, create_pcap);
148         devs = devs->next;
149      }
150   }
151}
152
153void deinit_pcap()
154{
155   clear_netdev();
156}
157
158#endif  // SDLMAME_WIN32
Property changes on: trunk/src/osd/sdl/netdev_pcap_osx.c
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain

Previous 199869 Revisions Next


© 1997-2024 The MAME Team