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

ЖАНРЫ

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

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_ XXX
, так как он свободно доступен в Интернете (см. предисловие).

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

//lib/mcast_set_loop.c

1 #include "unp.h"

2 int

3 mcast_set_loop(int sockfd, int onoff)

4 {

5 switch (sockfd_to_family(sockfd)) {

6 case AF_INET:{

7 u_char flag;

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