mirror of
https://github.com/deavmi/libtun.git
synced 2024-09-11 09:03:12 +02:00
150 lines
3.2 KiB
D
150 lines
3.2 KiB
D
module libtun.adapter;
|
|
|
|
import libtun.tunctl;
|
|
|
|
public class Adapter
|
|
{
|
|
/* Tunnel device descriptor */
|
|
private int tunFD;
|
|
private bool isClosed;
|
|
|
|
/* Temporary scratchpad buffer */
|
|
private byte[] scratch;
|
|
|
|
|
|
/**
|
|
* Instantiates a new Adapter with the given interface name
|
|
* and optionally you can specifiy the adapter type (default
|
|
* is TAP)
|
|
*
|
|
* Params:
|
|
* interfaceName = the name of the interface to create
|
|
* adapterType = The AdapterType to use
|
|
*/
|
|
this(string interfaceName, AdapterType adapterType = AdapterType.TAP)
|
|
{
|
|
init(interfaceName, adapterType);
|
|
}
|
|
|
|
private void init(string interfaceName, AdapterType adapterType)
|
|
{
|
|
tunFD = createTun(cast(char*)interfaceName, 4096|adapterType);
|
|
if(tunFD < 0)
|
|
{
|
|
throw new AdapterException("Error creating tun device");
|
|
}
|
|
|
|
/* TODO: Get device MTU and add functions for setting it */
|
|
ushort mtu = cast(ushort)-1;
|
|
scratch.length = mtu;
|
|
}
|
|
|
|
private void sanityCheck()
|
|
{
|
|
if(isClosed)
|
|
{
|
|
throw new AdapterException("Cannot operate on closed tunnel device");
|
|
}
|
|
}
|
|
|
|
public void setAddress()
|
|
{
|
|
|
|
}
|
|
|
|
/**
|
|
* Closes the adapter
|
|
*
|
|
* Throws:
|
|
* TUNException if the operation failed
|
|
*/
|
|
public void close()
|
|
{
|
|
sanityCheck();
|
|
|
|
isClosed = true;
|
|
destroyTun(tunFD);
|
|
}
|
|
|
|
/**
|
|
* Blocks to receive into the buffer
|
|
*
|
|
* Params:
|
|
* buffer = The buffer variable to write the received
|
|
* data into
|
|
* Throws:
|
|
* TUNException if the read failed
|
|
*/
|
|
public void receive(ref byte[] buffer)
|
|
{
|
|
sanityCheck();
|
|
|
|
|
|
|
|
/**
|
|
* We read with a request of maximum possible
|
|
* Ethernet frame size (-1 -> 2 bytes) 65535,
|
|
* this ensures our buffer fills up in all cases
|
|
* but we get returned either < 0 or > 0.
|
|
*
|
|
* Former, systemcall read error
|
|
* Latter, ethernet frame size
|
|
*/
|
|
int status = tunRead(tunFD, cast(char*)scratch.ptr, cast(int)scratch.length);
|
|
|
|
|
|
if(status < 0)
|
|
{
|
|
throw new AdapterException("Read failed");
|
|
}
|
|
else if(status == 0)
|
|
{
|
|
assert(false);
|
|
}
|
|
else
|
|
{
|
|
/* Copy the data into their buffer (and of correct length) */
|
|
buffer = scratch[0..status].dup;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sends the provided data
|
|
*
|
|
* Params:
|
|
* buffer = The data to send
|
|
* Throws:
|
|
* TUNException if an error occurs
|
|
*/
|
|
public void send(byte[] buffer)
|
|
{
|
|
sanityCheck();
|
|
|
|
tunWrite(tunFD, cast(char*)buffer.ptr, cast(int)buffer.length);
|
|
}
|
|
|
|
|
|
public void setDeviceMTU(ushort mtu)
|
|
{
|
|
/* TODO: Set the MTU on the device */
|
|
|
|
/* TODO: Set the scratchpad to match the MTU */
|
|
scratch.length = mtu;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public final class AdapterException : Exception
|
|
{
|
|
this(string msg)
|
|
{
|
|
super(msg);
|
|
}
|
|
}
|
|
|
|
public enum AdapterType : byte
|
|
{
|
|
TUN = 1,
|
|
TAP = 2
|
|
} |