Ориентация главы

Главы 63–70 решили «как данные утекают»: адреса, порты, буферы, DNS, TCP, UDP, прокси. Эта глава добавляет вторую половину картины — увидеть себя: какие сетевые карты у этой машины, какие адреса висят на каждой, как называется петлевой интерфейс, каков предпочтительный адрес машины. Эта информация незаменима в четырёх сценариях: стартовые журналы, печатающие сетевое окружение; административные диагностические страницы с данными узла; выбор адреса привязки на многосетевых машинах; и идентификатор scope, который обязаны нести IPv6 link-local адреса. Их формы на нативных API печально фрагментированы — GUID адаптеров Windows, if_nametoindex POSIX, разные системы имён на платформах — XRT стягивает их в маленький модуль без зависимостей от движка: ни Socket, ни потоков, ни DNS; свободно сочетается с любым транспортным слоем.

71.1引入

Предположим, вы пишете стартовый поток распределённого сервиса. Эксплуатация требует, чтобы каждый стартовый журнал нёс «имя хоста + локальный адрес + аппаратный идентификатор», чтобы узел мгновенно находился среди тысяч строк; админ-эндпоинт /health показывает тот же набор; на многосетевой машине конфиг даёт имя интерфейса eth0, и вам нужен его индекс для IPv6-мультикаста; и та классическая ошибка — fe80::1 не соединяется, потому что link-local адрес полон только в форме fe80::1%3 (3 — индекс интерфейса).

По отдельности эти потребности несложны; вместе — межплатформенное болото: «имя» интерфейса Windows — GUID, отображаемое имя — «Ethernet»; каноническое имя Linux — eth0; петлевой интерфейс на двух сторонах называется совершенно по-разному. Аппаратные адреса на Windows берутся через GetAdaptersAddresses, на POSIX — через ioctl, и длина не обязательно 6 байт. Собственный сток стоит по ветке на каждую платформу, а модуль интерфейсов XRT уже сделал эту работу: один вызов даёт согласованную структуру-снимок, имя и индекс конвертируются в обе стороны, локальная тройка (адрес/аппаратура/имя хоста) — по три удобных формы на каждую.

71.2概念

Снимок интерфейсов: одно распределение, все виды заимствованы

xrtNetInterfaces создаёт согласованный снимок текущих интерфейсов и адресов системы: одно распределение XRT вмещает массив интерфейсов, массив адресов, имена и аппаратные адреса; после этого все поля — заимствованные представления.

1ПеречислениеxrtNetInterfaces(&List) — один системный запрос строит снимок
2ЧтениеItems[i].Name / Addresses[j] — всё заимствовано из хранилища снимка
3ОсвобождениеxrtNetInterfacesFree(&List) — возврат всего хранилища и обнуление структуры

Ценность снимка — согласованность: добавление/удаление интерфейсов в процессе перечисления не рассинхронизирует записи; цена — моментальный срез без подписки на изменения. Метаданные на интерфейс: IPv4Index/IPv6Index (Windows ведёт раздельно; POSIX обычно одинаково), битовые Flags, Mtu, виды Name (каноническое) и DisplayName (отображаемое), сырые байты HardwareAddress, массив Addresses — каждый адрес с PrefixLength (0..32 для IPv4, 0..128 для IPv6; XNET_INTERFACE_PREFIX_UNKNOWN, когда платформа не может сказать).

Две дисциплины использования: порядок интерфейсов и адресов решает ОС — не считайте порядок идентичностью; после освобождения виды умирают мгновенно — все чтения обязаны предшествовать Free.

Флаги: стабильное межплатформенное пересечение

Flags открывают только шесть флагов, стабильно наблюдаемых на всех платформах: UP (в сети), RUNNING (работает), LOOPBACK (петля), BROADCAST (широковещание), POINT_TO_POINT (точка-точка), MULTICAST (поддержка мультикаста). Флаг без надёжного источника на некоторой платформе остаётся невыставленным — невыставленный ≠ возможности нет, лишь платформа не видит. «Можно ли вступить в мультикаст-группу» читает MULTICAST; «петля ли это» — LOOPBACK; каждое — одно битовое И.

Имена и индексы: конвертация в обе стороны

У интерфейсов две системы идентичности. Индекс — ключ мира ядра (IPv6 scope и управление членством мультикаста используют его); имя — ключ мира людей (в конфигах пишут его):

  • xrtNetInterfaceIndex(名称, 族) возвращает индекс; нулевой индекс — не результат; промах сообщает XERR_NOT_FOUND.
  • xrtNetInterfaceName(索引, 族, 缓冲, 容量) выводит каноническое имя в обратную сторону, возвращая нужную длину; пустой буфер сначала меряет, недостаточный безопасно усекает, дополняет нулём и возвращает полную нужную длину — то же двухчастное соглашение, что у текстовых API главы 63.

Различия имён поглощаются модулем: на Windows каноническое имя — системное имя адаптера (вида GUID), отображаемое — псевдоним интерфейса; на POSIX оба — if_name. Index принимает и каноническое, и отображаемое имя; запрос с UNSPEC предпочитает IPv6-индекс, откатываясь на IPv4.

Локальная тройка: три уровня

Диагностический набор «имя хоста, локальный адрес, аппаратный адрес» имеет три уровня использования, и API делится по уровням:

УровеньАдресАппаратураИмя хостаСценарии
Структура/байтыxrtNetLocalAddressxrtNetLocalHardwarexrtNetHostNameПродолжение в бинарной форме (соединения, сравнения)
Двухчастный текстxrtNetLocalAddressTextxrtNetLocalHardwareText— (HostName уже текст)Фиксированные буферы, среды без распределений
String-удобствоxrtNetLocalAddressStringxrtNetLocalHardwareStringxrtNetHostNameStringСтартовые журналы и диагностические страницы одним махом

Выбор xrtNetLocalAddress — детерминированный запрос предпочтения: последовательно предпочитаются UP, RUNNING, не-петля, не-link-local интерфейсы; при равенстве UNSPEC предпочитает IPv6. Он подходит стартовым журналам и отчётам узла, но не публичный исходящий адрес и не маршрут по умолчанию — для точного выбора обходите xrtNetInterfaces и решайте сами. Текст аппаратного адреса — компактный HEX в верхнем регистре без разделителей (MAC 6 байт — 12 символов); для двоеточий и иных форматов показа читайте сырые байты и форматируйте сами. Уровень String возвращает строки, освобождаемые xrtFree; проверка на пустоту и есть обработка ошибки (семантика запроса — ошибка потока не ставится).

Нежданный подарок: разбор IPv6 scope

С включённым модулем xrtNetAddrParse и xrtNetAddrParseEndpoint главы 63 принимают одновременно числовой scope и scope-имя интерфейса: разбираются и fe80::1%3, и fe80::1%eth0; можно и [fe80::1%eth0]:8080. Результат разбора хранит только стабильный числовой индекс интерфейса; текстовый вывод (xrtNetAddrText) сохраняет каноническую форму без системных запросов — имена меняются с конфигурацией системы, индекс — постоянно сравнимая идентичность.

71.3示例

Первая полная программа: перечисление интерфейсов и префиксов адресов

Следующая программа из examples/network/interface/main.c обходит все локальные интерфейсы, печатая имя, двухстековые индексы, MTU и префикс каждого адреса — разовая панорама для осмотра многосетевой машины:

examples/network/interface/main.c源码 ↗
#include <stdio.h>

#include <xrt.h>


















 */


