netdevice(7) низкоуровневый доступ к сетевым устройствам Linux

ОБЗОР

#include <sys/ioctl.h>
#include <net/if.h>

ОПИСАНИЕ

В этой справочной странице описан интерфейс сокетов, используемый для настройки сетевых устройств.

Linux поддерживает несколько стандартных вызовов ioctl для настройки сетевых устройств. Они могут применяться для любого файлового дескриптора сокета независимо от семейства или типа сокета. В качестве параметра большинство из них передаёт структуру ifreq:

struct ifreq {
    char ifr_name[IFNAMSIZ]; /* имя интерфейса */
    union {
        struct sockaddr ifr_addr;
        struct sockaddr ifr_dstaddr;
        struct sockaddr ifr_broadaddr;
        struct sockaddr ifr_netmask;
        struct sockaddr ifr_hwaddr;
        short           ifr_flags;
        int             ifr_ifindex;
        int             ifr_metric;
        int             ifr_mtu;
        struct ifmap    ifr_map;
        char            ifr_slave[IFNAMSIZ];
        char            ifr_newname[IFNAMSIZ];
        char           *ifr_data;
    };
};

Обычно, пользователь указывает имя нужного устройства в ifr_name. Все остальные поля структуры могут занимать единое пространство в памяти.

Вызовы ioctl

Если указано, вызов ioctl считается привилегированным, то для его использования необходимо иметь эффективный идентификатор пользователя 0 или мандат CAP_NET_ADMIN. В противном случае будет возвращено значение EPERM.
SIOCGIFNAME
Возвращает в ifr_name имя интерфейса для заданного индекса ifr_ifindex. Это единственный вызов ioctl, возвращающий результат в ifr_name.
SIOCGIFINDEX
Возвращает индекс интерфейса в ifr_ifindex.
SIOCGIFFLAGS, SIOCSIFFLAGS
Считывает или устанавливает слово флагов устройства. В ifr_flags содержится битовая маска из следующих значений:
Флаги устройства
IFF_UPИнтерфейс активен.
IFF_BROADCASTУстановлен правильный широковещательный адрес.
IFF_DEBUGФлаг внутренней отладки.
IFF_LOOPBACKИнтерфейс является устройством обратной петли.
IFF_POINTOPOINTИнтерфейс является соединением точка-точка.
IFF_RUNNINGРесурсы выделены.
IFF_NOARP Нет протокола arp, адрес назначения 2-ого уровня (L2) не установлен.
IFF_PROMISCИнтерфейс в режиме захвата (promiscuous).
IFF_NOTRAILERSИзбегать использования концевиков (trailers).
IFF_ALLMULTIПринимать все многоадресные пакеты.
IFF_MASTERМастер в связке балансирования нагрузки.
IFF_SLAVEПодчинённый в связке балансирования нагрузки.
IFF_MULTICASTПоддержка многоадресной передачи.
IFF_PORTSELМожет выбирать тип среды с помощью ifmap.
IFF_AUTOMEDIAЗапущен автоматический выбор среды.
IFF_DYNAMIC Адреса теряются, если интерфейс становится неактивным.
IFF_LOWER_UPДрайвер L1 указывает на включение интерфейса (начиная с Linux 2.6.17)
IFF_DORMANTДрайвер L1 указывает на неактивность интерфейса (начиная с Linux 2.6.17)
IFF_ECHOПосылать пакеты echo (начиная с Linux 2.6.25)

Установка флага в слове флагов является привилегированной операцией, но считывать его может любой процесс.
SIOCGIFPFLAGS, SIOCSIFPFLAGS
Считает или устанавливает (индивидуальные) флаги устройства. Значение ifr_flags представляет собой битовую маску следующих значений:
Индивидуальные флаги
IFF_802_1Q_VLANИнтерфейс является устройством 802.1Q VLAN.
IFF_EBRIDGEИнтерфейс является устройством моста Ethernet.
IFF_SLAVE_INACTIVEИнтерфейс является неактивным подчинённым в связке балансирования нагрузки.
IFF_MASTER_8023ADИнтерфейс является мастером в связке балансирования нагрузки 802.3ad.
IFF_MASTER_ALBИнтерфейс является мастером связки балансирования нагрузки в режиме balanced-alb.
IFF_BONDINGИнтерфейс является мастером или подчинённым в связке балансирования нагрузки.
IFF_SLAVE_NEEDARPИнтерфейсу требуется ARP для проверки.
IFF_ISATAPИнтерфейс является интерфейсом RFC4214 ISATAP.

Установка расширенных (индивидуальных) флагов интерфейса является привилегированной операцией.

