Чтение онлайн

ЖАНРЫ

UNIX: разработка сетевых приложений
Шрифт:

Возвращает: текущий флаг закольцовки в случае успешного выполнения, -1 в случае ошибки

int mcast_get_ttl(int sockfd);

Возвращает: текущее значение TTL или предельное количество транзитных узлов в случае успешного выполнения, -1 в случае ошибки

Функция

mcast_join
присоединяет узел к группе. IP-адрес этой группы содержится в структуре адреса сокета, на которую указывает аргумент
grp
, а длина этой структуры задается аргументом
grplen
. Мы можем задать интерфейс, на котором должно происходить присоединение к группе, либо через имя интерфейса (непустой аргумент
ifname
), либо
через ненулевой индекс интерфейса (непустой аргумент
ifindex
). Если ни одно из этих значений не задано, ядро самостоятельно выбирает интерфейс, на котором происходит присоединение к группе. Вспомните, что в случае IPv6 для работы с параметрами сокета интерфейс задается по его индексу. Если для сокета IPv6 известно имя интерфейса, нужно вызвать функцию
if_nametoindex
, чтобы получить индекс интерфейса. В случае параметра сокета IPv4 мы задаем интерфейс по его IP-адресу направленной передачи. Если для сокета IPv4 интерфейс задан по имени, нужно вызвать функцию
ioctl
с запросом
SIOCGIFADDR
для получения IP-адреса направленной передачи для этого интерфейса. Если для сокета IPv4 задан индекс интерфейса, мы сначала вызываем функцию
if_indextoname
, чтобы получить имя интерфейса, а затем обрабатываем имя так, как только что было сказано.

ПРИМЕЧАНИЕ

Пользователи обычно задают имя интерфейса le0 или ether0, а IP-адрес и индекс интерфейса не используются. Например, tcpdump является одной из немногих программ, позволяющих пользователю задавать интерфейс, а ее параметр -i принимает имя интерфейса в качестве аргумента.

Функция

mcast_leave
выводит узел из группы с IP-адресом, содержащимся в структуре адреса сокета, на которую указывает аргумент
grp
.

Функция

mcast_block_source
блокирует получение через конкретный сокет пакетов, относящихся к определенной группе и исходящих от определенного источника. IP-адреса группы и источника хранятся в структурах адреса сокета, на которые указывают аргументы
grp
и
src
соответственно. Длины структур задаются параметрами
srclen
и
grplen
. Для успешного завершения функции необходимо, чтобы до ее вызова уже была вызвана функция
mcast_join
для того же сокета и той же группы.

Функция

mcast_unblock_source
разблокирует получение трафика от источника из заданной группы. Аргументы
src
,
srclen
,
grp
и
grplen
имеют тот же смысл, что и аргументы предыдущей функции, и должны совпадать с ними по значениям.

Функция

mcast_join_source_group
выполняет присоединение к группе источника. Адрес источника и адрес группы содержатся в структурах адреса сокета, на которые указывают аргументы
src
и
grp
. Длины структур задаются параметрами
srclen
и
grplen
. Интерфейс, присоединяемый к группе, может быть задан именем (ненулевой аргумент
ifname
) или индексом (
ifindex
). Если интерфейс не задан явно, ядро выбирает его самостоятельно.

Функция

mcast_leave_source_group
выполняет отсоединение от группы источника. Адреса источника и группы содержатся в структурах адреса сокета, на которые указывают аргументы
src
и
grp
. Длины структур задаются параметрами
srclen
и
grplen
. Подобно
mcast_leave
,
mcast_leave_source_group
не требует указания интерфейса: она всегда отсоединяет от группы первый интерфейс, удовлетворяющий условиям.

Функция

mcast_set_if
устанавливает индекс интерфейса по умолчанию для исходящих дейтаграмм многоадресной передачи. Если аргумент
ifname
непустой, он задает имя интерфейса. Иначе положительное значение аргумента
ifindex
будет задавать индекс интерфейса. В случае IPv6 имя сопоставляется индексу с использованием функции
if_nametoindex
. В случае IPv4 сопоставление имени или индекса IP-адресу направленной передачи интерфейса происходит так же, как для функции
mcast_join
.

Функция

mcast_set_loop
устанавливает параметр закольцовки либо в 0, либо в 1, а функция
mcast_set_ttl
TTL
в случае IPv4 или предел количества транзитных узлов в случае IPv6. Функции
mcast_get_XXX
возвращают соответствующие значения.

Пример: функция mcast_join

В листинге 21.1 [1] показана первая часть функции

mcast_join
. Эта часть демонстрирует простоту интерфейса программирования, не зависящего от протокола.

1

Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.

Листинг 21.1. Присоединение к группе: сокет IPv4

//lib/mcast_join.c

1 #include "unp.h"

2 #include <net/if.h>

3 int

4 mcast_join(int sockfd, const SA *grp, socklen_t grplen,

5 const char *ifname, u_int ifindex)

6 {

7 #ifdef MCAST_JOIN_GROUP

8 struct group_req req;

9 if (ifindex > 0) {

10 req.gr_interface = ifindex;

11 } else if (ifname != NULL) {

12 if ((req.gr_interface = if_nametoindex(ifname)) == 0) {

13 errno = ENXIO; /* интерфейс не найден */

14 return(-1);

15 }

16 } else

17 req.gr_interface = 0;

18 if (grplen > sizeof(req.gr_group)) {

19 errno = EINVAL;

20 return -1;

21 }

22 memcpy(&req.gr_group, grp, grplen);

23 return (setsockopt(sockfd, family_to_level(grp->sa_family),

24 MCAST_JOIN_GROUP, &req, sizeof(req)));

25 #else

Обработка индекса

9-17
Если при вызове был указан индекс интерфейса, функция использует его непосредственно. В противном случае (при указании имени интерфейса), имя преобразуется в индекс вызовом
if_nametoindex
. Если ни имя, ни индекс не заданы, интерфейс выбирается ядром.

Копирование адреса и вызов setsockopt

18-22
Адрес сокета копируется непосредственно в поле группы. Вспомните, что поле это имеет тип
sockaddr_storage
, а потому достаточно велико для хранения адреса любого типа, поддерживаемого системой. Для предотвращения переполнения буфера (при ошибках в программе) мы проверяем размер
sockaddr
и возвращаем
EINVAL
, если он слишком велик.

23-24
Присоединение к группе выполняется вызовом
setsockopt
. Аргумент
level
определяется на основании семейства группового адреса вызовом нашей собственной функции
family_to_level
. Некоторые системы допускают несоответствие аргумента level семейству адреса сокета, например использование
IPPROTO_IP
с
MCAST_JOIN_GROUP
, даже если сокет относится к семейству
AF_INET6
, но это верно не для всех систем, поэтому мы и должны выполнить преобразование семейства к нужному значению
level
. Листинг этой тривиальной функции в книге мы не приводим, но исходный код этой функции вы можете скачать вместе со всеми остальными программами.

В листинге 21.2 представлена вторая часть функции

mcast_join
, обрабатывающая сокеты IPv4.

Листинг 21.2. Присоединение к группе: обработка сокета IPv4

26 switch (grp->sa_family) {

27 case AF_INET: {

28 struct ip_mreq mreq;

29 struct ifreq ifreq;

30 memcpy(&mreq.imr_multiaddr,

Поделиться с друзьями: