18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  TAP-Win32 -- A kernel driver to provide virtual tap device functionality
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *               on Windows.  Originally derived from the CIPE-Win32
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *               project by Damion K. Wilson, with extensive modifications by
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *               James Yonan.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  All source code which derives from the CIPE-Win32 project is
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (C) Damion K. Wilson, 2003, and is released under the
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  GPL version 2 (see below).
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  All other source code is Copyright (C) James Yonan, 2003-2004,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  and is released under the GPL version 2 (see below).
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  This program is free software; you can redistribute it and/or modify
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  it under the terms of the GNU General Public License as published by
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  the Free Software Foundation; either version 2 of the License, or
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  (at your option) any later version.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  This program is distributed in the hope that it will be useful,
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  GNU General Public License for more details.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  You should have received a copy of the GNU General Public License
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  along with this program (see the file COPYING included with this
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  distribution); if not, write to the Free Software Foundation, Inc.,
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
30cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "net/net.h"
3134c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <windows.h>
347f661af7cfca4b7857d30d598923dd2095f78ff0Andrew Hsieh#include <winioctl.h>
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//=============
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// TAP IOCTLs
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//=============
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_CONTROL_CODE(request,method) \
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_GET_MAC               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE (2, METHOD_BUFFERED)
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_GET_MTU               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_GET_INFO              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE (6, METHOD_BUFFERED)
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_CONFIG_DHCP_MASQ      TAP_CONTROL_CODE (7, METHOD_BUFFERED)
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_GET_LOG_LINE          TAP_CONTROL_CODE (8, METHOD_BUFFERED)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//=================
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// Registry keys
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//=================
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//======================
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// Filesystem prefixes
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//======================
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define USERMODEDEVICEDIR "\\\\.\\Global\\"
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TAPSUFFIX         ".tap"
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//======================
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project// Compile time configuration
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//======================
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner//#define DEBUG_TAP_WIN32
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TUN_ASYNCHRONOUS_WRITES 1
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TUN_BUFFER_SIZE 1560
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TUN_MAX_BUFFER_COUNT 32
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The data member "buffer" must be the first element in the tun_buffer
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * structure. See the function, tap_win32_free_buffer.
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct tun_buffer_s {
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char buffer [TUN_BUFFER_SIZE];
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long read_size;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct tun_buffer_s* next;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} tun_buffer_t;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct tap_win32_overlapped {
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE handle;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE read_event;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE write_event;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE output_queue_semaphore;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE free_list_semaphore;
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    HANDLE tap_semaphore;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CRITICAL_SECTION output_queue_cs;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CRITICAL_SECTION free_list_cs;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OVERLAPPED read_overlapped;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    OVERLAPPED write_overlapped;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT];
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* free_list;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* output_queue_front;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* output_queue_back;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} tap_win32_overlapped_t;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic tap_win32_overlapped_t tap_overlapped;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic tun_buffer_t* get_buffer_from_free_list(tap_win32_overlapped_t* const overlapped)
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* buffer = NULL;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WaitForSingleObject(overlapped->free_list_semaphore, INFINITE);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EnterCriticalSection(&overlapped->free_list_cs);
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buffer = overlapped->free_list;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//    assert(buffer != NULL);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->free_list = buffer->next;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LeaveCriticalSection(&overlapped->free_list_cs);
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buffer->next = NULL;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buffer;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void put_buffer_on_free_list(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EnterCriticalSection(&overlapped->free_list_cs);
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    buffer->next = overlapped->free_list;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->free_list = buffer;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LeaveCriticalSection(&overlapped->free_list_cs);
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ReleaseSemaphore(overlapped->free_list_semaphore, 1, NULL);
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic tun_buffer_t* get_buffer_from_output_queue(tap_win32_overlapped_t* const overlapped, const int block)
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* buffer = NULL;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD result, timeout = block ? INFINITE : 0L;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    // Non-blocking call
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    result = WaitForSingleObject(overlapped->output_queue_semaphore, timeout);
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    switch (result)
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    {
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        // The semaphore object was signaled.
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case WAIT_OBJECT_0:
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            EnterCriticalSection(&overlapped->output_queue_cs);
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buffer = overlapped->output_queue_front;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            overlapped->output_queue_front = buffer->next;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if(overlapped->output_queue_front == NULL) {
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                overlapped->output_queue_back = NULL;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            LeaveCriticalSection(&overlapped->output_queue_cs);
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        // Semaphore was nonsignaled, so a time-out occurred.
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case WAIT_TIMEOUT:
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            // Cannot open another window.
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            break;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return buffer;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic tun_buffer_t* get_buffer_from_output_queue_immediate (tap_win32_overlapped_t* const overlapped)
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return get_buffer_from_output_queue(overlapped, 0);
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void put_buffer_on_output_queue(tap_win32_overlapped_t* const overlapped, tun_buffer_t* const buffer)
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    EnterCriticalSection(&overlapped->output_queue_cs);
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(overlapped->output_queue_front == NULL && overlapped->output_queue_back == NULL) {
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        overlapped->output_queue_front = overlapped->output_queue_back = buffer;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        buffer->next = NULL;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        overlapped->output_queue_back->next = buffer;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        overlapped->output_queue_back = buffer;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LeaveCriticalSection(&overlapped->output_queue_cs);
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ReleaseSemaphore(overlapped->output_queue_semaphore, 1, NULL);
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int is_tap_win32_dev(const char *guid)
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HKEY netcard_key;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LONG status;
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD len;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i = 0;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = RegOpenKeyEx(
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        HKEY_LOCAL_MACHINE,
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ADAPTER_KEY,
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        KEY_READ,
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &netcard_key);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (status != ERROR_SUCCESS) {
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return FALSE;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char enum_name[256];
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char unit_string[256];
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        HKEY unit_key;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char component_id_string[] = "ComponentId";
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char component_id[256];
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char net_cfg_instance_id_string[] = "NetCfgInstanceId";
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char net_cfg_instance_id[256];
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        DWORD data_type;
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = sizeof (enum_name);
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = RegEnumKeyEx(
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            netcard_key,
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i,
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            enum_name,
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            &len,
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL);
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status == ERROR_NO_MORE_ITEMS)
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (status != ERROR_SUCCESS) {
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return FALSE;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf (unit_string, sizeof(unit_string), "%s\\%s",
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  ADAPTER_KEY, enum_name);
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = RegOpenKeyEx(
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            HKEY_LOCAL_MACHINE,
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unit_string,
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            0,
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            KEY_READ,
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            &unit_key);
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status != ERROR_SUCCESS) {
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return FALSE;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = sizeof (component_id);
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            status = RegQueryValueEx(
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                unit_key,
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                component_id_string,
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                NULL,
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &data_type,
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                (LPBYTE)component_id,
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &len);
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(status != ERROR_SUCCESS || data_type != REG_SZ)) {
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = sizeof (net_cfg_instance_id);
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                status = RegQueryValueEx(
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    unit_key,
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    net_cfg_instance_id_string,
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    NULL,
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    &data_type,
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    (LPBYTE)net_cfg_instance_id,
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    &len);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (status == ERROR_SUCCESS && data_type == REG_SZ) {
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (/* !strcmp (component_id, TAP_COMPONENT_ID) &&*/
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        !strcmp (net_cfg_instance_id, guid)) {
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        RegCloseKey (unit_key);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        RegCloseKey (netcard_key);
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return TRUE;
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            RegCloseKey (unit_key);
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ++i;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RegCloseKey (netcard_key);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return FALSE;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int get_device_guid(
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *name,
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int name_size,
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *actual_name,
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int actual_name_size)
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LONG status;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HKEY control_net_key;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD len;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i = 0;
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int stop = 0;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    status = RegOpenKeyEx(
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        HKEY_LOCAL_MACHINE,
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NETWORK_CONNECTIONS_KEY,
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        KEY_READ,
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &control_net_key);
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (status != ERROR_SUCCESS) {
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (!stop)
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char enum_name[256];
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char connection_string[256];
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        HKEY connection_key;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char name_data[256];
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        DWORD name_type;
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char name_string[] = "Name";
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = sizeof (enum_name);
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = RegEnumKeyEx(
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_net_key,
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i,
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            enum_name,
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            &len,
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL,
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            NULL);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status == ERROR_NO_MORE_ITEMS)
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (status != ERROR_SUCCESS) {
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        snprintf(connection_string,
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             sizeof(connection_string),
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             "%s\\%s\\Connection",
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             NETWORK_CONNECTIONS_KEY, enum_name);
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        status = RegOpenKeyEx(
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            HKEY_LOCAL_MACHINE,
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            connection_string,
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            0,
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            KEY_READ,
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            &connection_key);
3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status == ERROR_SUCCESS) {
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = sizeof (name_data);
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            status = RegQueryValueEx(
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                connection_key,
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                name_string,
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                NULL,
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &name_type,
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                (LPBYTE)name_data,
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &len);
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (status != ERROR_SUCCESS || name_type != REG_SZ) {
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return -1;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else {
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (is_tap_win32_dev(enum_name)) {
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    snprintf(name, name_size, "%s", enum_name);
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (actual_name) {
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (strcmp(actual_name, "") != 0) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (strcmp(name_data, actual_name) != 0) {
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                RegCloseKey (connection_key);
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                ++i;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                continue;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            snprintf(actual_name, actual_name_size, "%s", name_data);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    stop = 1;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            RegCloseKey (connection_key);
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ++i;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    RegCloseKey (control_net_key);
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (stop == 0)
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int tap_win32_set_status(HANDLE handle, int status)
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long len = 0;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return DeviceIoControl(handle, TAP_IOCTL_SET_MEDIA_STATUS,
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &status, sizeof (status),
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                &status, sizeof (status), &len, NULL);
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void tap_win32_overlapped_init(tap_win32_overlapped_t* const overlapped, const HANDLE handle)
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->handle = handle;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->read_event = CreateEvent(NULL, FALSE, FALSE, NULL);
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->read_overlapped.Offset = 0;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->read_overlapped.OffsetHigh = 0;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->read_overlapped.hEvent = overlapped->read_event;
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->write_overlapped.Offset = 0;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->write_overlapped.OffsetHigh = 0;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->write_overlapped.hEvent = overlapped->write_event;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    InitializeCriticalSection(&overlapped->output_queue_cs);
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    InitializeCriticalSection(&overlapped->free_list_cs);
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    overlapped->output_queue_semaphore = CreateSemaphore(
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL,   // default security attributes
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,   // initial count
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        TUN_MAX_BUFFER_COUNT,   // maximum count
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL);  // unnamed semaphore
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(!overlapped->output_queue_semaphore)  {
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "error creating output queue semaphore!\n");
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    overlapped->free_list_semaphore = CreateSemaphore(
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL,   // default security attributes
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        TUN_MAX_BUFFER_COUNT,   // initial count
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        TUN_MAX_BUFFER_COUNT,   // maximum count
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL);  // unnamed semaphore
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(!overlapped->free_list_semaphore)  {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "error creating free list semaphore!\n");
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    overlapped->free_list = overlapped->output_queue_front = overlapped->output_queue_back = NULL;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned index;
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for(index = 0; index < TUN_MAX_BUFFER_COUNT; index++) {
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tun_buffer_t* element = &overlapped->buffers[index];
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            element->next = overlapped->free_list;
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            overlapped->free_list = element;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* To count buffers, initially no-signal. */
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    overlapped->tap_semaphore = CreateSemaphore(NULL, 0, TUN_MAX_BUFFER_COUNT, NULL);
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if(!overlapped->tap_semaphore)
4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        fprintf(stderr, "error creating tap_semaphore.\n");
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_win32_write(tap_win32_overlapped_t *overlapped,
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           const void *buffer, unsigned long size)
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long write_size;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BOOL result;
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD error;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = GetOverlappedResult( overlapped->handle, &overlapped->write_overlapped,
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                  &write_size, FALSE);
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!result && GetLastError() == ERROR_IO_INCOMPLETE)
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        WaitForSingleObject(overlapped->write_event, INFINITE);
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = WriteFile(overlapped->handle, buffer, size,
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       &write_size, &overlapped->write_overlapped);
4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!result) {
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (error = GetLastError())
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        {
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        case ERROR_IO_PENDING:
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef TUN_ASYNCHRONOUS_WRITES
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            WaitForSingleObject(overlapped->write_event, INFINITE);
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic DWORD WINAPI tap_win32_thread_entry(LPVOID param)
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tap_win32_overlapped_t *overlapped = (tap_win32_overlapped_t*)param;
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long read_size;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BOOL result;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD dwError;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* buffer = get_buffer_from_free_list(overlapped);
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = ReadFile(overlapped->handle,
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          buffer->buffer,
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          sizeof(buffer->buffer),
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &read_size,
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          &overlapped->read_overlapped);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!result) {
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dwError = GetLastError();
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dwError == ERROR_IO_PENDING) {
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                WaitForSingleObject(overlapped->read_event, INFINITE);
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                result = GetOverlappedResult( overlapped->handle, &overlapped->read_overlapped,
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                              &read_size, FALSE);
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!result) {
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_TAP_WIN32
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    LPVOID lpBuffer;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    dwError = GetLastError();
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   (LPTSTR) & lpBuffer, 0, NULL );
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    fprintf(stderr, "Tap-Win32: Error GetOverlappedResult %d - %s\n", dwError, lpBuffer);
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    LocalFree( lpBuffer );
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_TAP_WIN32
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                LPVOID lpBuffer;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               (LPTSTR) & lpBuffer, 0, NULL );
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                fprintf(stderr, "Tap-Win32: Error ReadFile %d - %s\n", dwError, lpBuffer);
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                LocalFree( lpBuffer );
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if(read_size > 0) {
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buffer->read_size = read_size;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            put_buffer_on_output_queue(overlapped, buffer);
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ReleaseSemaphore(overlapped->tap_semaphore, 1, NULL);
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buffer = get_buffer_from_free_list(overlapped);
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_win32_read(tap_win32_overlapped_t *overlapped,
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          uint8_t **pbuf, int max_size)
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size = 0;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* buffer = get_buffer_from_output_queue_immediate(overlapped);
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if(buffer != NULL) {
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pbuf = buffer->buffer;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = (int)buffer->read_size;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if(size > max_size) {
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            size = max_size;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return size;
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped,
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                  uint8_t *pbuf)
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tun_buffer_t* buffer = (tun_buffer_t*)pbuf;
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    put_buffer_on_free_list(overlapped, buffer);
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_win32_open(tap_win32_overlapped_t **phandle,
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          const char *prefered_name)
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char device_path[256];
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char device_guid[0x100];
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rc;
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HANDLE handle;
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BOOL bret;
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char name_buffer[0x100] = {0, };
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct {
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned long major;
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned long minor;
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned long debug;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } version;
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DWORD version_len;
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD idThread;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (prefered_name != NULL)
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name);
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer));
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rc)
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf (device_path, sizeof(device_path), "%s%s%s",
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              USERMODEDEVICEDIR,
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              device_guid,
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              TAPSUFFIX);
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    handle = CreateFile (
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        device_path,
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        GENERIC_READ | GENERIC_WRITE,
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        OPEN_EXISTING,
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0 );
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (handle == INVALID_HANDLE_VALUE) {
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bret = DeviceIoControl(handle, TAP_IOCTL_GET_VERSION,
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           &version, sizeof (version),
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           &version, sizeof (version), &version_len, NULL);
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bret == FALSE) {
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CloseHandle(handle);
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!tap_win32_set_status(handle, TRUE)) {
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tap_win32_overlapped_init(&tap_overlapped, handle);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phandle = &tap_overlapped;
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6227891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner    (void) CreateThread(NULL, 0, tap_win32_thread_entry,
6237891dd35fa2439a70f43ab8572778a398365bf24David 'Digit' Turner                        (LPVOID)&tap_overlapped, 0, &idThread);
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************/
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project typedef struct TAPState {
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     VLANClientState *vc;
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     tap_win32_overlapped_t *handle;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } TAPState;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_cleanup(VLANClientState *vc)
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TAPState *s = vc->opaque;
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL);
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* FIXME: need to kill thread and close file handle:
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner       tap_win32_close(s);
6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    */
643aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(s);
6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TAPState *s = vc->opaque;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return tap_win32_write(s->handle, buf, size);
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_win32_send(void *opaque)
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TAPState *s = opaque;
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t *buf;
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int max_size = 4096;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size;
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = tap_win32_read(s->handle, &buf, max_size);
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size > 0) {
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_send_packet(s->vc, buf, size);
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tap_win32_free_buffer(s->handle, buf);
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint tap_win32_init(VLANState *vlan, const char *model,
6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                   const char *name, const char *ifname)
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TAPState *s;
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
672aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    s = g_malloc0(sizeof(TAPState));
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s)
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tap_win32_open(&s->handle, ifname) < 0) {
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("tap: Could not open '%s'\n", ifname);
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, tap_receive,
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                 NULL, tap_cleanup, s);
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             "tap: ifname=%s", ifname);
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s);
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
689