Литмир - Электронная Библиотека
ЛитМир: бестселлеры месяца
Содержание  
A
A

В листинге 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,

31    &((const struct sockaddr_in*)grp)->sin_addr,

32    sizeof(struct in_addr));

33    if (ifindex > 0) {

34     if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) {

35      errno = ENXIO; /* i/f index not found */

36      return(-1);

37     }

38     goto doioctl;

39    } else if (ifname != NULL) {

40     strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);

41 doioctl:

42     if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0)

43      return(-1);

44     memcpy(&mreq.imr_interface,

45      &((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr,

46      sizeof(struct in_addr));

47    } else

48     mreq.imr_interface.s_addr = htonl(INADDR_ANY);

49    return(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,

50     &mreq, sizeof(mreq)));

51   }

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

33-38
 Адрес многоадресной передачи IPv4 в структуре адреса сокета копируется в структуру
ip_mreq
. Если индекс был задан, вызывается функция
if_indextoname
, сохраняющая имя в нашей структуре
ip_mreq
. Если это выполняется успешно, мы переходим на точку вызова
ioctl
.

Обработка имени

39-46
 Имя вызывающего процесса копируется в структуру
ip_mreq
, а вызов
SIOCGIFADDR
функции
ioctl
возвращает адрес многоадресной передачи, связанный с этим именем. При успешном выполнении адрес IPv4 копируется в элемент
imr_interface
структуры
ip_mreq
.

Значения по умолчанию

47-48
 Если ни индекс, ни имя не заданы, используется универсальный адрес, что указывает ядру на необходимость выбрать интерфейс.

49-50
 Функция
setsockopt
выполняет присоединение к группе.

Третья, и последняя, часть функции, обрабатывающая сокеты IPv6, приведена в листинге 21.3.

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

52 #ifdef IPV6

53  case AF_INET6: {

54   struct ipv6_mreq mreq6;

55   memcpy(&mreq6.ipv6mr_multiaddr,

56    &((const struct sockaddr_in6*) grp)->sin6_addr,

57    sizeof(struct in6_addr));

58    if (ifindex > 0) {

59     mreq6.ipv6mr_interface = ifindex;

60    } else if (ifname != NULL) {

61     if ((mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) {

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

63      return(-1);

64     }

65    } else

66     mreq6.ipv6mr_interface = 0;

67    return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,

68     &mreq6, sizeof(mreq6)));

69   }

70 #endif

71  default:

72   errno = EAFNOSUPPORT;

73   return(-1);

74  }

75 #endif

76 }

Копирование адреса

55-57
 Сначала адрес IPv6 копируется из структуры адреса сокета в структуру
ipv6_mreq
.

Обработка индекса или имени интерфейса или выбор интерфейса по умолчанию

58-66
 Если был задан индекс, он записывается в элемент
ipv6mr_interface
. Если индекс не задан, но задано имя, то для получения индекса вызывается функция
if_nametoindex
. В противном случае для функции
setsockopt
индекс устанавливается в 0, что указывает ядру на необходимость выбрать интерфейс.

67-68
 Выполняется присоединение к группе.

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

В листинге 21.4 показана наша функция

mcast_set_loop
.

Поскольку аргументом является дескриптор сокета, а не структура адреса сокета, мы вызываем нашу функцию

sockfd_to_family
, чтобы получить семейство адресов сокета. Устанавливается соответствующий параметр сокета.

Мы не показываем исходный код для всех остальных функций

mcast_<i>XXX</i>
, так как он свободно доступен в Интернете (см. предисловие).

Листинг 21.4. Установка параметра закольцовки для многоадресной передачи

//lib/mcast_set_loop.c

 1 #include &quot;unp.h&quot;

 2 int

 3 mcast_set_loop(int sockfd, int onoff)

235
{"b":"225366","o":1}
ЛитМир: бестселлеры месяца