getifaddrs, freeifaddrs -
возвращают
адреса
интерфейса
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 <
[email protected]>, Dmitry Bolkhovskikh
<
[email protected]>, Vladislav <
[email protected]>,
Yuri Kozlov <
[email protected]> и
Иван
Павлов <
[email protected]>
Этот
перевод
является
бесплатной
документацией;
прочитайте
Стандартную
общественную
лицензию GNU
версии 3
или более
позднюю,
чтобы
узнать об
условиях
авторского
права. Мы не
несем
НИКАКОЙ
ОТВЕТСТВЕННОСТИ.
Если вы
обнаружите
ошибки в
переводе
этой
страницы
руководства,
пожалуйста,
отправьте
электронное
письмо на
[email protected]