ADS.Adapter (yaads v0.1.0)

Copy Markdown View Source

A network adapter of a TwinCAT system, as its system service lists them, for ADS.Client.adapters/2: index group 701, SYSTEMSERVICE_IPHELPERAPI in Beckhoff's Tc2_Utilities, offset 1, IPHELPERAPI_ADAPTERSINFO, on AMS port 10000. A read of 4 bytes answers the size of the whole list; a read of less than that, :device_invalid_size.

Beckhoff doesn't document how the list comes; this is as TwinCAT 3.1 4026 answers. It is the IP_ADAPTER_INFO of Windows' GetAdaptersInfo, as Microsoft documents it, laid out as a 32-bit program has it, with a 64-bit time_t: 648 bytes for each adapter, each pointer an offset from the start of the list. All numbers are little-endian:

BytesField
4the offset of the next adapter, 0 after the last
4a combined index
260its name, with a zero after
132its description, with a zero after
4, 8the length of its hardware address, and the address
4its index
4its type, as MIB_IF_TYPE_* in Windows (see type/0)
4whether DHCP is enabled
4a pointer, 0
40its first IP address, and the offset of its next
40its first gateway, and the offset of its next
40its DHCP server
4, 40, 40whether it has WINS, and its two WINS servers
8, 8when its DHCP lease was had and when it ends

Each address of 40 bytes is the offset of the next, 0 after the last; the address and the mask as 16 bytes of text each, with zeros after; and 4 bytes more. An adapter's further addresses come after it, before the next adapter. 0.0.0.0 stands for none: an adapter without an address, gateway or DHCP server lists that.

The lease times aren't read: a system has answered bytes there that aren't times, for an adapter without DHCP; nor WINS, which TwinCAT systems don't use. The strings are in the system's code page, as Windows' ANSI functions give them, Windows-1252 unless told otherwise (see ADS.Codepage).

Summary

Types

t()

An adapter's type, as Windows' MIB_IF_TYPE_* and IF_TYPE_IEEE80211 name them, or its number.

Functions

The adapters from the bytes of the list, or :error if they don't make one. No bytes are no adapters.

Types

t()

@type t() :: %ADS.Adapter{
  addresses: [{:inet.ip4_address(), :inet.ip4_address()}],
  description: String.t(),
  dhcp: boolean(),
  dhcp_server: :inet.ip4_address() | nil,
  gateways: [:inet.ip4_address()],
  index: non_neg_integer(),
  mac: String.t(),
  name: String.t(),
  type: type()
}

type()

@type type() ::
  :other
  | :ethernet
  | :token_ring
  | :fddi
  | :ppp
  | :loopback
  | :slip
  | :wireless
  | non_neg_integer()

An adapter's type, as Windows' MIB_IF_TYPE_* and IF_TYPE_IEEE80211 name them, or its number.

Functions

decode_all(bytes, codepage \\ Codepage.default())

@spec decode_all(binary(), ADS.Codepage.t()) :: {:ok, [t()]} | :error

The adapters from the bytes of the list, or :error if they don't make one. No bytes are no adapters.

iex> address = fn ip, mask -> <<0::32, ip::binary-16, mask::binary-16, 0::32>> end
iex> text = fn string -> string <> :binary.copy(<<0>>, 16 - byte_size(string)) end
iex> list =
...>   <<0::32, 9::32-little, "{5E97F165}", 0::size(250)-unit(8), "Intel Ethernet",
...>     0::size(118)-unit(8), 6::32-little, 0, 1, 5, 0x76, 0x34, 0xAE, 0, 0, 9::32-little,
...>     6::32-little, 0::32, 0::32>> <>
...>     address.(text.("10.0.0.5"), text.("255.255.255.0")) <>
...>     address.(text.("10.0.0.1"), text.("255.255.255.255")) <>
...>     address.(text.(""), text.("")) <> <<0::32>> <> address.(<<0::128>>, <<0::128>>) <>
...>     address.(<<0::128>>, <<0::128>>) <> <<0::128>>
iex> ADS.Adapter.decode_all(list)
{:ok, [%ADS.Adapter{name: "{5E97F165}", description: "Intel Ethernet",
                    mac: "00:01:05:76:34:AE", index: 9, type: :ethernet, dhcp: false,
                    addresses: [{{10, 0, 0, 5}, {255, 255, 255, 0}}],
                    gateways: [{10, 0, 0, 1}], dhcp_server: nil}]}