Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ else
CFLAGS += -std=gnu99
endif

#We need this for netinet/in.h IN6_* macros
CFLAGS += -D_GNU_SOURCE

# If not cross-compiling, then run sudo by default
ifeq ($(origin CROSSCOMPILE), undefined)
SUDO_ASKPASS ?= /usr/bin/ssh-askpass
Expand Down
9 changes: 9 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use Mix.Config

#config :nerves_network_interface, :managed_interfaces,
# ["eth0", "ens38"]

# Other possible configurations:
# 1. Manage all available interfaces - explicitly said implicit equivalen of no :managed interfaces provided
# config :nerves_network_interface, :managed_interfaces,
# "all"
32 changes: 32 additions & 0 deletions lib/nerves_network_interface.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ defmodule Nerves.NetworkInterface do
ensure that the port process is running as a privileged user.
"""

@type interface_name :: String.t
@type registration ::
{:ok, pid} |
{:error, {:already_registered, pid}}

@doc """
Return the list of network interfaces on this machine.
"""
Expand Down Expand Up @@ -93,4 +98,31 @@ defmodule Nerves.NetworkInterface do
Returns `:ok` on success or `{:error, reason}` if an error occurs.
"""
defdelegate setup(ifname, options), to: Nerves.NetworkInterface.Worker

@doc """
Register for Nerves.NetworkInterface events on a specific interface

The calling process is the process that will be registered for
all events. The events can be handled by implementing a `handle_info\2`.

`def handle_info({Nerves.NetworkInterface, :ifchanged, ifstate} = event, state)`

Use :all to register for events from all interfaces.

The registration registers for messages dispatched out of `Registry`.

For information on how `Registry` works please see that module's
documentation.
"""
@spec register(:all | interface_name) ::
registration |
[registration] |
[]
def register(:all) do
Enum.each(interfaces(), &register/1)
end

def register(ifname) do
Registry.register(Nerves.NetworkInterface, ifname, [])
end
end
32 changes: 31 additions & 1 deletion lib/network_interface/worker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ defmodule Nerves.NetworkInterface.Worker do
is_broadcast: boolean,
is_lower_up: boolean,
is_multicast: boolean,
"is_all-multicast": boolean,
is_up: boolean,
is_running: boolean,
mac_address: mac_address,
Expand Down Expand Up @@ -125,8 +126,37 @@ defmodule Nerves.NetworkInterface.Worker do
{ :ok, %Nerves.NetworkInterface.Worker{port: port} }
end

#Returns intersection of lists a and b
defp intersect(a, b), do: a -- (a -- b)

# Returns list of interfaces to be managed by Nerves.NetworkInterface and Nerves.Network modules
# By default this is list of ALL network interfaces available in the system. It can be reduced
# by specifying a list of interfaces we want to be managed by Nerves.Network sub-system in the
# .../config/config.exs file.
defp get_managed_interfaces(available_interfaces) do
managed_interfaces = Application.get_env(:nerves_network_interface, :managed_interfaces, [])
Logger.debug "#{__MODULE__}: managed_interfaces = #{inspect managed_interfaces}"

case managed_interfaces do
"all" -> available_interfaces
nil -> available_interfaces
[] -> available_interfaces
_ -> managed_interfaces
end
end

def handle_call(:all_interfaces, _from, state) do
available_interfaces = call_port(state, :interfaces, [])
{:reply, available_interfaces, state }
end

def handle_call(:interfaces, _from, state) do
response = call_port(state, :interfaces, [])
available_interfaces = call_port(state, :interfaces, [])
response =
get_managed_interfaces(available_interfaces)
|> intersect(available_interfaces)
Logger.debug "#{__MODULE__}: response: #{inspect response}"
IO.puts "#{__MODULE__}: response: #{inspect response}"
{:reply, response, state }
end
def handle_call({:status, ifname}, _from, state) do
Expand Down
15 changes: 14 additions & 1 deletion src/erlcmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,21 @@ int erlcmd_encode_errno_error(char *buf, int *index, int err)
case EROFS: reason = "erofs"; break;
case EMLINK: reason = "emlink"; break;
case EPIPE: reason = "epipe"; break;
case ENETDOWN: reason = "enetdown"; break;
case ENETUNREACH: reason = "enetunreach"; break;
case ENETRESET: reason = "enetreset"; break;
case ECONNABORTED: reason = "econnaborted"; break;
case ECONNRESET: reason = "econnreset"; break;
case EADDRNOTAVAIL: reason = "eaddrnotavail"; break;
default: reason = "unknown"; break;
case ENOBUFS: reason = "enobufs"; break;
case EISCONN: reason = "eisconn"; break;
case ENOTCONN: reason = "enotconn"; break;
case ETOOMANYREFS: reason = "etoomanyrefs"; break;
case ETIMEDOUT: reason = "etimedout"; break;
case ECONNREFUSED: reason = "econnrefused"; break;
case EHOSTDOWN: reason = "ehostdown"; break;
case EHOSTUNREACH: reason = "ehostunreach"; break;
default: reason = "unknown"; break;
}
return erlcmd_encode_error_tuple(buf, index, reason);
}
Expand Down
Loading