New upstream version 3.1.1
This commit is contained in:
parent
4e9934e5ec
commit
e7b41df57b
229 changed files with 57000 additions and 12055 deletions
517
win32/wintap.c
Normal file
517
win32/wintap.c
Normal file
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
(C) 2007-22 - Luca Deri <deri@ntop.org>
|
||||
*/
|
||||
|
||||
#include "n2n.h"
|
||||
#include "n2n_win32.h"
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
void initWin32() {
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
|
||||
err = WSAStartup(MAKEWORD(2, 2), &wsaData );
|
||||
if( err != 0 ) {
|
||||
/* Tell the user that we could not find a usable */
|
||||
/* WinSock DLL. */
|
||||
printf("FATAL ERROR: unable to initialise Winsock 2.x.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void destroyWin32() {
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
struct win_adapter_info {
|
||||
HANDLE handle;
|
||||
char adapterid[1024];
|
||||
char adaptername[1024];
|
||||
};
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static HANDLE open_tap_device(const char *adapterid) {
|
||||
char tapname[1024];
|
||||
_snprintf(tapname, sizeof(tapname), USERMODEDEVICEDIR "%s" TAPSUFFIX, adapterid);
|
||||
|
||||
return(CreateFile(tapname, GENERIC_WRITE | GENERIC_READ,
|
||||
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));
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static void iterate_win_network_adapters(
|
||||
int (*callback)(struct win_adapter_info*, struct tuntap_dev *),
|
||||
void *userdata) {
|
||||
HKEY key, key2;
|
||||
char regpath[1024];
|
||||
long len, rc;
|
||||
int found = 0;
|
||||
int err, i;
|
||||
struct win_adapter_info adapter;
|
||||
|
||||
/* Open registry and look for network adapters */
|
||||
if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ, &key))) {
|
||||
printf("Unable to read registry: [rc=%d]\n", rc);
|
||||
exit(EXIT_FAILURE);
|
||||
/* MSVC Note: If you keep getting rc=2 errors, make sure you set:
|
||||
Project -> Properties -> Configuration Properties -> General -> Character set
|
||||
to: "Use Multi-Byte Character Set"
|
||||
*/
|
||||
}
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
len = sizeof(adapter.adapterid);
|
||||
if(RegEnumKeyEx(key, i, (LPTSTR)adapter.adapterid, &len, 0, 0, 0, NULL))
|
||||
break;
|
||||
|
||||
/* Find out more about this adapter */
|
||||
|
||||
_snprintf(regpath, sizeof(regpath), "%s\\%s\\Connection", NETWORK_CONNECTIONS_KEY, adapter.adapterid);
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2))
|
||||
continue;
|
||||
|
||||
len = sizeof(adapter.adaptername);
|
||||
err = RegQueryValueEx(key2, "Name", 0, 0, adapter.adaptername, &len);
|
||||
|
||||
RegCloseKey(key2);
|
||||
|
||||
if(err)
|
||||
continue;
|
||||
|
||||
|
||||
adapter.handle = open_tap_device(adapter.adapterid);
|
||||
|
||||
if(adapter.handle != INVALID_HANDLE_VALUE) {
|
||||
/* Valid device, use the callback */
|
||||
if(!callback(&adapter, userdata))
|
||||
break;
|
||||
else
|
||||
CloseHandle(adapter.handle);
|
||||
/* continue */
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static int print_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) {
|
||||
printf(" %s - %s\n", adapter->adapterid, adapter->adaptername);
|
||||
|
||||
/* continue */
|
||||
return(1);
|
||||
}
|
||||
|
||||
void win_print_available_adapters() {
|
||||
iterate_win_network_adapters(print_adapter_callback, NULL);
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static int lookup_adapter_info_reg(const char *target_adapter, char *regpath, size_t regpath_size) {
|
||||
HKEY key, key2;
|
||||
long len, rc;
|
||||
char index[16];
|
||||
int err, i;
|
||||
char adapter_name[N2N_IFNAMSIZ];
|
||||
int rv = 0;
|
||||
|
||||
if((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_INFO_KEY, 0, KEY_READ, &key))) {
|
||||
printf("Unable to read registry: %s, [rc=%d]\n", ADAPTER_INFO_KEY, rc);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for(i = 0; ; i++) {
|
||||
len = sizeof(index);
|
||||
if(RegEnumKeyEx(key, i, (LPTSTR)index, &len, 0, 0, 0, NULL))
|
||||
break;
|
||||
|
||||
_snprintf(regpath, regpath_size, "%s\\%s", ADAPTER_INFO_KEY, index);
|
||||
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCSTR)regpath, 0, KEY_READ, &key2))
|
||||
continue;
|
||||
|
||||
len = sizeof(adapter_name);
|
||||
err = RegQueryValueEx(key2, "NetCfgInstanceId", 0, 0, adapter_name, &len);
|
||||
|
||||
RegCloseKey(key2);
|
||||
|
||||
if(err)
|
||||
continue;
|
||||
|
||||
if(!strcmp(adapter_name, target_adapter)) {
|
||||
rv = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return(rv);
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static void set_interface_mac(struct tuntap_dev *device, const char *mac_str) {
|
||||
char cmd[256];
|
||||
char mac_buf[18];
|
||||
char adapter_info_reg[1024];
|
||||
|
||||
uint64_t mac = 0;
|
||||
uint8_t *ptr = (uint8_t*)&mac;
|
||||
|
||||
if(strlen(mac_str) != 17) {
|
||||
printf("Invalid MAC: %s\n", mac_str);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Remove the colons */
|
||||
for(int i=0; i<6; i++) {
|
||||
mac_buf[i*2] = mac_str[2*i + i];
|
||||
mac_buf[i*2+1] = mac_str[2*i + i + 1];
|
||||
}
|
||||
mac_buf[12] = '\0';
|
||||
|
||||
if(!lookup_adapter_info_reg(device->device_name, adapter_info_reg, sizeof(adapter_info_reg))) {
|
||||
printf("Could not determine adapter MAC registry key\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_snprintf(cmd, sizeof(cmd),
|
||||
"reg add HKEY_LOCAL_MACHINE\\%s /v MAC /d %s /f > nul", adapter_info_reg, mac_buf);
|
||||
system(cmd);
|
||||
|
||||
/* Put down then up again to apply */
|
||||
CloseHandle(device->device_handle);
|
||||
_snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" disabled > nul", device->ifName);
|
||||
system(cmd);
|
||||
_snprintf(cmd, sizeof(cmd), "netsh interface set interface \"%s\" enabled > nul", device->ifName);
|
||||
system(cmd);
|
||||
|
||||
device->device_handle = open_tap_device(device->device_name);
|
||||
if(device->device_handle == INVALID_HANDLE_VALUE) {
|
||||
printf("Reopening TAP device \"%s\" failed\n", device->device_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
static int choose_adapter_callback(struct win_adapter_info *adapter, struct tuntap_dev *device) {
|
||||
if(device->device_name) {
|
||||
/* A device name filter was set, name must match */
|
||||
if(strcmp(device->device_name, adapter->adapterid) &&
|
||||
strcmp(device->device_name, adapter->adaptername)) {
|
||||
/* Not found, continue */
|
||||
return(1);
|
||||
}
|
||||
} /* otherwise just pick the first available adapter */
|
||||
|
||||
/* Adapter found, break */
|
||||
device->device_handle = adapter->handle;
|
||||
if(device->device_name) free(device->device_name);
|
||||
device->device_name = _strdup(adapter->adapterid);
|
||||
device->ifName = _strdup(adapter->adaptername);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ***************************************************** */
|
||||
|
||||
int open_wintap(struct tuntap_dev *device,
|
||||
const char * devname,
|
||||
const char * address_mode, /* "static" or "dhcp" */
|
||||
char *device_ip,
|
||||
char *device_mask,
|
||||
const char *device_mac,
|
||||
int mtu,
|
||||
int metric) {
|
||||
|
||||
char cmd[256];
|
||||
DWORD len;
|
||||
ULONG status = TRUE;
|
||||
|
||||
memset(device, 0, sizeof(struct tuntap_dev));
|
||||
device->device_handle = INVALID_HANDLE_VALUE;
|
||||
device->device_name = devname[0] ? _strdup(devname) : NULL;
|
||||
device->ifName = NULL;
|
||||
device->ip_addr = inet_addr(device_ip);
|
||||
|
||||
iterate_win_network_adapters(choose_adapter_callback, device);
|
||||
|
||||
if(device->device_handle == INVALID_HANDLE_VALUE) {
|
||||
if(!devname[0])
|
||||
printf("No Windows tap devices found, did you run tapinstall.exe?\n");
|
||||
else
|
||||
printf("Cannot find tap device \"%s\"\n", devname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
/* interface index, required for routing */
|
||||
|
||||
ULONG buffer_len = 0;
|
||||
IP_ADAPTER_INFO *buffer;
|
||||
|
||||
// get required buffer size and allocate buffer
|
||||
GetAdaptersInfo(NULL, &buffer_len);
|
||||
buffer = malloc(buffer_len);
|
||||
|
||||
// find device by name and get its index
|
||||
if(buffer && !GetAdaptersInfo(buffer, &buffer_len)) {
|
||||
IP_ADAPTER_INFO *i;
|
||||
for(i = buffer; i != NULL; i = i->Next) {
|
||||
if(!strcmp(device->device_name, i->AdapterName)) {
|
||||
device->if_idx = i->Index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
if(device_mac[0])
|
||||
set_interface_mac(device, device_mac);
|
||||
|
||||
/* Get MAC address from tap device->device_name */
|
||||
|
||||
if(!DeviceIoControl(device->device_handle, TAP_IOCTL_GET_MAC,
|
||||
device->mac_addr, sizeof(device->mac_addr),
|
||||
device->mac_addr, sizeof(device->mac_addr), &len, 0)) {
|
||||
printf("Could not get MAC address from Windows tap %s (%s)\n",
|
||||
device->device_name, device->ifName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
device->mtu = mtu;
|
||||
|
||||
printf("Open device [name=%s][ip=%s][ifName=%s][MTU=%d][mac=%02X:%02X:%02X:%02X:%02X:%02X]\n",
|
||||
device->device_name, device_ip, device->ifName, device->mtu,
|
||||
device->mac_addr[0] & 0xFF,
|
||||
device->mac_addr[1] & 0xFF,
|
||||
device->mac_addr[2] & 0xFF,
|
||||
device->mac_addr[3] & 0xFF,
|
||||
device->mac_addr[4] & 0xFF,
|
||||
device->mac_addr[5] & 0xFF);
|
||||
|
||||
/* ****************** */
|
||||
|
||||
if ( 0 == strcmp("dhcp", address_mode) )
|
||||
{
|
||||
_snprintf(cmd, sizeof(cmd),
|
||||
"netsh interface ip set address \"%s\" dhcp > nul",
|
||||
device->ifName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_snprintf(cmd, sizeof(cmd),
|
||||
"netsh interface ip set address \"%s\" static %s %s > nul",
|
||||
device->ifName, device_ip, device_mask);
|
||||
}
|
||||
|
||||
if(system(cmd) == 0) {
|
||||
device->ip_addr = inet_addr(device_ip);
|
||||
device->device_mask = inet_addr(device_mask);
|
||||
} else
|
||||
printf("WARNING: Unable to set device %s IP address [%s]\n",
|
||||
device->ifName, cmd);
|
||||
|
||||
/* ****************** */
|
||||
|
||||
/* MTU */
|
||||
|
||||
_snprintf(cmd, sizeof(cmd),
|
||||
"netsh interface ipv4 set subinterface \"%s\" mtu=%d store=persistent > nul",
|
||||
device->ifName, mtu);
|
||||
|
||||
if(system(cmd) != 0)
|
||||
printf("WARNING: Unable to set device %s parameters MTU=%d store=persistent [%s]\n",
|
||||
device->ifName, mtu, cmd);
|
||||
|
||||
/* ****************** */
|
||||
|
||||
/* metric */
|
||||
|
||||
PMIB_IPINTERFACE_ROW Row;
|
||||
|
||||
if(metric) { /* try to change only if a value has been given, otherwise leave with default or as set before */
|
||||
// find & store original metric
|
||||
Row = calloc(1, sizeof(MIB_IPINTERFACE_ROW));
|
||||
InitializeIpInterfaceEntry(Row);
|
||||
Row->InterfaceIndex = device->if_idx;
|
||||
Row->Family = AF_INET;
|
||||
GetIpInterfaceEntry(Row);
|
||||
|
||||
device->metric_original = Row->Metric;
|
||||
device->metric = metric;
|
||||
|
||||
// set new value
|
||||
Row->Metric = metric;
|
||||
|
||||
// store
|
||||
Row->SitePrefixLength = 0; /* if not set to zero, following function call fails... */
|
||||
SetIpInterfaceEntry(Row);
|
||||
|
||||
free(Row);
|
||||
}
|
||||
|
||||
/* ****************** */
|
||||
|
||||
|
||||
/* set driver media status to 'connected' (i.e. set the interface up) */
|
||||
if (!DeviceIoControl (device->device_handle, TAP_IOCTL_SET_MEDIA_STATUS,
|
||||
&status, sizeof (status),
|
||||
&status, sizeof (status), &len, NULL))
|
||||
printf("WARNING: Unable to enable TAP adapter\n");
|
||||
|
||||
/*
|
||||
* Initialize overlapped structures
|
||||
*/
|
||||
device->overlap_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
device->overlap_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!device->overlap_read.hEvent || !device->overlap_write.hEvent) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len)
|
||||
{
|
||||
DWORD read_size, last_err;
|
||||
|
||||
ResetEvent(tuntap->overlap_read.hEvent);
|
||||
if (ReadFile(tuntap->device_handle, buf, len, &read_size, &tuntap->overlap_read)) {
|
||||
//printf("tun_read(len=%d)\n", read_size);
|
||||
return read_size;
|
||||
}
|
||||
switch (last_err = GetLastError()) {
|
||||
case ERROR_IO_PENDING:
|
||||
WaitForSingleObject(tuntap->overlap_read.hEvent, INFINITE);
|
||||
GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_read, &read_size, FALSE);
|
||||
return read_size;
|
||||
break;
|
||||
default:
|
||||
printf("GetLastError() returned %d\n", last_err);
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
/* ************************************************ */
|
||||
|
||||
int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len)
|
||||
{
|
||||
DWORD write_size;
|
||||
|
||||
//printf("tun_write(len=%d)\n", len);
|
||||
|
||||
ResetEvent(tuntap->overlap_write.hEvent);
|
||||
if (WriteFile(tuntap->device_handle,
|
||||
buf,
|
||||
len,
|
||||
&write_size,
|
||||
&tuntap->overlap_write)) {
|
||||
//printf("DONE tun_write(len=%d)\n", write_size);
|
||||
return write_size;
|
||||
}
|
||||
switch (GetLastError()) {
|
||||
case ERROR_IO_PENDING:
|
||||
WaitForSingleObject(tuntap->overlap_write.hEvent, INFINITE);
|
||||
GetOverlappedResult(tuntap->device_handle, &tuntap->overlap_write,
|
||||
&write_size, FALSE);
|
||||
return write_size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
int tuntap_open(struct tuntap_dev *device,
|
||||
char *dev,
|
||||
const char *address_mode, /* static or dhcp */
|
||||
char *device_ip,
|
||||
char *device_mask,
|
||||
const char * device_mac,
|
||||
int mtu,
|
||||
int metric) {
|
||||
return(open_wintap(device, dev, address_mode, device_ip, device_mask, device_mac, mtu, metric));
|
||||
}
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
void tuntap_close(struct tuntap_dev *tuntap) {
|
||||
|
||||
PMIB_IPINTERFACE_ROW Row;
|
||||
|
||||
if(tuntap->metric) { /* only required if a value has been given (and thus stored) */
|
||||
// find device entry
|
||||
Row = calloc(1, sizeof(MIB_IPINTERFACE_ROW));
|
||||
InitializeIpInterfaceEntry(Row);
|
||||
Row->InterfaceIndex = tuntap->if_idx;
|
||||
Row->Family = AF_INET;
|
||||
GetIpInterfaceEntry(Row);
|
||||
|
||||
// restore original value
|
||||
Row->Metric = tuntap->metric_original;
|
||||
|
||||
// store
|
||||
Row->SitePrefixLength = 0; /* if not set to zero, following function call fails... */
|
||||
SetIpInterfaceEntry(Row);
|
||||
|
||||
free(Row);
|
||||
}
|
||||
|
||||
CloseHandle(tuntap->device_handle);
|
||||
}
|
||||
|
||||
/* Fill out the ip_addr value from the interface. Called to pick up dynamic
|
||||
* address changes. */
|
||||
void tuntap_get_address(struct tuntap_dev *tuntap)
|
||||
{
|
||||
}
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
#if 0
|
||||
int main(int argc, char* argv[]) {
|
||||
struct tuntap_dev tuntap;
|
||||
int i;
|
||||
int mtu = 1400;
|
||||
|
||||
printf("Welcome to n2n\n");
|
||||
initWin32();
|
||||
open_wintap(&tuntap, "static", "1.2.3.20", "255.255.255.0", mtu, 0);
|
||||
|
||||
for(i=0; i<10; i++) {
|
||||
u_char buf[MTU];
|
||||
int rc;
|
||||
|
||||
rc = tun_read(&tuntap, buf, sizeof(buf));
|
||||
buf[0]=2;
|
||||
buf[1]=3;
|
||||
buf[2]=4;
|
||||
|
||||
printf("tun_read returned %d\n", rc);
|
||||
rc = tun_write(&tuntap, buf, rc);
|
||||
printf("tun_write returned %d\n", rc);
|
||||
}
|
||||
// rc = tun_open (device->device_name, IF_MODE_TUN);
|
||||
WSACleanup ();
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue