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

ЖАНРЫ

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

const int on = 1;

setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVRTHDR, &on, sizeof(on));

На рис. 27.8 показан формат объекта вспомогательных данных, используемый для отправки и получения заголовка маршрутизации. Для создания и обработки заголовка маршрутизации определены шесть функций. Следующие три функции используются для создания отправляемого параметра.

#include <netinet/in.h>

socklen_t inet6_rth_space(int type, int segments);

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

void *inet6_rth_init(void * rthbuf, socklen_t rthlen, int type, int segments);

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

int inet6_rth_add(void * rthbuf, const struct in6_addr * addr);

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

Рис. 27.8. Объект вспомогательных данных для заголовка маршрутизации IPv6

Функция

inet6_rth_space
возвращает количество байтов, необходимое для размещения объекта вспомогательных данных, содержащего заголовок маршрутизации указанного типа (обычно это
IPV6_RTHDR_TYPE_0
) с заданным количеством сегментов.

Функция

inet6_rth_init
инициализирует буфер, на который указывает аргумент
rthbuf
, для помещения заголовка маршрутизации типа type и заданного количества сегментов. Возвращаемое значение этой функции — указатель на буфер. Этот указатель используется как аргумент при вызове следующей функции. Функция
inet6_rth_init
возвращает
NULL
в случае возникновения ошибок (например, при недостаточном размере предоставленного буфера).

Функция

inet6_rth_add
добавляет адрес IPv6, на который указывает аргумент
addr
, к концу составляемого заголовка маршрутизации. В случае успешного выполнения обновляется значение элемента
segleft
заголовка маршрутизации, чтобы учесть добавленный новый адрес.

Следующие три функции манипулируют полученным заголовком маршрутизации:

#include <netinet/in.h>

int inet6_rth_reverse(const void * in, void * out);

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

int inet6_rth_segments(const void * rthbuf);

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

struct in6_addr *inet6_rth_getaddr(const void * rthbuf, int index);

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

Функция

inet6_rth_reverse
принимает в качестве аргумента заголовок маршрутизации, полученный в виде объекта вспомогательных данных (на который указывает аргумент
in
), и создает новый заголовок маршрутизации (в буфере, на который указывает аргумент
out
), отправляющий дейтаграммы по обратному маршруту. Указатели in и out могут указывать на один и тот же буфер.

Функция

inet6_rth_segments
возвращает количество сегментов в заголовке маршрутизации, на который указывает
rthbuf
. В случае успешного выполнения функции возвращаемое значение оказывается больше 0.

Функция

inet6_rth_getaddr
возвращает указатель на адрес IPv6, заданный через
index
в заголовке маршрутизации
rthbuf
. Аргумент
index
должен лежать в пределах от 1 до значения, возвращенного функцией
inet6_rth_segments
, включительно.

Чтобы продемонстрировать использование этих параметров, мы создали UDP-клиент и UDP-сервер. Клиент представлен в листинге 27.5. Он принимает маршрут от отправителя в командной строке подобно TCP-клиенту IPv4, представленному в листинге 27.4. Сервер печатает маршрут полученного сообщения и обращает этот маршрут для отправки сообщения в обратном направлении.

Листинг 27.5. UDP-клиент, использующий маршрутизацию от отправителя

1 #include "unp.h"

2 int

3 main(int argc, char **argv)

4 {

5 int с, sockfd, len = 0;

6 u_char *ptr = NULL;

7 void *rth;

8 struct addrinfo *ai;

9 if (argc < 2)

10 err_quit("usage: udpcli01 [ <hostname> ... ] <hostname>");

11 if (argc > 2) {

12 int i;

13 len = Inet6_rth_space(IPV6_RTHDR_TYPE_0, argc-2);

14 ptr = Malloc(len);

15 Inet6_rth_init(ptr, len, IPV6_RTHDR_TYPE_0, argc-2);

16 for (i = 1; i < argc-1; i++) {

17 ai = Host_serv(argv[i], NULL, AF_INET6, 0);

18 Inet6_rth_add(ptr,

19 &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);

20 }

21 }

22 ai = Host_serv(argv[argc-1], SERV_PORT_STR, AF_INET6, SOCK_DGRAM);

23 sockfd = Socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

24 if (ptr) {

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