View Source VintageNet.Connectivity.Inspector (vintage_net v0.13.3)

This module looks at the network activity of all TCP socket connections known to Erlang/OTP to deduce whether the internet is working.

To use it, call check_internet/2, save the returned cache, and then call it again a minute later (or so). If any socket has transferred data in both directions to an off-LAN host on the interface of interest, then it will return that the internet is available.

This has a couple advantages:

  1. No data is sent to perform the check which is good for metered connections
  2. Most long-lived TCP connections have a keepalive mechanism that generates traffic, so this piggy-backs off that existing connectivity check.
  3. Devices can be behind very restrictive firewalls and internet connectivity can still be verified without knowing which IP/port/protocol combinations are allowed.

It is not perfect:

  1. It only works on long-lived TCP connections.
  2. The TCP connection must be sending and receiving data. If the keapalive is longer than the check_internet/2
  3. It doesn't help if nobody is using the network interface.
  4. It may have scalability issues if there are a LOT of TCP sockets.

Link to this section Summary

Types

Cache for use between check_internet/2 calls. Initialize to an empty map.

The return tuple for check_internet/2

Internet connectivity status

Functions

Check whether the internet is accessible on the specified interface

Return true if an IP address is on one of the subnets in a list

Return true if an IP address is in the subnet

Returns true if the specified address is not on the network interface

Link to this section Types

@type cache() :: %{required(port()) => {non_neg_integer(), non_neg_integer()}}

Cache for use between check_internet/2 calls. Initialize to an empty map.

@type result() :: {status(), cache()}

The return tuple for check_internet/2

  • :internet - at least one TCP connection sent and received data to a non-LAN IP address
  • :unknown - no conclusion could be made
  • :no_internet - the interface didn't have an IP address, so Internet is definitely not available

Save the cache away and pass it to the next call to check_internet/2.

@type status() :: :internet | :unknown | :no_internet

Internet connectivity status

  • :internet - the internet is available
  • :unknown - not sure
  • :no_internet - the internet is definitely not available

Link to this section Functions

Link to this function

check_internet(ifname, cache)

View Source
@spec check_internet(VintageNet.ifname(), cache()) :: result()

Check whether the internet is accessible on the specified interface

Pass an empty map for the cache parameter for the first call. Then pass it back the returned cache for each subsequent call. If any TCP socket that's connected to a computer on another subnet and that's using the passed in network interface has send AND received data since the previous call, then :internet is returned. If not, then usually :unknown is returned to signify that internet may be available, but we just don't know. If the interface doesn't have an IP address, then :no_internet is returned, since that's a prerequisite to communicating with anyone on the internet.

@spec on_interface?(:inet.ip_address(), [ip_address_and_mask()]) :: boolean()

Return true if an IP address is on one of the subnets in a list

@spec on_subnet?(:inet.ip_address(), ip_address_and_mask()) :: boolean()

Return true if an IP address is in the subnet

examples

Examples

iex> Inspector.on_subnet?({192,168,0,50}, {{192,168,0,1}, {255,255,255,0}})
true

iex> Inspector.on_subnet?({192,168,5,1}, {{192,168,0,1}, {255,255,255,0}})
false
Link to this function

routed_address?(ifname, ip_address)

View Source
@spec routed_address?(VintageNet.ifname(), :inet.ip_address()) :: boolean()

Returns true if the specified address is not on the network interface

This function is useful for checking whether an address is on the Internet if you don't trust the DNS server. Captive portals, for example, can give back IP addresses that are local. It's not guaranteed, but it would be pointless to check those IP's if you're looking for the Internet.