Merge branch 'pu'
[jungerl.git] / lib / tuntap / src / tuntap.erl
blob5381855f918249c4be7cae94271879c0da6cd64f
1 %%%-------------------------------------------------------------------
2 %%% File : tuntap.erl
3 %%% Author : Luke Gorrie <luke@bluetail.com>
4 %%% Purpose : Linux "Universal TUN/TAP device" driver
5 %%% See /usr/src/linux/Documentation/networking/tuntap.txt
6 %%%
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
12 %% appropriate user.
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
23 %% the tunnel).
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".
30 -module(tuntap).
32 -author('luke@bluetail.com').
34 -export([init/0,
35 open_tun/0, open_tap/0, open_tuntap/2,
36 device_name/1, write/2, set_active/2]).
38 -define(REPLY_ERROR, 0).
39 -define(REPLY_OK, 1).
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).
49 %% Returns: ok
50 init() ->
51 erl_ddll:start(),
52 ok = erl_ddll:load_driver(code:priv_dir(tuntap), "tun_drv").
54 %% Returns port()
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..
61 ok = init(),
62 TypeName = case Type of
63 tun -> "tun";
64 tap -> "tap"
65 end,
66 DevArg = if Dev == undefined -> "";
67 list(Dev) -> " " ++ Dev
68 end,
69 open_port({spawn, "tun_drv "++TypeName++DevArg}, [binary]).
71 %% Returns: string() (e.g. "tun0" or "tap42")
72 device_name(Port) ->
73 [?REPLY_OK|Name] = erlang:port_control(Port, ?REQUEST_GET_DEVICE, []),
74 Name.
76 %% Returns: ok
77 write(Port, Packet) ->
78 erlang:port_command(Port, Packet),
79 ok.
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]),
87 ok.