1 %%%-------------------------------------------------------------------
3 %%% Author : Luke Gorrie <luke@bluetail.com>
4 %%% Purpose : Linux "Universal TUN/TAP device" driver
5 %%% See /usr/src/linux/Documentation/networking/tuntap.txt
7 %%% Created : 10 Nov 2001 by Luke Gorrie <luke@bluetail.com>
8 %%%-------------------------------------------------------------------
10 %% Note: if you want to be able to create tunnels as some user other
11 %% than root, you should chmod "/dev/net/tun" to be read/write by the
14 %% To actually communicate between your host machine and Erlang via a
15 %% tun/tap interface, you will probably want to assign it an IP
16 %% address and setup routing. For example (on Linux):
18 %% ifconfig tun0 200.0.0.1 pointopoint 200.0.0.2
20 %% Will configure the tun0 interface so that the host machine (Linux
21 %% itself) has the address 200.0.0.1 and that it believes Erlang has
22 %% the address 200.0.0.2 (i.e. it sets up routing of that address into
25 %% The exact setup varies from unix to unix. The point is that you
26 %% configure it exactly like a normal network interface: assign an
27 %% address for the local machine to use and a route for any addresses
28 %% you want to talk to "out there".
32 -author('luke@bluetail.com').
35 open_tun
/0, open_tap
/0, open_tuntap
/2,
36 device_name
/1, write
/2, set_active
/2]).
38 -define(REPLY_ERROR
, 0).
41 -define(REQUEST_GET_DEVICE
, 0).
42 -define(REQUEST_WRITE
, 1).
43 -define(REQUEST_ACTIVE
, 2).
45 -define(ACTIVE_FALSE
, 0).
46 -define(ACTIVE_TRUE
, 1).
47 -define(ACTIVE_ONCE
, 2).
52 ok
= erl_ddll:load_driver(code:priv_dir(tuntap
), "tun_drv").
55 open_tun() -> open_tuntap(tun
, undefined
).
56 open_tap() -> open_tuntap(tap
, undefined
).
58 %% open_tuntap(tun|tap, undefined|string()) -> port()
59 open_tuntap(Type
, Dev
) ->
60 %% It seems to be okay to init() multiple times..
62 TypeName
= case Type
of
66 DevArg
= if Dev
== undefined
-> "";
67 list(Dev
) -> " " ++ Dev
69 open_port({spawn, "tun_drv "++TypeName
++DevArg
}, [binary]).
71 %% Returns: string() (e.g. "tun0" or "tap42")
73 [?REPLY_OK
|Name
] = erlang:port_control(Port
, ?REQUEST_GET_DEVICE
, []),
77 write(Port
, Packet
) ->
78 erlang:port_command(Port
, Packet
),
81 set_active(Port
, false
) -> set_active1(Port
, ?ACTIVE_FALSE
);
82 set_active(Port
, true
) -> set_active1(Port
, ?ACTIVE_TRUE
);
83 set_active(Port
, once
) -> set_active1(Port
, ?ACTIVE_ONCE
).
85 set_active1(Port
, Arg
) ->
86 [?REPLY_OK
] = erlang:port_control(Port
, ?REQUEST_ACTIVE
, [Arg
]),