getifaddrs(3)

ИМЯ
getifaddrs, freeifaddrs - возвращают адреса интерфейса

LIBRARY
Standard C library (libc, -lc)

СИНТАКСИС
#include <sys/types.h>
#include <ifaddrs.h>

int getifaddrs(struct ifaddrs **ifap);
void freeifaddrs(struct ifaddrs *ifa);

ОПИСАНИЕ
Функция getifaddrs() создаёт связный список структур, описывающих сетевые интерфейсы локальной системы, и сохраняет адрес первого элемента списка в *ifap. Список состоит из структур ifaddrs:

    struct ifaddrs {
        struct ifaddrs  *ifa_next;    /* след. элемент в списке */
        char            *ifa_name;    /* имя интерфейса */
        unsigned int     ifa_flags;   /* флаги из SIOCGIFFLAGS */
        struct sockaddr *ifa_addr;    /* адрес интерфейса */
        struct sockaddr *ifa_netmask; /* сетевая маска интерфейса */
        union {
            struct sockaddr *ifu_broadaddr;
                             /* широковещательный адрес интерфейса */
            struct sockaddr *ifu_dstaddr;
                             /* адрес назначения точка-точка */
        } ifa_ifu;
    #define              ifa_broadaddr ifa_ifu.ifu_broadaddr
    #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
        void            *ifa_data;    /* спец. данные для адреса */
    };

В поле ifa_next содержится указатель на следующую структуру в списке или NULL, если это последний элемент в списке.

Поле ifa_name указывает на имя интерфейса (заканчивающееся null).

В поле ifa_flags содержатся флаги интерфейса, полученные операцией SIOCGIFFLAGS ioctl(2) (список флагов приведён в netdevice(7)).

Поле ifa_addr указывает на структуру, содержащую адрес интерфейса (для определения формата структуры адреса обратитесь к подполю sa_family). Это поле может содержать указатель null.

Поле ifa_netmask указывает на структуру, содержащую маску сети для ifa_addr (если она используется в адресном семействе). Это поле может содержать указатель null.

В зависимости от наличия флага IFF_BROADCAST или IFF_POINTOPOINT в ifa_flags (может быть установлен какой-то один), в ifa_broadaddr будет содержаться широковещательный адрес ifa_addr (если он используется в адресном семействе) или ifa_dstaddr будет содержать адрес назначения интерфейса типа точка-точка.

Поле ifa_data указывает на буфер, содержащий данные, присущие адресному семейству; это поле может быть равно NULL, если данных для этого интерфейса нет.

Память под структуру данных, возвращаемая getifaddrs(), выделяется динамически и должна освобождаться с помощью freeifaddrs(), когда больше не нужна.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
On success, getifaddrs() returns zero; on error, -1 is returned, and errno is set to indicate the error.

ОШИБКИ
Функция getifaddrs() может завершиться с ошибками и назначить переменной errno значения, перечисленные в socket(2), bind(2), getsockname(2), recvmsg(2), sendto(2), malloc(3) или realloc(3).

ВЕРСИИ
Впервые функция getifaddrs() появилась в glibc 2.3, но до glibc 2.3.3 реализация поддерживала только интерфейсы с адресами IPv4; поддержка IPv6 добавлена в glibc 2.3.3. Поддержка семейств адресов не IPv4 доступна только в ядрах, поддерживающих netlink.

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
getifaddrs(), freeifaddrs() | Безвредность в нитях | MT-Safe

СТАНДАРТЫ
Not in POSIX.1. This function first appeared in BSDi and is present on the BSD systems, but with slightly different semantics documented—returning one entry per interface, not per address. This means ifa_addr and other fields can actually be NULL if the interface has no address, and no link-level address is returned if the interface has an IP address assigned. Also, the way of choosing either ifa_broadaddr or ifa_dstaddr differs on various systems.

ЗАМЕЧАНИЯ
Адреса, возвращаемые в Linux, обычно, являются адресами IPv4 и IPv6, назначенными интерфейсу, но также есть один адрес AF_PACKET на интерфейс, содержащий канальные настройки интерфейса и его физический уровень. В этом случае поле ifa_data может содержать указатель на struct rtnl_link_stats, определённую в <linux/if_link.h> (в Linux 2.4 и ранее — struct net_device_stats, определена в <linux/netdevice.h>), которая содержит различные атрибуты интерфейса и статистику.

ПРИМЕРЫ
В программе, показанной далее, демонстрируется использование getifaddrs(), freeifaddrs(), и getnameinfo(3). Вот результат запуска этой программы:

    $ ./a.out
    lo       AF_PACKET (17)
                    tx_packets =        524; rx_packets =        524
                    tx_bytes   =      38788; rx_bytes   =      38788
    wlp3s0   AF_PACKET (17)
                    tx_packets =     108391; rx_packets =     130245
                    tx_bytes   =   30420659; rx_bytes   =   94230014
    em1      AF_PACKET (17)
                    tx_packets =          0; rx_packets =          0
                    tx_bytes   =          0; rx_bytes   =          0
    lo       AF_INET (2)
                    адрес: <127.0.0.1>
    wlp3s0   AF_INET (2)
                    адрес: <192.168.235.137>
    lo       AF_INET6 (10)
                    адрес: <::1>
    wlp3s0   AF_INET6 (10)
                    адрес: <fe80::7ee9:d3ff:fef5:1a91%wlp3s0>

  Исходный код программы
    #define _GNU_SOURCE     /* чтобы получить NI_MAXSERV и NI_MAXHOST */
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <ifaddrs.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <linux/if_link.h>
    int main(int argc, char *argv[])
    {
        struct ifaddrs *ifaddr;
        int family, s;
        char host[NI_MAXHOST];
        if (getifaddrs(&ifaddr) == -1) {
            perror("getifaddrs");
            exit(EXIT_FAILURE);
        }
        /* Walk through linked list, maintaining head pointer so we
           can free list later. */
        for (struct ifaddrs *ifa = ifaddr; ifa != NULL;
                 ifa = ifa->ifa_next) {
            if (ifa->ifa_addr == NULL)
                continue;
            family = ifa->ifa_addr->sa_family;
            /* Display interface name and family (including symbolic
               form of the latter for the common families). */
            printf("%-8s %s (%d)\n",
                   ifa->ifa_name,
                   (family == AF_PACKET) ? "AF_PACKET" :
                   (family == AF_INET) ? "AF_INET" :
                   (family == AF_INET6) ? "AF_INET6" : "???",
                   family);
            /* For an AF_INET* interface address, display the address. */
            if (family == AF_INET || family == AF_INET6) {
                s = getnameinfo(ifa->ifa_addr,
                        (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                              sizeof(struct sockaddr_in6),
                        host, NI_MAXHOST,
                        NULL, 0, NI_NUMERICHOST);
                if (s != 0) {
                    printf("ошибка getnameinfo(): %s\n", gai_strerror(s));
                    exit(EXIT_FAILURE);
                }
                printf("\t\tадрес: <%s>\n", host);
            } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
                struct rtnl_link_stats *stats = ifa->ifa_data;
                printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
                       "\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",
                       stats->tx_packets, stats->rx_packets,
                       stats->tx_bytes, stats->rx_bytes);
            }
        }
        freeifaddrs(ifaddr);
        exit(EXIT_SUCCESS);
    }

СМ. ТАКЖЕ
bind(2), getsockname(2), socket(2), packet(7), ifconfig(8)

ПЕРЕВОД
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 (https://www.gnu.org/licenses/gpl-3.0.html) или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.