libtun/source/libtun/adapter.d

142 lines
2.8 KiB
D
Raw Normal View History

module libtun.adapter;
extern (C) int ioctl(int fd, ulong request, void* data);
extern (C) int open(char* path, int flags);
2021-07-18 18:45:17 +01:00
import core.stdc.stdio;
/**
* TUN maintenance routines in `tunctl.c`
2022-11-28 16:27:38 +00:00
* TODO: Use import C here
*/
2022-11-28 16:27:38 +00:00
import libtun.tunctl;
// extern (C) int createTun(char* interfaceName, int iffFlags);
// extern (C) int destroyTun(int fd);
// extern (C) int tunWrite(int fd, char* data, int length);
// extern (C) int tunRead(int fd, char* data, int amount);
public class TUNAdapter
{
2021-07-18 18:45:17 +01:00
/* Tunnel device descriptor */
private int tunFD;
private bool isClosed;
2021-07-18 18:45:17 +01:00
/* Temporary scratchpad buffer */
private byte[] scratch;
this(string interfaceName, AdapterType adapterType = AdapterType.TAP)
{
2021-10-24 18:41:21 +01:00
init(interfaceName, adapterType);
}
2021-10-24 18:41:21 +01:00
private void init(string interfaceName, AdapterType adapterType)
{
2021-10-24 18:41:21 +01:00
tunFD = createTun(cast(char*)interfaceName, 4096|adapterType);
if(tunFD < 0)
{
throw new TUNException("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 TUNException("Cannot operate on closed tunnel device");
}
}
2022-11-28 16:27:38 +00:00
public void setAddress()
{
}
public void close()
{
sanityCheck();
isClosed = true;
destroyTun(tunFD);
}
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 TUNException("Read failed");
}
else if(status == 0)
{
assert(false);
}
else
{
/* Copy the data into their buffer (and of correct length) */
buffer = scratch[0..status].dup;
}
}
public void send(byte[] buffer)
{
sanityCheck();
2021-07-18 18:45:17 +01:00
tunWrite(tunFD, cast(char*)buffer.ptr, cast(int)buffer.length);
}
2021-08-18 13:11:34 +01:00
public void setDeviceMTU(ushort mtu)
{
2021-08-18 13:11:34 +01:00
/* TODO: Set the MTU on the device */
2021-08-18 13:11:34 +01:00
/* TODO: Set the scratchpad to match the MTU */
scratch.length = mtu;
}
2021-08-18 13:11:34 +01:00
}
public final class TUNException : Exception
{
this(string msg)
{
super(msg);
}
}
2021-10-24 18:41:21 +01:00
public enum AdapterType : byte
{
2021-07-18 22:24:06 +01:00
TUN = 1,
2021-10-24 18:41:21 +01:00
TAP = 2
}