Closed ghost closed 7 years ago
Found it!!!
The first issue is, that stdout is buffered, therefore the log output created by printf is shown, when the buffer is full. That delays the output, and messages send to stderr may be shown earlier. Therefore I changed the buffering of stdout and stderr to line buffering.
diff --git a/src/ubridge.c b/src/ubridge.c
index 39f1dc3..ccbf13a 100644
--- a/src/ubridge.c
+++ b/src/ubridge.c
@@ -338,6 +338,9 @@ int main(int argc, char **argv)
char *index;
size_t len;
+ setvbuf(stdout, NULL, _IOLBF, 0);
+ setvbuf(stderr, NULL, _IOLBF, 0);
+
printf("uBridge version %s running with %s\n", VERSION, pcap_lib_version());
while ((opt = getopt(argc, argv, "hved:f:H:")) != -1) {
switch (opt) {
That gives a better log output:
/Users/behlers/GNS3/projects/osxtap/project-files/builtin/831e1592-8482-4b13-8605-2cfcca83c5c3# cat ubridge.log
uBridge version 0.9.13 running with libpcap version 1.5.3 - Apple version 54
Hypervisor TCP control server started (IP 192.168.1.10 port 50401).
UDP tunnel connecting from local port 10000 to IPv4 addresss 192.168.1.10 on port 10001
Source NIO listener thread for 831e1592-8482-4b13-8605-2cfcca83c5c3-3 has started
Destination NIO listener thread for 831e1592-8482-4b13-8605-2cfcca83c5c3-3 has started
recv: Input/output error
Destination NIO listener thread for 831e1592-8482-4b13-8605-2cfcca83c5c3-3 has stopped
That shows, that the read from the TAP devices returns EIO and therefore the destination listener thread has stopped. According to the TUNTAP FAQ http://tuntaposx.sourceforge.net/faq.xhtml (last question) this is normal, the user hasn't activated the TAP IP interface yet. So I updated nio_tap.c to ignore EIO on OSX.
diff --git a/src/nio_tap.c b/src/nio_tap.c
index d6cfdcb..b7eb61e 100644
--- a/src/nio_tap.c
+++ b/src/nio_tap.c
@@ -111,7 +111,15 @@ static ssize_t nio_tap_send(nio_tap_t *nio_tap, void *pkt, size_t pkt_len)
static ssize_t nio_tap_recv(nio_tap_t *nio_tap, void *pkt, size_t max_len)
{
+#ifdef __APPLE__
+ /* ignore EIO error, TAP IP interface is not yet up */
+ ssize_t ret;
+ while ((ret = read(nio_tap->fd, pkt, max_len)) < 0 && errno == EIO)
+ sleep(1);
+ return ret;
+#else
return (read(nio_tap->fd, pkt, max_len));
+#endif
}
/* Create a new NIO TAP */
And the PR https://github.com/GNS3/dynamips/pull/79 might be valuable here as well. That should allow to use "tap0" as the TAP device, instead of "/dev/tap0".
Instead of polling with read() for an active interface, select() can be used (at least on my OS X v10.11).
The patch would then look like this:
diff --git a/src/nio_tap.c b/src/nio_tap.c
index d6cfdcb..57c2f71 100644
--- a/src/nio_tap.c
+++ b/src/nio_tap.c
@@ -111,6 +111,14 @@ static ssize_t nio_tap_send(nio_tap_t *nio_tap, void *pkt, size_t pkt_len)
static ssize_t nio_tap_recv(nio_tap_t *nio_tap, void *pkt, size_t max_len)
{
+#ifdef __APPLE__
+ /* wait for an active IP interface and incoming data */
+ fd_set tap_fd_set;
+ FD_ZERO(&tap_fd_set);
+ FD_SET(nio_tap->fd, &tap_fd_set);
+ if (select(nio_tap->fd + 1, &tap_fd_set, NULL, NULL, NULL) < 0)
+ perror("nio_tap_recv: select");
+#endif
return (read(nio_tap->fd, pkt, max_len));
}
Thanks a lot! :+1:
Well, integration of https://github.com/GNS3/dynamips/pull/79 isn't that simple. NETIO_DEV_MAXLEN is used in dynamips, in ubridge it's named NIO_DEV_MAXLEN. So currently ubridge doesn't compile.
Another comment to my perror("nio_tap_recv: select");
: Maybe a simple return -1
is better. The other send/recv functions normally return a status, errors are printed in the calling function. But for me both variants are fine.
I will make the changes soon. I compiled on Linux so I couldn't test the changes before I commit.
ubridge 0.9.11 and 0.9.12, GNS3 version 2.0.4dev1 on Darwin (64-bit)
While TAP connections work in GNS3 v1.5, I wasn't able to use them on GNS3 V2.0, see also https://www.gns3.com/qa/how-to-connect-os-x-terminal-to-
Test project, router and cloud are running on the local OS X:
Cloud configuration:
Other than in linux the TAP interfaces are not automatically detected in OS X. I have to use "/dev/tap0", otherwise the TAP device won't open, "tap0" as TAP device doesn't work.
After opening the TAP device I configured 10.1.1.1/24 on OS X and 10.1.1.100/24 on the router. But the router sees no (really 0) packets from OS X. Therefore no communication can happen.
In debug mode the ubridge.log looks like this:
The hypervisor shows the following: