Created
May 1, 2020 11:03
-
-
Save wkgcass/a04389aaab0616d6634e7aa4245b090d to your computer and use it in GitHub Desktop.
use windows openvpn tap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define USERMODEDEVICEDIR "\\\\.\\Global\\" | |
#define SYSDEVICEDIR "\\Device\\" | |
#define USERDEVICEDIR "\\DosDevices\\Global\\" | |
#define TAP_WIN_SUFFIX ".tap" | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <windows.h> | |
#include <unistd.h> | |
#include <io.h> | |
#include <winioctl.h> | |
#define TAP_WIN_CONTROL_CODE(request,method) \ | |
CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) | |
#define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) | |
#define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED) | |
#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" | |
int main(int argc, char** argv) { | |
int status; | |
char* dev_name = "tap0"; | |
// get device_guid | |
char* device_guid = NULL; // expect to be {284724C7-B746-4C84-A0F0-0846727BC903} | |
{ | |
// open reg | |
LONG res; | |
HKEY network_connections_key; | |
res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, | |
NETWORK_CONNECTIONS_KEY, | |
0, | |
KEY_READ, | |
&network_connections_key); | |
if (res != ERROR_SUCCESS) { | |
perror("failed to open NETWORK_CONNECTIONS_KEY"); | |
return 1; | |
} | |
int i = 0; | |
while (1) { | |
char enum_name[256]; | |
char connection_string[256]; | |
HKEY connection_key; | |
WCHAR name_data[256]; | |
DWORD name_type; | |
const WCHAR name_string[] = L"Name"; | |
DWORD len = sizeof(enum_name); | |
res = RegEnumKeyEx(network_connections_key, i++, enum_name, &len, | |
NULL, NULL, NULL, NULL); | |
if (res == ERROR_NO_MORE_ITEMS) { | |
break; | |
} else if (res != ERROR_SUCCESS) { | |
perror("failed to enumerate on keys"); | |
return 1; | |
} | |
snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection", | |
NETWORK_CONNECTIONS_KEY, enum_name); | |
res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key); | |
if (res != ERROR_SUCCESS) { | |
perror("failed to open connection key"); | |
// return 1; | |
continue; | |
} | |
len = sizeof(name_data); | |
res = RegQueryValueExW(connection_key, name_string, NULL, &name_type, (LPBYTE) name_data, &len); | |
if (res != ERROR_SUCCESS || name_type != REG_SZ) { | |
perror("RegQueryValueExW failed or not REG_SZ"); | |
return 1; | |
} | |
int n = WideCharToMultiByte(CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL); | |
char* name = malloc(n); | |
WideCharToMultiByte(CP_UTF8, 0, name_data, -1, name, n, NULL, NULL); | |
printf("found dev name: %s\n", name); | |
if (strcmp(dev_name, name) == 0) { | |
printf("found!\n"); | |
device_guid = malloc(sizeof(enum_name)); | |
memcpy(device_guid, enum_name, sizeof(enum_name)); | |
break; | |
} | |
} | |
} | |
if (device_guid == NULL) { | |
printf("device not found\n"); | |
return 1; | |
} | |
char tuntap_device_path[1024]; | |
sprintf(tuntap_device_path, "%s%s%s", USERMODEDEVICEDIR, device_guid, TAP_WIN_SUFFIX); | |
printf("%s\n", tuntap_device_path); | |
HANDLE handle = CreateFile(tuntap_device_path, | |
GENERIC_READ | GENERIC_WRITE, | |
0, | |
0, | |
OPEN_EXISTING, | |
FILE_ATTRIBUTE_SYSTEM, | |
0); | |
if (handle == INVALID_HANDLE_VALUE) { | |
perror("create handle failed"); | |
return 1; | |
} | |
printf("handle created: %lu\n", handle); | |
SECURITY_ATTRIBUTES sa; | |
SECURITY_DESCRIPTOR sd; | |
{ | |
memset(&sa, 0, sizeof(sa)); | |
sa.nLength = sizeof(sa); | |
sa.lpSecurityDescriptor = &sd; | |
sa.bInheritHandle = TRUE; | |
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { | |
perror("initialize security descriptor failed"); | |
return 1; | |
} | |
if (!SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE)) { | |
perror("Set security descriptor dacl failed"); | |
return 1; | |
} | |
} | |
status = SetKernelObjectSecurity(handle, DACL_SECURITY_INFORMATION, &sd); | |
// get info from the fd | |
{ | |
ULONG info[3]; | |
DWORD len; | |
if (DeviceIoControl(handle, TAP_WIN_IOCTL_GET_VERSION, info, sizeof(info), &info, sizeof(info), &len, NULL)) { | |
printf("TAP-Windows Driver Version %d.%d %s\n", (int)info[0], (int)info[0], (info[2] ? "(DEBUG)" : "")); | |
} else { | |
perror("Device io control failed"); | |
return 1; | |
} | |
} | |
// set to connected | |
{ | |
ULONG x = TRUE; | |
DWORD len; | |
if (DeviceIoControl(handle, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &x, sizeof(x), &x, sizeof(x), &len, NULL)) { | |
printf("Setting device to CONNECTED\n"); | |
} else { | |
perror("setting device to CONNECTED failed"); | |
return 1; | |
} | |
} | |
// register ring buffers | |
char ringR[16384]; | |
char ringW[16384]; | |
// read | |
char buf[2048]; | |
while (1) { | |
DWORD n = 0; | |
status = ReadFile(handle, buf, sizeof(buf), &n, NULL); | |
if (!status) { | |
printf("ReadFile returns false: %d\n", GetLastError()); | |
sleep(1); | |
} else { | |
printf("Read %d bytes from tap\n", n); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment