Skip to content

Instantly share code, notes, and snippets.

@murilopontes
Last active October 11, 2016 15:52
Show Gist options
  • Save murilopontes/9678872 to your computer and use it in GitHub Desktop.
Save murilopontes/9678872 to your computer and use it in GitHub Desktop.
Windows TAP Interface
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
namespace WindowsTapSpace
{
//change this in app.manifest
/* <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> */
class WindowsTapTest
{
//
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
private const uint FILE_DEVICE_UNKNOWN = 0x00000022;
private const int FILE_ATTRIBUTE_SYSTEM = 0x4;
private const int FILE_FLAG_OVERLAPPED = 0x40000000;
//
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr CreateFile(
string filename,
[MarshalAs(UnmanagedType.U4)]FileAccess fileaccess,
[MarshalAs(UnmanagedType.U4)]FileShare fileshare,
int securityattributes,
[MarshalAs(UnmanagedType.U4)]FileMode creationdisposition,
int flags,
IntPtr template);
//
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
IntPtr lpInBuffer, uint nInBufferSize,
IntPtr lpOutBuffer, uint nOutBufferSize,
out int lpBytesReturned, IntPtr lpOverlapped);
//
private static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
//
static uint TAP_WIN_CONTROL_CODE(uint request, uint method)
{
return CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS);
}
static string GetDeviceGuid()
{
const string AdapterKey = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
RegistryKey regAdapters = Registry.LocalMachine.OpenSubKey(AdapterKey);
string[] keyNames = regAdapters.GetSubKeyNames();
string devGuid = "";
foreach (string x in keyNames)
{
try
{
RegistryKey regAdapter = regAdapters.OpenSubKey(x);
object id = regAdapter.GetValue("ComponentId");
if (id != null && id.ToString() == "tap0801") devGuid = regAdapter.GetValue("NetCfgInstanceId").ToString();
if (id != null && id.ToString() == "tap0901") devGuid = regAdapter.GetValue("NetCfgInstanceId").ToString();
}
catch (Exception ex)
{
}
}
Console.WriteLine("devGuid=" + devGuid);
return devGuid;
}
static string HumanName(string guid)
{
const string ConnectionKey = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}";
if (guid != "")
{
RegistryKey regConnection = Registry.LocalMachine.OpenSubKey(ConnectionKey + "\\" + guid + "\\Connection");
object id = regConnection.GetValue("Name");
if (id != null) return id.ToString();
}
return "";
}
static FileStream Tap;
[STAThread]
static void Main(string[] args)
{
//tap ioctls
uint TAP_WIN_IOCTL_GET_MAC = TAP_WIN_CONTROL_CODE(1, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_GET_VERSION = TAP_WIN_CONTROL_CODE(2, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_GET_MTU = TAP_WIN_CONTROL_CODE(3, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_GET_INFO = TAP_WIN_CONTROL_CODE(4, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT = TAP_WIN_CONTROL_CODE(5, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_SET_MEDIA_STATUS = TAP_WIN_CONTROL_CODE(6, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_CONFIG_DHCP_MASQ = TAP_WIN_CONTROL_CODE(7, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_GET_LOG_LINE = TAP_WIN_CONTROL_CODE(8, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT = TAP_WIN_CONTROL_CODE(9, METHOD_BUFFERED);
uint TAP_WIN_IOCTL_CONFIG_TUN = TAP_WIN_CONTROL_CODE(10, METHOD_BUFFERED);
//get first tap interface
const string UsermodeDeviceSpace = "\\\\.\\Global\\";
string devGuid = GetDeviceGuid();
Console.WriteLine("interface-human-name=" + HumanName(devGuid));
//create handle to tap interface
IntPtr ptr = CreateFile(UsermodeDeviceSpace + devGuid + ".tap", FileAccess.ReadWrite, FileShare.ReadWrite, 0, FileMode.Open, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, IntPtr.Zero);
//create stream to tap interface
Tap = new FileStream(ptr, FileAccess.ReadWrite, true, 4096, true);
//create buffer to read packets from tap interface
byte[] buf = new byte[4096];
//set tap interface up
int len;
IntPtr pstatus = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(pstatus, 1);
DeviceIoControl(ptr, TAP_WIN_IOCTL_SET_MEDIA_STATUS, pstatus, 4, pstatus, 4, out len, IntPtr.Zero);
//configure ipv4 of tap interface
string arg = "interface ip set address \"" + HumanName(devGuid) + "\" dhcp";
Console.WriteLine(arg);
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo("netsh", arg);
p.StartInfo = psi;
p.Start();
//configure ipv6 of tap interface
string arg2 = "interface ipv6 set address \"" + HumanName(devGuid) + "\" 2001::6969 advertise=enabled";
Console.WriteLine(arg2);
Process p2 = new Process();
ProcessStartInfo psi2 = new ProcessStartInfo("netsh", arg2);
p2.StartInfo = psi2;
p2.Start();
//serial connection to embedded system
System.IO.Ports.SerialPort serial_port = new System.IO.Ports.SerialPort();
serial_port.PortName = "COM1";
serial_port.BaudRate = 115200;
serial_port.DataReceived += port_DataReceived;
serial_port.Open();
while (true)
{
//async read from windows network kernel
int BytesRead = Tap.Read(buf, 0, buf.Length);
Console.WriteLine("from-windows=" + BytesRead + "=>" + BitConverter.ToString(buf, 0, BytesRead));
//write to serial connected in embedded system
serial_port.Write(buf, 0, BytesRead);
}
}
//read from serial connected in embedded system
static void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
byte[] bin_from_stm32 = System.Text.Encoding.ASCII.GetBytes(indata);
Console.WriteLine("from-embedded=" + bin_from_stm32.Length + "=>" + BitConverter.ToString(bin_from_stm32, 0, bin_from_stm32.Length));
//mininum valid packet size for windows kernel
if (bin_from_stm32.Length >= 20)
{
//async write to windows network kernel
Tap.Write(bin_from_stm32, 0, bin_from_stm32.Length);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment