Nerves.NetworkInterface
This package enables Elixir applications to configure, get the status of, and listen to events from LAN and WiFi network interfaces. It is not meant as a full-featured network interface management library and lacks a majority of the features available. However, its goal is to support the set of networking parameters that make sense for end systems in home, office, and industrial environments. This includes:
- Enumerating available interfaces
- Reporting when new interfaces appear and disappear (USB WiFi dongle insertion/removal)
- Querying link-level interface status and statistics
- Reporting link-level interface status changes
- Configuring IP addresses, subnets, gateways, etc.
- Bringing interfaces up and down
Currently only IPv4 is supported. If you use IPv6, I’d be interested in working with you to integrate IPv6 support.
Prerequisites
This module requires libmnl to build. If you’re running a Debian-based system, you can get it by running:
sudo apt-get install libmnl-dev
Nerves includes libmnl
by default.
When not crosscompiling, be aware that the Makefile runs sudo
to set the
permissions on the priv/netif
binary, so you’ll be asked your password towards
the end. If you do not require additional privileges to modify network
interfaces on your system, you can bypass the calls to sudo by setting the
SUDO environment variable to true
. I.e., SUDO=true make
.
Installation
If available in Hex, the package can be installed as:
Add
nerves_network_interface
to your list of dependencies inmix.exs
:def deps do [{:nerves_network_interface, "~> 0.3.1"}] end
List
:nerves_network_interface
as an application dependency:def application do [applications: [:nerves_network_interface]] end
- Run
mix deps.get
andmix compile
Permissions
If an application just needs to get information about LAN interfaces,
this library does not require any additional privileges. If it is necessary
to modify the network interfaces, the same privilege needed to run applications
like ifconfig
and ip
will be needed. This can be accomplished by setting
the netif
binary to be setuid root. E.g.,
chown root:root priv/netif
chmod +s priv/netif
Keep in mind that running setuid
on the netif port binary could have
security implications in your system. The Makefile
will automatically call
sudo
to do this, but that can be disabled.
If you do not require additional privileges to modify network
interfaces on your system, you can bypass the calls to sudo
by setting the
SUDO environment variable to true
. I.e., SUDO=true make
.
Running
Start iex
:
$ iex -S mix
The Nerves.NetworkInterface
application will start automatically.
To see which interfaces are available, call Nerves.NetworkInterface.interfaces\0
:
iex> Nerves.NetworkInterface.interfaces
['lo', 'eth0', 'wlan0']
To get link-level status information and statistics on an interface, call
Nerves.NetworkInterface.status/1
:
iex> Nerves.NetworkInterface.status "eth0"
{:ok, %{ifname: 'eth0', index: 2, is_broadcast: true, is_lower_up: true,
is_multicast: true, is_running: true, is_up: true,
mac_address: <<224, 219, 85, 231, 139, 93>>,
mac_broadcast: <<255, 255, 255, 255, 255, 255>>, mtu: 1500, operstate: :up,
stats: %{collisions: 0, multicast: 7, rx_bytes: 2561254, rx_dropped: 0,
rx_errors: 0, rx_packets: 5301, tx_bytes: 944159, tx_dropped: 0,
tx_errors: 0, tx_packets: 3898}, type: :ethernet}
Polling Nerves.NetworkInterface
for status isn’t that great, so it’s possible to
register a GenEvent
with Nerves.NetworkInterface
.
This will change in the future. GenEvent use will be removed.
The following example shows how to view events at the prompt:
iex> defmodule Forwarder do
...> use GenEvent
...> def handle_event(event, parent) do
...> send parent, event
...> {:ok, parent}
...> end
...> end
iex> Nerves.NetworkInterface.event_manager |> GenEvent.add_handler(Forwarder, self())
:ok
iex> flush
:ok
# Plug Ethernet cable in
iex> flush
{:nerves_network_interface, #PID<0.62.0>, :ifchanged,
%{ifname: 'eth0', index: 2, is_broadcast: true, is_lower_up: true,
is_multicast: true, is_running: true, is_up: true,
mac_address: <<224, 219, 85, 231, 139, 93>>,
mac_broadcast: <<255, 255, 255, 255, 255, 255>>, mtu: 1500, operstate: :up,
stats: %{collisions: 0, multicast: 14, rx_bytes: 3061718, rx_dropped: 0,
rx_errors: 0, rx_packets: 7802, tx_bytes: 1273557, tx_dropped: 0,
tx_errors: 0, tx_packets: 5068}, type: :ethernet}}
Events sent by Nerves.NetworkInterface
include:
ifadded
- an interface was hotplugged (e.g., a USB wifi dongle)ifrenamed
- an interface was renamed (e.g.,wlan0
is nowwlxc83a35ca5f10
ifchanged
- an interface changed statue (e.g., it was down, but now it’s up)ifremoved
- an interface was removed (e.g., the user removed a USB wifi dongle)
To get the IP configuration for an interface, call Nerves.NetworkInterface.settings/1
:
iex> Nerves.NetworkInterface.settings "eth0"
{:ok, %{ipv4_address: '192.168.25.114', ipv4_broadcast: '192.168.25.255',
ipv4_gateway: '192.168.25.5', ipv4_subnet_mask: '255.255.255.0'}
To setting IP addresses and other configuration, just call
Nerves.NetworkInterface.setup/2
using keyword parameters or a map with what you’d like
to set. The following example uses keyward parameters:
iex> Nerves.NetworkInterface.setup "eth0", ipv4_address: "192.168.25.200", ipv4_subnet_mask: "255.255.255.0")
:ok
If you get an error, check that you are running Elixir with sufficient privilege
to modify network interfaces or make the netif
binary setuid root.
The library accepts both Erlang strings and Elixir strings. It, however, only returns Elixir strings.
To enable or disable an interface, you can do so with Nerves.NetworkInterface.ifup/1
and
Nerves.NetworkInterface.ifdown/1
. As you would expect, these require privilege to run:
iex> Nerves.NetworkInterface.ifdown "eth0"
:ok
Licensing
This package is licensed under the Apache 2.0 license.