Discover, setup, and get stats on network interfaces
Clone or download
Permalink
Failed to load latest commit information.
.circleci Circle! Mar 17, 2018
lib Add typespecs Nov 3, 2017
src Add $CFLAGS to c99 test script Nov 26, 2017
test implement some simple tests Aug 15, 2017
.gitignore NetBasic->Nerves.NetworkInterface May 19, 2016
CHANGELOG.md v0.4.4 release Nov 26, 2017
CODE_OF_CONDUCT.md Add links to contribution guides Aug 31, 2018
CONTRIBUTING.md
ISSUE_TEMPLATE.md
LICENSE Initial commit Jun 24, 2014
Makefile
README.md
mix.exs Sync dialyxir and ex_doc deps with other projects Aug 20, 2018
mix.lock Sync dialyxir and ex_doc deps with other projects Aug 20, 2018

README.md

Nerves.NetworkInterface

CircleCI

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.

Nerves.NetworkInterface or Nerves.Networking?

The purpose of Nerves.NetworkInterface is to handles low level access to Linux network interfaces. The Nerves.Networking module currently also takes care of the low level stuff, and also of IP address assignment. The low level functionality in Nerves.Networking should be removed in favor of Nerves.NetworkInterface. The Nerves.InterimWifi project does already make use of the functionality offered by Nerves.NetworkInterface.

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:

  1. Add nerves_network_interface to your list of dependencies in mix.exs:

    def deps do [{:nerves_network_interface, "~> 0.3.2"}] end

  2. Run mix deps.get and mix 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: "e0:db:55:e7:8b:53",
        mac_broadcast: "ff:ff:ff:ff:ff:ff", 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 to the Nerves.NetworkInterface Registry.

The following example shows how to view events at the prompt:

iex> Registry.register(Nerves.NetworkInterface, "eth0", [])
{:ok, #PID<0.106.0>}
iex> flush()
:ok
# Plug Ethernet cable in
iex> flush()
{Nerves.NetworkInterface, :ifchanged,
 %{ifname: "eth0", index: 2, is_broadcast: true, is_lower_up: true,
   is_multicast: true, is_running: true, is_up: true,
   mac_address: "e0:db:55:e7:8b:53",
   mac_broadcast: "ff:ff:ff:ff:ff:ff", 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 now wlxc83a35ca5f10
  • ifchanged - an interface changed status (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",
        mac_address: "e0:db:55:e7:8b:51"}

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

Testing

To run tests you will need a linux machine with ip, iproute2 and sudo access. See (#Permissions)[Permissions] for more info. by default mix test does not include external. To run all the unit tests you should do mix test --include external

Licensing

This package is licensed under the Apache 2.0 license.