diff -uN /opt/bzr/grub/grub-core/net/drivers/emu/emunet.c grub-core/net/drivers/emu/emunet.c --- /opt/bzr/grub/grub-core/net/drivers/emu/emunet.c 2013-01-31 03:44:09.248831000 +0100 +++ grub-core/net/drivers/emu/emunet.c 2013-01-31 08:57:26.999999900 +0100 @@ -21,8 +21,7 @@ #include #include #include -#include -#include +#include "emutuntap.h" #include #include #include @@ -31,15 +30,19 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static int fd; +#include "emutuntap.c" -static grub_err_t +/* _xxx to avoid "declaration of 'xxx' shadows a global declaration" warning */ +static char _dev[IFNAMSIZ]; +static int _fd; + +static grub_err_t send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { ssize_t actual; - actual = write (fd, pack->data, pack->tail - pack->data); + actual = tun_write (_fd, pack->data, pack->tail - pack->data); if (actual < 0) return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); @@ -65,7 +68,7 @@ return NULL; } - actual = read (fd, nb->data, 1536); + actual = tun_read (_fd, nb->data, 1536); if (actual < 0) { grub_netbuff_free (nb); @@ -76,14 +79,14 @@ return nb; } -static struct grub_net_card_driver emudriver = +static struct grub_net_card_driver emudriver = { .name = "emu", .send = send_card_buffer, .recv = get_card_packet }; -static struct grub_net_card emucard = +static struct grub_net_card emucard = { .name = "emu0", .driver = &emudriver, @@ -97,26 +100,17 @@ GRUB_MOD_INIT(emunet) { - struct ifreq ifr; - fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); - if (fd < 0) + _fd = tun_open(_dev, IF_MODE_TAP); + if (_fd < 0) return; - grub_memset (&ifr, 0, sizeof (ifr)); - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if (ioctl (fd, TUNSETIFF, &ifr) < 0) - { - close (fd); - fd = -1; - return; - } grub_net_card_register (&emucard); } GRUB_MOD_FINI(emunet) { - if (fd >= 0) + if (_fd >= 0) { - close (fd); + tun_close (_fd, _dev); grub_net_card_unregister (&emucard); } } diff -uN /opt/bzr/grub/grub-core/net/drivers/emu/emutuntap.c grub-core/net/drivers/emu/emutuntap.c --- /opt/bzr/grub/grub-core/net/drivers/emu/emutuntap.c 1970-01-01 01:00:00.000000000 +0100 +++ grub-core/net/drivers/emu/emutuntap.c 2013-01-31 08:57:48.999999900 +0100 @@ -0,0 +1,365 @@ +/* from http://svn.unix-ag.uni-kl.de/vpnc/trunk/sysdep.c */ + +#if defined(__CYGWIN__) + +/* + * Overlapped structures for asynchronous read and write + */ +static OVERLAPPED overlap_read, overlap_write; + +typedef enum { + SEARCH_IF_GUID_FROM_NAME, + SEARCH_IF_NAME_FROM_GUID +} search_if_en; + +/* + * Get interface guid/name from registry + */ +static char *search_if(char *value, char *key, search_if_en type) +{ + int i = 0; + LONG status; + DWORD len; + HKEY net_conn_key; + BOOL found = FALSE; + char guid[256]; + char ifname[256]; + char conn_string[512]; + HKEY conn_key; + DWORD value_type; + + if (!value || !key) { + return NULL; + } + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + NETWORK_CONNECTIONS_KEY, + 0, + KEY_READ, + &net_conn_key); + + if (status != ERROR_SUCCESS) { + printf("Error opening registry key: %s\n", NETWORK_CONNECTIONS_KEY); + return NULL; + } + + while (!found) { + len = sizeof(guid); + status = RegEnumKeyEx(net_conn_key, i++, guid, &len, + NULL, NULL, NULL, NULL); + if (status == ERROR_NO_MORE_ITEMS) { + break; + } else if (status != ERROR_SUCCESS) { + continue; + } + snprintf(conn_string, sizeof(conn_string), + "%s\\%s\\Connection", + NETWORK_CONNECTIONS_KEY, guid); + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + conn_string, + 0, + KEY_READ, + &conn_key); + if (status != ERROR_SUCCESS) { + continue; + } + len = sizeof(ifname); + status = RegQueryValueEx(conn_key, "Name", NULL, + &value_type, (LPBYTE) ifname, &len); + if (status != ERROR_SUCCESS || value_type != REG_SZ) { + RegCloseKey(conn_key); + continue; + } + + switch (type) { + case SEARCH_IF_GUID_FROM_NAME: + if (!grub_strcmp(key, ifname)) { + grub_strcpy(value, guid); + found = TRUE; + } + break; + case SEARCH_IF_NAME_FROM_GUID: + if (!grub_strcmp(key, guid)) { + grub_strcpy(value, ifname); + found = TRUE; + } + break; + default: + break; + } + RegCloseKey(conn_key); + } + RegCloseKey(net_conn_key); + + if (found) { + return value; + } + + return NULL; +} + +/* + * Open the TUN/TAP device with the provided guid + */ +static int open_tun_device (char *guid __attribute__ ((unused)), + char *dev __attribute__ ((unused)), enum if_mode_enum mode) +{ + HANDLE handle; + ULONG len, status, info[3]; + char device_path[512]; + + printf("Device: %s\n", dev); + + if (mode == IF_MODE_TUN) { + printf("TUN mode is not supported\n"); + return -1; + } + + /* + * Let's try to open Windows TAP-Win32 adapter + */ + snprintf(device_path, sizeof(device_path), "%s%s%s", + USERMODEDEVICEDIR, guid, TAPSUFFIX); + + handle = CreateFile(device_path, + GENERIC_READ | GENERIC_WRITE, + 0, /* Don't let other processes share or open + the resource until the handle's been closed */ + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, + 0); + + if (handle == INVALID_HANDLE_VALUE) { + return -1; + } + + /* + * get driver version info + */ + grub_memset(info, 0, sizeof(info)); + if (DeviceIoControl(handle, TAP_IOCTL_GET_VERSION, + &info, sizeof(info), + &info, sizeof(info), &len, NULL)) { + printf("TAP-Win32 Driver Version %d.%d %s\n", + (int) info[0], + (int) info[1], + (info[2] ? "(DEBUG)" : "")); + } + + /* + * Set driver media status to 'connected' + */ + status = TRUE; + if (!DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS, + &status, sizeof(status), + &status, sizeof(status), &len, NULL)) { + printf("WARNING: The TAP-Win32 driver rejected a " + "TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.\n"); + } + + /* + * Initialize overlapped structures + */ + overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!overlap_read.hEvent || !overlap_write.hEvent) { + return -1; + } + + /* + * Return fd + */ + return cygwin_attach_handle_to_fd(NULL, -1, handle, 1, GENERIC_READ | GENERIC_WRITE); +} + +/* + * Allocate TUN device, returns opened fd. + * Stores dev name in the first arg (must be large enough). + */ +int tun_open (char *dev, enum if_mode_enum mode) +{ + int fd = -1; + HKEY unit_key; + char guid[256]; + char comp_id[256]; + char enum_name[256]; + char unit_string[512]; + BOOL found = FALSE; + HKEY adapter_key; + DWORD value_type; + LONG status; + DWORD len; + + if (!dev) { + return -1; + } + + /* + * Device name has been provided. Open such device. + */ + if (*dev != '\0') { + if (!search_if(guid, dev, SEARCH_IF_GUID_FROM_NAME)) { + return -1; + } + return open_tun_device(guid, dev, mode); + } + + /* + * Device name has non been specified. Look for one available! + */ + int i = 0; + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + ADAPTER_KEY, + 0, + KEY_READ, + &adapter_key); + if (status != ERROR_SUCCESS) { + printf("Error opening registry key: %s", ADAPTER_KEY); + return -1; + } + + while (!found) { + len = sizeof(enum_name); + status = RegEnumKeyEx(adapter_key, i++, + enum_name, &len, + NULL, NULL, NULL, NULL); + if (status == ERROR_NO_MORE_ITEMS) { + break; + } else if (status != ERROR_SUCCESS) { + continue; + } + snprintf(unit_string, sizeof(unit_string), "%s\\%s", + ADAPTER_KEY, enum_name); + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + unit_string, + 0, + KEY_READ, + &unit_key); + if (status != ERROR_SUCCESS) { + continue; + } + len = sizeof(comp_id); + status = RegQueryValueEx(unit_key, + "ComponentId", NULL, + &value_type, (LPBYTE) comp_id, &len); + if (status != ERROR_SUCCESS || value_type != REG_SZ) { + RegCloseKey(unit_key); + continue; + } + len = sizeof(guid); + status = RegQueryValueEx(unit_key, + "NetCfgInstanceId", NULL, + &value_type, (LPBYTE) guid, &len); + if (status != ERROR_SUCCESS || value_type != REG_SZ) { + RegCloseKey(unit_key); + continue; + } + + int j = 0; + while (TAP_COMPONENT_ID[j]) { + if (!grub_strcmp(comp_id, TAP_COMPONENT_ID[j])) { + break; + } + j++; + } + if (!TAP_COMPONENT_ID[j]) { + RegCloseKey(unit_key); + continue; + } + + /* + * Let's try to open this device + */ + search_if(dev, guid, SEARCH_IF_NAME_FROM_GUID); + fd = open_tun_device(guid, dev, mode); + if (fd != -1) { + found = TRUE; + } + + RegCloseKey(unit_key); + } + RegCloseKey(adapter_key); + + return fd; +} + +int tun_close(int fd, char *dev __attribute__ ((unused))) +{ + return CloseHandle((HANDLE) get_osfhandle(fd)); +} + +int tun_read(int fd, unsigned char *buf, int len) +{ + DWORD read_size; + + ResetEvent(overlap_read.hEvent); + if (ReadFile((HANDLE) get_osfhandle(fd), buf, len, &read_size, &overlap_read)) { + return read_size; + } + switch (GetLastError()) { + case ERROR_IO_PENDING: + WaitForSingleObject(overlap_read.hEvent, INFINITE); + GetOverlappedResult((HANDLE) get_osfhandle(fd), &overlap_read, &read_size, FALSE); + return read_size; + break; + default: + break; + } + + return -1; +} + +int tun_write(int fd, unsigned char *buf, int len) +{ + DWORD write_size; + + ResetEvent(overlap_write.hEvent); + if (WriteFile((HANDLE) get_osfhandle(fd), + buf, + len, + &write_size, + &overlap_write)) { + return write_size; + } + switch (GetLastError()) { + case ERROR_IO_PENDING: + WaitForSingleObject(overlap_write.hEvent, INFINITE); + GetOverlappedResult((HANDLE) get_osfhandle(fd), &overlap_write, + &write_size, FALSE); + return write_size; + break; + default: + break; + } + + return -1; +} + +#else + +int tun_open(char *dev, enum if_mode_enum mode) +{ + struct ifreq ifr; + int fd; + + /* sysdep.c doesn't have O_NONBLOCK */ + fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); + if (fd < 0) + return -1; + + grub_memset (&ifr, 0, sizeof (ifr)); + ifr.ifr_flags = ((mode == IF_MODE_TUN) ? IFF_TUN : IFF_TAP) | IFF_NO_PI; + if (*dev) + grub_strncpy(ifr.ifr_name, dev, IFNAMSIZ); + + if (ioctl (fd, TUNSETIFF, &ifr) < 0) { + close (fd); + return -1; + } + + grub_strcpy(dev, ifr.ifr_name); + return fd; +} + +#endif diff -uN /opt/bzr/grub/grub-core/net/drivers/emu/emutuntap.h grub-core/net/drivers/emu/emutuntap.h --- /opt/bzr/grub/grub-core/net/drivers/emu/emutuntap.h 1970-01-01 01:00:00.000000000 +0100 +++ grub-core/net/drivers/emu/emutuntap.h 2013-01-31 08:56:47.999999900 +0100 @@ -0,0 +1,41 @@ +/* from http://svn.unix-ag.uni-kl.de/vpnc/trunk/sysdep.c */ + +#if defined(__CYGWIN__) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tap-win32.h" + +#ifdef IFNAMSIZ +#undef IFNAMSIZ +#endif +#define IFNAMSIZ 256 + +#define printf(fmt, ...) +#define snprintf(fmt, ...) + +int tun_close(int fd, char *dev); +int tun_write(int fd, unsigned char *buf, int len); +int tun_read(int fd, unsigned char *buf, int len); +#else +#include +#include + +#define tun_close(fd,dev) close(fd) +#define tun_read(fd,buf,len) read(fd,buf,len) +#define tun_write(fd,buf,len) write(fd,buf,len) +#endif + +enum if_mode_enum { + IF_MODE_TUN, + IF_MODE_TAP +}; + +int tun_open(char *dev, enum if_mode_enum mode); diff -uN /opt/bzr/grub/grub-core/net/drivers/emu/tap-win32.h grub-core/net/drivers/emu/tap-win32.h --- /opt/bzr/grub/grub-core/net/drivers/emu/tap-win32.h 1970-01-01 01:00:00.000000000 +0100 +++ grub-core/net/drivers/emu/tap-win32.h 2013-01-31 06:44:38.999999900 +0100 @@ -0,0 +1,87 @@ +/* from http://svn.unix-ag.uni-kl.de/vpnc/trunk/sysdep.c */ + +/* + * This file has been borrowed from the Win32 OpenVPN Tap driver + * (common.h is the original file name). + * + * TAP-Win32 -- A kernel driver to provide virtual tap device functionality + * on Windows. Originally derived from the CIPE-Win32 + * project by Damion K. Wilson, with extensive modifications by + * James Yonan. + * + * All source code which derives from the CIPE-Win32 project is + * Copyright (C) Damion K. Wilson, 2003, and is released under the + * GPL version 2 (see below). + * + * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC, + * and is released under the GPL version 2 (see below). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* =============================================== + This file is included both by OpenVPN and + the TAP-Win32 driver and contains definitions + common to both. + =============================================== */ + +/* ============= + TAP IOCTLs + ============= */ + +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +/* Present in 8.1 */ + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +/* Added in 8.2 */ + +/* obsoletes TAP_IOCTL_CONFIG_POINT_TO_POINT */ +#define TAP_IOCTL_CONFIG_TUN TAP_CONTROL_CODE (10, METHOD_BUFFERED) + +/* ================= + Registry keys + ================= */ + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +/* ====================== + Filesystem prefixes + ====================== */ + +#define USERMODEDEVICEDIR "\\\\.\\Global\\" +#define SYSDEVICEDIR "\\Device\\" +#define USERDEVICEDIR "\\DosDevices\\Global\\" +#define TAPSUFFIX ".tap" + +/* ========================================================= + TAP_COMPONENT_ID -- These strings defines the TAP driver + types -- different component IDs can reside in the system + simultaneously. + ========================================================= */ + +static const char* TAP_COMPONENT_ID[] = { "tap0901", "tap0801", NULL };