SIOCGIFADDR, SIOCSIFADDR
Назначает или получает адрес устройства с помощью ifr_addr. Назначение адреса интерфейса является привилегированной операцией. Для совместимости, принимаются или возвращаются только адреса семейства AF_INET.
SIOCGIFDSTADDR, SIOCSIFDSTADDR
Назначает или получает адрес назначения устройства точка-точка с помощью ifr_dstaddr. Для совместимости, принимаются или возвращаются только адреса семейства AF_INET. Присвоение адреса назначения является привилегированной операцией.
SIOCGIFBRDADDR, SIOCSIFBRDADDR
Назначает или получает широковещательный адрес устройства с помощью ifr_brdaddr. Для совместимости, принимаются или возвращаются только адреса семейства AF_INET. Присвоение широковещательного адреса является привилегированной операцией.
SIOCGIFNETMASK, SIOCSIFNETMASK
Назначает или получает маску сети устройства с помощью ifr_netmask. Для совместимости, принимаются или возвращаются только адреса семейства AF_INET. Назначение маски сети адреса является привилегированной операцией.
SIOCGIFMETRIC, SIOCSIFMETRIC
Считывает или устанавливает метрику устройства с помощью ifr_metric. В данный момент возможность не реализована; при считывании ifr_metric присваивается значение, равное нулю, а при попытке установки возвращается значение EOPNOTSUPP.
SIOCGIFMTU, SIOCSIFMTU
Считывает или устанавливает MTU (Maximum Transfer Unit — максимальную порцию данных) с помощью ifr_mtu. Установка MTU является привилегированной операцией. Установка слишком маленьких значений может привести к авариям в ядре.
SIOCGIFHWADDR, SIOCSIFHWADDR
Считывает или устанавливает аппаратный адрес устройства с помощью ifr_hwaddr. Аппаратный адрес задаётся в структуре sockaddr. В sa_family содержится тип устройства ARPHRD_*, в sa_data содержится аппаратный адрес L2, начиная с байта 0. Установка аппаратного адреса является привилегированной операцией.
SIOCSIFHWBROADCAST
Устанавливает аппаратный широковещательный адрес устройства с помощью ifr_hwaddr. Это привилегированная операция.
SIOCGIFMAP, SIOCSIFMAP
Считывает или устанавливает аппаратные параметры интерфейса с помощью ifr_map. Установка параметров является привилегированной операцией.

struct ifmap {
    unsigned long   mem_start;
    unsigned long   mem_end;
    unsigned short  base_addr;
    unsigned char   irq;
    unsigned char   dma;
    unsigned char   port;
};

Назначение структуры ifmap зависит от драйвера устройства и архитектуры системы.

SIOCADDMULTI, SIOCDELMULTI
Добавляет или удаляет адрес из фильтров многоадресной передачи уровня связи устройства с помощью ifr_hwaddr. Это привилегированная операция. Альтернативный способ приведен в packet(7).
SIOCGIFTXQLEN, SIOCSIFTXQLEN
Считывает или устанавливает размер очереди передачи устройства с помощью ifr_qlen. Установка размера очереди передачи является привилегированной операцией.
SIOCSIFNAME
Изменяет имя интерфейса, указанное в ifr_name, на ifr_newname. Это привилегированная операция. Она разрешена только тогда, когда интерфейс не активен.
SIOCGIFCONF
Возвращает список адресов (транспортного уровня) интерфейсов. В настоящее время, сюда входят только адреса семейства AF_INET (IPv4), для совместимости. В отличии от других, данный ioctl передаёт структуру ifconf:

struct ifconf {
    int                 ifc_len; /* размер буфера */
    union {
        char           *ifc_buf; /* адрес буфера */
        struct ifreq   *ifc_req; /* массив структур */
    };
};

Если ifc_req равно NULL, то SIOCGIFCONF возвращает необходимый размер буфера в байтах для приёма всех доступных адресов в ifc_len. В противном случае ifc_req содержит указатель на массив структур ifreq, который будет заполнен адресами всех активных интерфейсов L3. В ifc_len содержится размер массива в байтах. Внутри каждой структуры ifreq в ifr_name будет записано имя интерфейса, а в ifr_addr — адрес. Реальное количество переданных байт возвращается в ifc_len.

Если размера, указанного в ifc_len, недостаточно для сохранения всех адресов, то ядро не запишет не поместившиеся и сообщит об успешном выполнении. Не существует надёжного способа обнаружения возникновения такой ситуации. Поэтому рекомендуется или сначала определить необходимый размер буфера вызовом SIOCGIFCONF с значением ifc_req равным NULL, или повторить вызов с большим буфером и проверить не отличается ли ifc_len на менее чем sizeof(struct ifreq) от первого значения.

Если произошла ошибка доступа к структуре ifconf или ifreq, то возвращается EFAULT.

Большинство протоколов поддерживают свои собственные вызовы ioctl для настройки предназначенных только для протокола параметров интерфейса. Подробности приведены в справочных страницах протоколов. Настройка адресов IP описывается в ip(7).

В дополнение ко всему, некоторые устройства поддерживают индивидуальные (private) вызовы ioctl. Здесь они не описаны.

ЗАМЕЧАНИЯ

Строго говоря, SIOCGIFCONF и другие вызовы ioctl, которые принимают или возвращают только адреса сокетов AF_INET, работают только с IP и принадлежат ip(7).

Имена интерфейсов, не имеющих адресов или установленного флага IFF_RUNNING, можно определить с помощью /proc/net/dev.

Локальные IP-адреса IPv6 можно найти в /proc/net или по rtnetlink(7).

ДЕФЕКТЫ

В glibc 2.1 отсутствует макрос ifr_newname в файле <net/if.h>. Добавьте следующие строки в вашу программу (чтобы обойти это):

#ifndef ifr_newname
#define ifr_newname     ifr_ifru.ifru_slave
#endif