/* 列出本机接口以及可用于绑定、Scope 和多播的地址元数据。 */
int main(void)
{
	xnetinterfacelist List;
	size_t i;

	if ( !xrtNetInterfaces(&List) ) {
		return 1;
	}
	for ( i = 0; i < List.Count; i++ ) {
		const xnetinterface* pInterface = &List.Items[i];
		size_t j;

		printf("%.*s (%.*s) index4=%u index6=%u mtu=%u\n",
			(int)pInterface->Name.Size, pInterface->Name.Data,
			(int)pInterface->DisplayName.Size, pInterface->DisplayName.Data,
			(unsigned int)pInterface->IPv4Index,
			(unsigned int)pInterface->IPv6Index,
			(unsigned int)pInterface->Mtu);
		for ( j = 0; j < pInterface->AddressCount; j++ ) {
			const xnetinterfaceaddress* pAddress = &pInterface->Addresses[j];
			char sAddress[96];

			if ( xrtNetAddrText(
				&pAddress->Address, sAddress, sizeof(sAddress)
			) == XRT_NPOS ) {
				xrtNetInterfacesFree(&List);
				return 1;
			}
			printf("  %s/%u\n", sAddress,
				(unsigned int)pAddress->PrefixLength);
		}
	}
	xrtNetInterfacesFree(&List);
	return 0;
}
$ gcc -O1 -DXRT_MODULE_ALL -I single -include xrt.h impl.c examples/network/interface/main.c -lws2_32 -liphlpapi(输出随机器变化:每个接口一行"名称 (显示名) index4=.. index6=.. mtu=..",其下每条地址一行"地址/前缀位数",如 127.0.0.1/8 与 ::1/128)

Что только что произошло. Три пункта. (1) xrtNetInterfaces одним вызовом делает перечисление и снимок; List.Count и List.Items — все интерфейсы, без дескрипторов, которые надо закрывать по одному. (2) Имя и отображаемое имя интерфейса — xstrview, печать через %.*s с Size; адреса переиспользуют xrtNetAddrText главы 63 для текста, XRT_NPOS сигнализирует нехватку буфера. (3) PrefixLength приписывается прямо к адресу — строки в стиле CIDR 127.0.0.1/8, 192.168.1.10/24 — реальные префиксы из снимка. Вывод зависит от машины, поэтому ожидаемый вывод в заголовке примера — описание, а не фиксированный текст.

Вторая полная программа: круговорот имя-индекс и локальная тройка

Вторая программа из examples/network/interface_tour/main.c соединяет круговорот имя → индекс → имя и двухчастные запросы локального адреса, аппаратуры и имени хоста в один осмотр:

examples/network/interface_tour/main.c源码 ↗

















 */

#include <stdio.h>
#include <string.h>
#include <xrt.h>

