Erlang interface for manipulating 802.11 wireless devices
Erlang Other
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Erlang interface for manipulating 802.11 wireless network devices

wierl is a set of Erlang modules for interacting with 802.11 wireless devices on Linux.


To run this code, Erlang will either have to run as root or have CAP_NET_ADMIN privileges:

setcap cap_net_admin=ep /path/to/beam


cd wierl

sudo setcap cap_net_admin=ep /path/to/beam

% Scan using the "wlan0" interface

% Monitor mode: make sure the network manager is stopped. For example,
% on Ubuntu: service network-manager stop
{ok, Socket} = wierl_monitor:open(<<"wlan0">>),
{ok, Frame} = wierl_monitor:read(Socket),
wierl_monitor:frame(Socket, Frame).

# If you want to remove the privs
sudo setcap -r /path/to/beam



wierl_scan:list() ->  [{Interface, AccessPoints}]
wierl_scan:list(Interface) ->  AccessPoints
wierl_scan:list(Interface, Options) ->  AccessPoints

    Types   Interface = binary()
            AccessPoints = [AccessPoint]
            AccessPoint = {BSSID, ScanInfo}
            BSSID = binary()
            ScanInfo = [Info]
            Info = {Key, binary()}
            Key = custom
                | encode
                | essid
                | freq
                | genie
                | mode
                | qual
                | rate
            Options = [{essid, binary()}]

    Initiate a wireless scan and return the scan list.

wierl:format(AccessPoints) -> proplist()

    Decode some of the binary data values returned in the list of
    access points.


param(Ifname) -> Parameters
param(Ifname, Attr) -> binary() | {error, unsupported}
        | {error, posix()}
param(Socket, Ifname, Attr) -> binary() | {error, unsupported}
        | {error, posix()}

    Types   Ifname = binary()
            Socket = int()
            Attr = {Key,Value} | Key
            Key = name
                | nwid
                | freq
                | mode
                | essid
                | encode
                | range
                | ap
                | rate
                | power
            Value = binary() | integer()
            Parameters = [Parameter]
            Parameter = {name, binary()}
                | {nwid, binary()}
                | {freq, binary()}
                | {mode, binary()}
                | {essid, binary()}
                | {encode, binary()}
                | {range, binary()}
                | {ap, binary()}
                | {rate, binary()}
                | {power, binary()}

    Query or set a wireless parameter.

    param/1 lists all parameters for the interface.

    param/3 queries or sets a single parameter.

    param/2 is a wrapper around param/3 that will open and close the
    netlink socket for the caller.

    Use the wierl module to decode the values, e.g.,

        1> wierl_config:param(<<"wlan0">>, freq).

        2> wierl:decode({freq,<<108,9,0,0,6,0,0,0,0,0,0,0,0,0,0,0>>}).

    To set a parameter, use a key/value as the attribute, e.g.,

        1> wierl_config:param(<<"wlan0">>, {essid, <<"MY ESSID">>}).
        <<"MY ESSID">>

    Depending on the parameter, the value can be either an integer or a
    binary (which will be converted to a pointer to an iw_point struct
    and may require assigning a value to the flag field of the structure).

    To change some parameters, the interface must first be brought
    down. For example, to put the interface into monitor mode:

        wierl_config:param(<<"wlan0">>, {mode, wierl:mode(monitor)}),

up(Ifname) -> ok

    Types   Ifname = binary()

    Configure the interface as up and running.

down(Ifname) -> ok

    Types   Ifname = binary()

    Bring down the interface.

open() -> {ok, FD}

    Types   FD = integer()

    Obtain a netlink socket file descriptor.

close(FD) -> ok

    Types   FD = integer()

    Close the file descriptor.



wierl_monitor:open(Interface) ->  {ok, Socket} | {error, posix()}

    Types   Interface = binary()
            Socket = pid()
    Place a wireless network interface into monitor mode, returning a
    file descriptor (the pid of a gen_server holding the fd) that can
    be used for reading 802.11 frames.

wierl_monitor:close(Socket) ->  ok | {error, posix()}

    Types   Socket = pid()
            Interface = binary()

    Close the file descriptor associated with the wireless device. close/1
    leaves the device in monitor mode.

wierl_monitor:read(Socket) -> {ok, Frame} | {error, posix()}
wierl_monitor:read(Socket, Size) -> {ok, Frame} | {error, posix()}

    Types   Socket = pid()
            Size = integer()
            Frame = binary()

    Attempt to read a frame from the wireless device.

wierl_monitor:write(Socket, Frame) -> ok | {error, posix()}

    Types   Socket = pid()
            Frame = binary()

    Attempt to write a frame to the wireless device.

wierl_monitor:frame(Socket, Frame) -> {Radiotap, FrameControl,
    FrameBody, FrameCheckSequence} | {error, bad_frame}
wierl_monitor:frame(Socket, {FrameControl, FrameBody}) -> Frame

    Types   Socket = pid()
            Frame = binary()
            Radiotap = #ieee802_11_radiotap{}
            FrameControl = #ieee802_11_fc{}
            FrameBody = #ieee802_11_management{}
                | #ieee802_11_cf_rts{},
                | #ieee802_11_cf_cts{},
                | #ieee802_11_cf_ack{},
                | #ieee802_11_cf_ps{},
                | #ieee802_11_cf_cfend{},
                | #ieee802_11_cf_bar{},
                | #ieee802_11_cf_ba{},
                | #ieee802_11_data{}
            FrameCheckSequence = integer()

    Encode or decode an 802.11 wireless frame between binaries and
    records. Include the wierl_frame header to have access to the
    record structures:



rfkill is a wireless soft kill switch.


block() -> ok | {error, posix()}

    Disable wireless devices.

unblock() -> ok | {error, posix()}

    Enable wireless devices.

list() -> #rfkill_event{} | {error, posix()}

    Monitor rfkill device events.


  • get stats from /proc/net/wireless

  • wierl_monitor

    • sending frames
    • cleanup: redundant constants between wierl/procket
    • frame/1: allow the caller to specify the header type
  • support Mac OS X

  • wierl: support decoding

    • encode, genie, name, rate