Echo
Mix.install([
{:tundra, "> 0.0.0"}
])
Section
defmodule Reflector do
use GenServer
@mtu 1500
def start_link(_), do: GenServer.start_link(__MODULE__, [], name: __MODULE__)
@impl true
def init(_args) do
# Create a TUN device with the given address and options
{:ok, state} =
Tundra.create("fd11:b7b7:4360::2",
dstaddr: "fd11:b7b7:4360::1",
netmask: "ffff:ffff:ffff:ffff::",
mtu: @mtu)
{:ok, state, {:continue, :read}}
end
@impl true
def handle_continue(:read, {dev, _} = state) do
# Read a frame from the device
case Tundra.recv(dev, @mtu, :nowait) do
{:ok, data} ->
{:noreply, state, {:continue, {:reflect, data}}}
{:select, _} ->
{:noreply, state}
end
end
def handle_continue({:reflect, data}, {dev, _} = state) do
# Swap the source and destination addresses of the IPv6 packet
<<pre::binary-size(8),
src::binary-size(16),
dst::binary-size(16),
rest::binary>> = data
reflected = [pre, dst, src, rest]
# Write the frame back to the device, assume it won't block
:ok = Tundra.send(dev, reflected, :nowait)
{:noreply, state, {:continue, :read}}
end
@impl true
def handle_info({:"$socket", dev, :select, _}, {dev, _} = state) do
# Handle 'input ready' notifications
{:noreply, state, {:continue, :read}}
end
end
{:ok, pid} = Reflector.start_link([])
GenServer.stop(pid)