int main(void)
{
	char sName[64];
	char sText[64];
	uint8 Hardware[16];
	xnetaddr Address;
	uint32 iIndex;
	size_t iSize = 0;
	size_t iNeed = 0;
	int iResult = 1;

	/* ---- InterfaceIndex / InterfaceName:回环往返 ---- */
		#if defined(_WIN32) || defined(_WIN64)
    iIndex = xrtNetInterfaceIndex("loopback4", XNET_FAMILY_IPV4);
#elif defined(__APPLE__)
    iIndex = xrtNetInterfaceIndex("lo0", XNET_FAMILY_IPV4);
#else
    iIndex = xrtNetInterfaceIndex("lo", XNET_FAMILY_IPV4);
#endif
	if ( iIndex == 0u ) {
		/* Windows 命名不同:回环显示名 "Loopback Pseudo-Interface 1"。 */
		iIndex = xrtNetInterfaceIndex(
			"Loopback Pseudo-Interface 1", XNET_FAMILY_IPV4);
	}
	if ( iIndex == 0u ) {
		goto Cleanup;  /* 找不到回环:环境异常 */
	}
	/* InterfaceName 两段式:查询 → 写入 → 回环索引反查一致。 */
	iNeed = xrtNetInterfaceName(iIndex, XNET_FAMILY_IPV4, NULL,
		0u);
	if ( (iNeed == 0u) || (iNeed >= sizeof(sName)) ) {
		goto Cleanup;
	}
	iSize = xrtNetInterfaceName(iIndex, XNET_FAMILY_IPV4, sName,
		sizeof(sName));
	if ( (iSize == 0u) || (iSize != iNeed) ) {
		goto Cleanup;
	}
	/* 名字反查索引一致(roundtrip)。 */
	if ( xrtNetInterfaceIndex(sName, XNET_FAMILY_IPV4) !=
		iIndex ) {
		/* 显示名与规范名可能不同:跳过反查但记录。 */
		printf("iface: (display-name index differs) ");
	}
	printf("iface: loopback index!=0 name=[%s] ok\n", sName);

	/* ---- LocalAddress / Text ---- */
	if ( !xrtNetLocalAddress(&Address, XNET_FAMILY_IPV4) ||
		(Address.Family != XNET_FAMILY_IPV4) ||
		(Address.Port != 0u) ) {
		goto Cleanup;
	}
	iNeed = xrtNetLocalAddressText(XNET_FAMILY_IPV4, NULL, 0u);
	if ( (iNeed == 0u) || (iNeed >= sizeof(sText)) ) {
		goto Cleanup;
	}
	iSize = xrtNetLocalAddressText(XNET_FAMILY_IPV4, sText,
		sizeof(sText));
	if ( (iSize == 0u) || (iSize != iNeed) ||
		(strchr(sText, '.') == NULL) ) {
		goto Cleanup;  /* IPv4 文本必含点 */
	}
	printf("iface: local addr=[%s]", sText);

	/* ---- LocalHardware / Text:MAC 至少 6 字节。 ---- */
	iNeed = xrtNetLocalHardware(NULL, 0u);
	if ( (iNeed < 6u) || (iNeed > sizeof(Hardware)) ) {
		goto Cleanup;
	}
	iSize = xrtNetLocalHardware(Hardware, sizeof(Hardware));
	if ( iSize != iNeed ) {
		goto Cleanup;
	}
	iNeed = xrtNetLocalHardwareText(NULL, 0u);
	if ( (iNeed < 12u) || (iNeed >= sizeof(sText)) ) {
		goto Cleanup;  /* 6 字节 → 12 个 HEX 字符 */
	}
	iSize = xrtNetLocalHardwareText(sText, sizeof(sText));
	if ( (iSize != iNeed) ) {
		goto Cleanup;
	}
	printf(" hw=%s", sText);

	/* ---- HostName:非空且可写入。 ---- */
	iNeed = xrtNetHostName(NULL, 0u);
	if ( (iNeed == 0u) || (iNeed >= sizeof(sName)) ) {
		goto Cleanup;
	}
	iSize = xrtNetHostName(sName, sizeof(sName));
	if ( (iSize == 0u) || (iSize != iNeed) ) {
		goto Cleanup;
	}
	printf(" host=[%s] ok\n", sName);
	iResult = 0;

Cleanup:
	return iResult;
}
$ gcc -O1 -DXRT_MODULE_ALL -I single -include xrt.h impl.c examples/network/interface_tour/main.c -lws2_32 -liphlpapiiface: loopback index!=0 name=[[GUID]] okiface: local addr=[192.168.0.66] hw=00E04C7D7E66 host=[DESKTOP-DQCMPS1] ok

