Шрифт:
Заполнение структуры msghdr и вызов функции recvmsg
23-33
Заполняется структура msghdr
и вызывается функция recvmsg
. Значения элементов msg_namelen
и msg_flags
должны быть переданы обратно вызывающему процессу. Они являются аргументами типа «значение-результат». Мы также инициализируем структуру вызывающего процесса unp_in_pktinfo
, устанавливая IP-адрес 0.0.0.0 и индекс интерфейса 0. В листинге 22.2 показана вторая часть нашей функции.
Листинг 22.2. Функция recvfrom_flags: возвращаемые флаги и адрес получателя
//advio/recvfromflags.c
34 #ifndef HAVE_MSGHDR_MSG_CONTROL
35 *flagsp = 0; /* возвращение результатов */
36 return(n);
37 #else
38 *flagsp = msg.msg_flags; /* возвращение результатов */
39 if (msg.msg_controllen < sizeof(struct cmsghdr) ||
40 (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
41 return(n);
42 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
43 cmptr = CMSG_NXTHDR(&msg, cmptr)) {
44 #ifdef IP_RECVDSTADDR
45 if (cmptr->cmsg_level == IPPROTO_IP &&
46 cmptr->cmsg_type == IP_RECVDSTADDR) {
47 memcpy(&pktp->ipi_addr, CMSG_DATA(cmptr),
48 sizeof(struct in_addr));
49 continue;
50 }
51 #endif
52 #ifdef IP_RECVIF
53 if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF) {
54 struct sockaddr_dl *sdl;
55 sdl = (struct sockaddr_dl*)CMSG_DATA(cmptr);
56 pktp->ipi_ifindex = sdl->sdl_index;
57 continue;
58 }
59 #endif
60 err_quit("unknown ancillary data, len = %d,
level = %d, type = %d",
61 cmptr->cmsg_len, cmptr->cmsg_level, cmptr->cmsg_type);
62 }
63 return(n);
64 #endif /* HAVE_MSGHDR_MSG_CONTROL */
65 }
34-37
Если реализация не поддерживает элемента msg_control
, мы просто обнуляем возвращаемые флаги и завершаем функцию. Оставшаяся часть функции обрабатывает информацию, содержащуюся в структуре msg_control
. Возвращение при отсутствии управляющей информации
38-41
Мы возвращаем значение msg_flags
и передаем управление вызывающей функции в том случае, если нет никакой управляющей информации, управляющая информация была обрезана или вызывающий процесс не требует возвращения структуры unp_in_pktinfo
. Обработка вспомогательных данных
42-43
Мы обрабатываем произвольное количество объектов вспомогательных данных с помощью макросов CMSG_FIRSTHDR
и CMSG_NEXTHDR
. Обработка параметра сокета IP_RECVDSTADDR
47-54
Если в составе управляющей информации был возвращен IP-адрес получателя (см. рис. 14.2), он возвращается вызывающему процессу. Обработка параметра сокета IP_RECVIF
55-63
Если в составе управляющей информации был возвращен индекс интерфейса, он возвращается вызывающему процессу. На рис. 22.1 показано содержимое возвращенного объекта вспомогательных данных.