summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.mac2
-rw-r--r--node/EthernetTap.cpp38
-rw-r--r--tap-mac/tuntap/src/tuntap.cc8
3 files changed, 33 insertions, 15 deletions
diff --git a/Makefile.mac b/Makefile.mac
index f3c6136f..6955710e 100644
--- a/Makefile.mac
+++ b/Makefile.mac
@@ -17,7 +17,7 @@ CXXFLAGS=$(CFLAGS) -fno-rtti
include objects.mk
-all: one cli mac-tap
+all: one cli
one: $(OBJS)
$(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS)
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp
index 226d0397..fadd8e50 100644
--- a/node/EthernetTap.cpp
+++ b/node/EthernetTap.cpp
@@ -533,6 +533,7 @@ void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const
*((uint16_t *)(putBuf + 12)) = htons((uint16_t)etherType);
memcpy(putBuf + 14,data,len);
len += 14;
+
int n = ::write(_fd,putBuf,len);
if (n <= 0) {
LOG("error writing packet to Ethernet tap device: %s",strerror(errno));
@@ -658,7 +659,8 @@ void EthernetTap::threadMain()
{
fd_set readfds,nullfds;
MAC to,from;
- char getBuf[4096 + 14];
+ int n,nfds,r;
+ char getBuf[8194];
Buffer<4096> data;
// Wait for a moment after startup -- wait for Network to finish
@@ -667,8 +669,9 @@ void EthernetTap::threadMain()
FD_ZERO(&readfds);
FD_ZERO(&nullfds);
- int nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
+ nfds = (int)std::max(_shutdownSignalPipe[0],_fd) + 1;
+ r = 0;
for(;;) {
FD_SET(_shutdownSignalPipe[0],&readfds);
FD_SET(_fd,&readfds);
@@ -678,20 +681,31 @@ void EthernetTap::threadMain()
break;
if (FD_ISSET(_fd,&readfds)) {
- int n = (int)::read(_fd,getBuf,_mtu + 14);
-
- if (n > 14) {
- for(int i=0;i<6;++i)
- to.data[i] = (unsigned char)getBuf[i];
- for(int i=0;i<6;++i)
- from.data[i] = (unsigned char)getBuf[i + 6];
- data.copyFrom(getBuf + 14,(unsigned int)n - 14);
- _handler(_arg,from,to,ntohs(((const uint16_t *)getBuf)[6]),data);
- } else if (n < 0) {
+ n = (int)::read(_fd,getBuf + r,sizeof(getBuf) - r);
+ if (n < 0) {
if ((errno != EINTR)&&(errno != ETIMEDOUT)) {
TRACE("unexpected error reading from tap: %s",strerror(errno));
break;
}
+ } else {
+ // Some tap drivers like to send the ethernet frame and the
+ // payload in two chunks, so handle that by accumulating
+ // data until we have at least a frame.
+ r += n;
+ if (r > 14) {
+ if (r > (_mtu + 14)) // sanity check for weird TAP behavior on some platforms
+ r = _mtu + 14;
+ for(int i=0;i<6;++i)
+ to.data[i] = (unsigned char)getBuf[i];
+ for(int i=0;i<6;++i)
+ from.data[i] = (unsigned char)getBuf[i + 6];
+ unsigned int etherType = ntohs(((const uint16_t *)getBuf)[6]);
+ if (etherType != 0x8100) { // VLAN tagged frames are not supported!
+ data.copyFrom(getBuf + 14,(unsigned int)r - 14);
+ _handler(_arg,from,to,etherType,data);
+ }
+ r = 0;
+ }
}
}
}
diff --git a/tap-mac/tuntap/src/tuntap.cc b/tap-mac/tuntap/src/tuntap.cc
index 941de94c..7fdbb795 100644
--- a/tap-mac/tuntap/src/tuntap.cc
+++ b/tap-mac/tuntap/src/tuntap.cc
@@ -648,7 +648,9 @@ tuntap_interface::cdev_write(uio_t uio, int ioflag)
mb = first;
while (uio_resid(uio) > 0) {
/* copy a chunk. enforce mtu (don't know if this is correct behaviour) */
- chunk_len = min(ifnet_mtu(ifp), min(uio_resid(uio), mlen));
+ // ... evidently not :) -- Adam Ierymenko <adam.ierymenko@zerotier.com>
+ //chunk_len = min(ifnet_mtu(ifp), min(uio_resid(uio), mlen));
+ chunk_len = min(uio_resid(uio),mlen);
error = uiomove((caddr_t) mbuf_data(mb), chunk_len, uio);
if (error) {
log(LOG_ERR, "tuntap: could not copy data from userspace: %d\n", error);
@@ -664,7 +666,9 @@ tuntap_interface::cdev_write(uio_t uio, int ioflag)
copied += chunk_len;
/* if done, break the loop */
- if (uio_resid(uio) <= 0 || copied >= ifnet_mtu(ifp))
+ //if (uio_resid(uio) <= 0 || copied >= ifnet_mtu(ifp))
+ // break;
+ if (uio_resid(uio) <= 0)
break;
/* allocate a new mbuf if the current is filled */