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:
| Bytes | Field |
|---|---|
| 4 | the offset of the next adapter, 0 after the last |
| 4 | a combined index |
| 260 | its name, with a zero after |
| 132 | its description, with a zero after |
| 4, 8 | the length of its hardware address, and the address |
| 4 | its index |
| 4 | its type, as MIB_IF_TYPE_* in Windows (see type/0) |
| 4 | whether DHCP is enabled |
| 4 | a pointer, 0 |
| 40 | its first IP address, and the offset of its next |
| 40 | its first gateway, and the offset of its next |
| 40 | its DHCP server |
| 4, 40, 40 | whether it has WINS, and its two WINS servers |
| 8, 8 | when 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
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
@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() :: :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
@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}]}