Что только что произошло. (1) Петлевой интерфейс сначала пробуется под POSIX-именем loopback4, при неудаче — под отображаемым именем Windows Loopback Pseudo-Interface 1 — стандартная запись «межплатформенная разность имён поглощается одним откатом на стороне вызова». (2) Двухчастность InterfaceName: сначала NULL/0 меряет нужную длину, затем запись и сверка двух возвратов; получив каноническое имя, обратный запрос индекса делает контроль круговорота (платформы, где отображаемое и каноническое имена различаются, могут пропустить обратный запрос). (3) Локальная тройка проверяется по очереди: LocalAddress со структурой-выходом и проверкой семейства и нулевого порта, LocalAddressText с выходом, обязательно содержащим точку (текстовый признак IPv4), LocalHardware с сырыми байтами не меньше 6, LocalHardwareText ровно вдвое больше байт HEX-символами, HostName непуст и записываем. Любой провал идёт через единый Cleanup с ненулевым возвратом — «осмотр», записанный как цепочка «упал — дальше не идём», читается куда лучше россыпи if.

Третья полная программа: диагностическая страница одним взглядом (уровень String)

Третья программа из examples/network/local_info/main.c собирает стартовую тройку одним махом через уровень String, с текстом-заглушкой при отсутствии аппаратного адреса:

examples/network/local_info/main.c源码 ↗
#include <stdio.h>

#include <xrt.h>
















 */


/* 一次读取适合启动日志和诊断页展示的本机网络信息。 */
int main(void)
{
	str sAddress = xrtNetLocalAddressString(XNET_FAMILY_UNSPEC);
	str sHost = xrtNetHostNameString();
	str sHardware = xrtNetLocalHardwareString();

	if ( (sAddress == NULL) || (sHost == NULL) ) {
		xrtFree(sAddress);
		xrtFree(sHost);
		xrtFree(sHardware);
		return 1;
	}
	printf("host = %s\n", sHost);
	printf("address = %s\n", sAddress);
	printf("hardware = %s\n", sHardware != NULL ? sHardware : "unavailable");
	xrtFree(sHardware);
	xrtFree(sHost);
	xrtFree(sAddress);
	return 0;
}
$ gcc -O1 -DXRT_MODULE_ALL -I single -include xrt.h impl.c examples/network/local_info/main.c -lws2_32 -liphlpapi(输出随机器变化:host = 主机名、address = 本机地址、hardware = 大写紧凑 HEX 或 unavailable)

Что только что произошло. Контракт уровня String проявляется здесь: возврат str (освобождение xrtFree), NULL означает недоступность без установки ошибки потока — проверка на пустоту и есть вся обработка ошибок. Отсутствие адреса или имени хоста считается аномалией среды с возвратом 1, тогда как аппаратный адрес в чисто петлевой среде (контейнеры, VM без карт) может законно отсутствовать — печатается unavailable, и работа продолжается. Освобождение трёх строк собрано в конце — даже промежуточная неудача освобождает всё через xrtFree: xrtFree(NULL) — отсутствие операции, построчные проверки не нужны.

71.4契约

  • Владение снимком: Interfaces владеет всем хранилищем одним распределением; виды полей только заимствуют; InterfacesFree возвращает и обнуляет структуру, вызываем повторно на пустом списке; неудача не меняет выход.
  • Порядок не гарантирован: порядок интерфейсов и адресов решает ОС и не может служить стабильной идентичностью; идентичность — индекс (число) и каноническое имя.
  • Имя/индекс: нулевой индекс — не результат; Index принимает каноническое и отображаемое имена, UNSPEC предпочитает IPv6-индекс; Name следует двухчастному соглашению текстовых API (мерить → писать; нехватка безопасно усекается и возвращает полную нужную длину).
  • Границы уровня удобства: LocalAddress — детерминированный запрос предпочтения (UP/RUNNING/не-петля/не-link-local, UNSPEC предпочитает IPv6) — не публичный исходящий, не маршрут по умолчанию, не замена политике прослушивания и адреса-источника; точный выбор — обход Interfaces.
  • Текстовый уровень: текст аппаратного адреса — компактный HEX верхнего регистра; уровень String возвращает xrtFree-освобождаемые строки, NULL значит недоступность, ошибка потока не ставится (семантика запроса).
  • Ошибки: неудачи сообщаются через xrtGetError() — XERR_NOT_FOUND (интерфейс/адрес/аппаратура отсутствуют), XERR_IO (сбой системного перечисления), XERR_RANGE + XNET_ERROR_BUFFER (нехватка буфера), домен xrt.net.
  • Зависимости и обрезка: XRT_MODULE_NET_INTERFACE зависит только от базового слоя сетевых адресов — без Socket, Engine, потоков, DNS и контейнеров; XRT_MODULE_NET_INTERFACE_TEXT — отдельный тонкий слой с HEX-кодированием.

Типичные ошибки

Ловушка 1: LocalAddress как публичный исходящий или адрес привязки:Ловушка 1: LocalAddress как публичный исходящий или адрес привязки

Симптомы: сервис недостижим в многосетевых/NAT-средах — «локальный адрес» в журнале принадлежит какому-то интрасетевому интерфейсу, а не адресу, достижимому пиром; или после привязки к нему сервис недоступен извне контейнера.

Причина: xrtNetLocalAddress — выбор предпочтения (предпочитает онлайнные, работающие, не-петлевые, не-link-local unicast-адреса); он не знает таблицу маршрутизации и тем более публичный исходящий за NAT. Использовать его как «внешне достижимый адрес» или единственный адрес привязки — значит принять диагностическую информацию за решение о маршрутизации.

错误写法
xnetaddr Addr;
xrtNetLocalAddress(&Addr, XNET_FAMILY_UNSPEC);
/* напрямую регистрируем Addr как «адрес, по которому пир ко мне подключится» */
register_service(xrtNetAddrText(&Addr, ...));
正确写法
   многосетевая привязка — обход снимка и собственное решение */
xnetinterfacelist List;
if ( xrtNetInterfaces(&List) ) {
	for ( size_t i = 0; i < List.Count; i++ ) {
		const xnetinterface* pIf = &List.Items[i];
		if ( (pIf->Flags & XNET_INTERFACE_UP) == 0 ) {
			continue;
		}
		/* отбор по бизнес-правилам: семейство, префикс, мультикаст... */
	}
	xrtNetInterfacesFree(&List);
}
Ловушка 2: заимствованные виды после освобождения снимка:Ловушка 2: заимствованные виды после освобождения снимка

Симптомы: редкие падения или мусорные байты — обычно в коде «кэширующем данные интерфейсов».

Причина: Items[i].Name.Data, Addresses[j], HardwareAddress.Data — всё указывает во внутреннее хранилище снимка; после xrtNetInterfacesFree все они повисают. Снимок — моментальный срез со семантикой значения, а не долго удерживаемый объект.

错误写法
xnetinterfacelist List;
xrtNetInterfaces(&List);
const xstrview Name = List.Items[0].Name;   /* заимствованный вид */
const xnetinterfaceaddress* Addrs = List.Items[0].Addresses;
xrtNetInterfacesFree(&List);                /* хранилище возвращено */
printf("%.*s\n", (int)Name.Size, Name.Data); /* повисшее чтение */
正确写法
xnetinterfacelist List;
if ( xrtNetInterfaces(&List) ) {
	for ( size_t i = 0; i < List.Count; i++ ) {
		const xnetinterface* pIf = &List.Items[i];
		printf("%.*s\n", (int)pIf->Name.Size, pIf->Name.Data);
		/* информацию, которую надо сохранить, копируйте в собственное хранилище прямо сейчас */
	}
	xrtNetInterfacesFree(&List);
}
Ловушка 3: длина аппаратного адреса зашита в 6 байт:Ловушка 3: длина аппаратного адреса зашита в 6 байт

Симптомы: обрезанные буферы или неверные длины на платформах с 8-байтовыми EUI-64 или некоторыми виртуальными интерфейсами.

Причина: 6 байт MAC-48 — лишь «типичное значение»; контракт модуля прямо говорит, что LocalHardware возвращает требуемое число байт и не зашивает длину; Size вида HardwareAddress тоже решает система.

错误写法
uint8 Mac[6];
if ( xrtNetLocalHardware(Mac, sizeof(Mac)) == 0 ) {
	/* предположение 6 байт: более длинные адреса молча усекаются */
}
正确写法
size_t iNeed = xrtNetLocalHardware(NULL, 0u);   /* сначала меряем */
if ( (iNeed == 0u) || (iNeed > 16u) ) {
	return 1;
}
uint8 Hardware[16];
size_t iSize = xrtNetLocalHardware(Hardware, iNeed);
/* только iSize == iNeed — полный адрес; длина HEX-текста 2*iSize */

Практические задания

Базовое: отчёт по петлевому интерфейсу

Перечислите снимок, найдите интерфейс с XNET_INTERFACE_LOOPBACK во Flags и напечатайте его имя, двухстековые индексы и все адреса. Критерий приёмки: по одному запуску на Windows и Linux (подойдёт и WSL), обе стороны корректно печатают данные петли; после освобождения снимка программа нормально завершается.

Продвинутое: селектор сетевой карты для мультикаста

Напишите функцию uint32 pick_multicast_iface(void): обходя снимок, выберите интерфейс «в сети, с мультикастом, не петля, с максимальным MTU», верните его IPv6-индекс или 0 при отсутствии. Подсказка: проверяйте во Flags одновременно XNET_INTERFACE_UP и XNET_INTERFACE_MULTICAST; петлю исключайте по XNET_INTERFACE_LOOPBACK; не забудьте InterfacesFree перед возвратом.

Вызов: диагностическая страница узла

Реализуйте print_diagnostics(void): одним махом печатайте имя хоста (HostName двухчастно), локальный адрес (LocalAddressText двухчастно, семейство UNSPEC), аппаратный адрес (LocalHardware сырыми байтами, самостоятельно форматируя в HEX верхнего регистра с двоеточиями, как 00:E0:4C:7D:7E:66), общее число интерфейсов и адресов (из снимка). Критерий приёмки: весь вывод без единой утечки (сверка со статистикой распределений главы 6); отсутствие аппаратного адреса печатает hardware: unavailable, а не падение; два возврата каждого двухчастного вызова сверены построчно.

Итоги

ТемаКраткая справка
СнимокInterfaces владеет всем одним распределением; виды заимствованы; InterfacesFree обнуляет и повторяем; порядок — не идентичность
Метаданные интерфейсадвухстековые индексы / Flags / Mtu / Name+DisplayName / HardwareAddress / Addresses+PrefixLength
ФлагиUP RUNNING LOOPBACK BROADCAST POINT_TO_POINT MULTICAST; невыставленный ≠ возможности нет
Имя↔индексInterfaceIndex (имя → индекс, 0 = неудача) / InterfaceName (индекс → имя, двухчастно); UNSPEC предпочитает IPv6
Локальная тройкаадрес (запрос предпочтения, не публичный исходящий) / аппаратура (длина варьируется) / имя хоста (локальная метка, не DNS-имя)
Три уровнявыход-параметр (продолжить в бинарном) → Text двухчастный (без распределений) → String (журналы одним махом, xrtFree + проверка на пустоту)
Текст аппаратурыHEX верхнего регистра без разделителей (6 байт = 12 символов); форматы показа — сами
IPv6 scopeс включённым модулем разбираются и fe80::1%3, и fe80::1%eth0; хранится стабильный числовой индекс
ОшибкиNOT_FOUND (интерфейс/адрес/аппаратура) / IO (перечисление) / RANGE+BUFFER (нехватка буфера), домен xrt.net
ОбрезкаXRT_MODULE_NET_INTERFACE без зависимостей от движка; слой TEXT отдельно добавляет HEX

📖 Справочники API в этой главе:net_interface (16 записей)net (247 записей)

Полные сигнатуры, ограничения параметров, возвращаемые значения и ошибки