Skip to content

Instantly share code, notes, and snippets.

@wkgcass
Created May 1, 2020 11:03
Show Gist options
  • Save wkgcass/a04389aaab0616d6634e7aa4245b090d to your computer and use it in GitHub Desktop.
Save wkgcass/a04389aaab0616d6634e7aa4245b090d to your computer and use it in GitHub Desktop.
use windows openvpn tap
#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