--- gvpe/src/device-linux.C 2003/03/01 15:53:03 1.1 +++ gvpe/src/device-linux.C 2005/03/23 21:55:39 1.12 @@ -1,7 +1,10 @@ /* device-linux.C -- Interaction with Linux tun/tap device + Copyright (C) 2003-2005 Marc Lehmann - This program is free software; you can redistribute it and/or modify + This file is part of GVPE. + + GVPE is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. @@ -12,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software + along with gvpe; if not, write to the Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -30,8 +33,10 @@ #include #include +#include + #ifdef LINUX_IF_TUN_H -#include LINUX_IF_TUN_H +# include LINUX_IF_TUN_H #else #include #endif @@ -41,6 +46,23 @@ #include "conf.h" +#if TEST_ETHEREMU +# define IF_istun +# include "ether_emu.C" +#endif + +const char * +tap_device::info () +{ + return _("Linux tun/tap device"); +} + +const char * +tap_device::if_up () +{ + return "/sbin/ifconfig $IFNAME hw ether $MAC mtu $MTU up"; +} + tap_device::tap_device () { struct ifreq ifr; @@ -52,11 +74,15 @@ if (fd < 0) { slog (L_ERR, _("could not open device %s: %s"), device, strerror (errno)); - exit (1); + exit (EXIT_FAILURE); } memset (&ifr, 0, sizeof (ifr)); +#if TEST_ETHEREMU + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; +#else ifr.ifr_flags = IFF_TAP | IFF_NO_PI; +#endif if (conf.ifname) strncpy (ifr.ifr_name, conf.ifname, IFNAMSIZ); @@ -71,12 +97,11 @@ else { slog (L_CRIT, _("unable to configure tun/tap interface: %s"), strerror (errno)); - exit (1); + exit (EXIT_FAILURE); } - if (conf.ifpersist) - if (ioctl (fd, TUNSETPERSIST, 1)) - slog (L_WARN, _("cannot set persistent mode for device %s: %s"), ifrname, strerror (errno)); + if (ioctl (fd, TUNSETPERSIST, conf.ifpersist ? 1 : 0)) + slog (L_WARN, _("cannot set persistency mode for device %s: %s"), ifrname, strerror (errno)); slog (L_DEBUG, _("%s is a %s"), device, info ()); } @@ -91,23 +116,46 @@ { tap_packet *pkt = new tap_packet; +#if TEST_ETHEREMU + pkt->len = read (fd, &((*pkt)[14]), MAX_MTU - 14); +#else pkt->len = read (fd, &((*pkt)[0]), MAX_MTU); +#endif if (pkt->len <= 0) { + delete pkt; slog (L_ERR, _("error while reading from %s %s: %s"), info (), DEFAULT_DEVICE, strerror (errno)); - free (pkt); return 0; } +#if TEST_ETHEREMU + pkt->len += 14; + + // assume ipv4 + (*pkt)[12] = 0x08; + (*pkt)[13] = 0x00; + + if (!ether_emu.tun_to_tap (pkt)) + { + delete pkt; + return 0; + } +#endif + return pkt; } void tap_device::send (tap_packet *pkt) { +#if TEST_ETHEREMU + if (ether_emu.tap_to_tun (pkt) && + write (fd, &((*pkt)[14]), pkt->len - 14) < 0) +#else if (write (fd, &((*pkt)[0]), pkt->len) < 0) +#endif slog (L_ERR, _("can't write to %s %s: %s"), info (), DEFAULT_DEVICE, strerror (errno)); }