int ipi6_ifindex; /* индекс интерфейса для исходящей/получаемой дейтаграммы */
};
Эта структура определяется в заголовочном файле
, подключение которого позволяет ее использовать. В структуре cmsghdr
, содержащей вспомогательные данные, элемент cmsg_level
будет иметь значение IPPROTO_IPV6
, элемент cmsg_type
будет равен IPV6_PKTINFO
и первый байт данных будет первым байтом структуры in6_pktinfo
. В примере, приведенном на рис. 22.5, мы считаем, что между структурой cmsghdr
и данными нет заполнения и целое число занимает 4 байта.
Чтобы отправить эту информацию, никаких специальных действий не требуется — нужно только задать управляющую информацию во вспомогательных данных функции sendmsg
. Чтобы информация добавлялась ко всем отправляемым через сокет пакетам, необходимо установить параметр сокета IPV6_PKTINFO
со значением in6_pktinfo
. Возвращать эту информацию функция recvmsg
будет, только если приложение включит параметр сокета IPV6_RECVPKTINFO
.
Исходящий и входящий интерфейсы
Интерфейсы на узле IPv6 идентифицируются небольшими целыми положительными числами, как мы сказали в разделе 18.6. Вспомните, что ни одному интерфейсу не может быть присвоен нулевой индекс. При задании исходящего интерфейса ядро само выберет исходящий интерфейс, если значение ipi6_ifindex
нулевое. Если приложение задает исходящий интерфейс для пакета многоадресной передачи, то любой интерфейс, заданный параметром сокета IPV6_MULTICAST_IF
, заменяется на интерфейс, заданный вспомогательными данными (но только для данной дейтаграммы).
Адрес отправителя и адрес получателя IPv6
IPv6-адрес отправителя обычно определяется при помощи функции bind
. Но если адрес отправителя поставляется вместе с данными, это может снизить непроизводительные затраты. Этот параметр также позволяет серверу гарантировать, что адрес отправителя ответа совпадает с адресом получателя клиентского запроса — некоторым клиентам требуется такое условие, которое сложно выполнить в случае IPv4 (см. упражнение 22.4).
Когда IPv6-адрес отправителя задан в качестве вспомогательных данных и элемент ipi6_addr
структуры in6_pktinfo
имеет значение IN6ADDR_ANY_INIT
, возможны следующие сценарии: если адрес в настоящий момент связан с сокетом, он используется в качестве адреса отправителя; если в настоящий момент никакой адрес не связан с сокетом, ядро выбирает адрес отправителя. Если же элемент ipi6_addr
не является неопределенным адресом, но сокет уже связался с адресом отправителя, то значением элемента ipi6_addr
перекрывается уже связанный адрес, но только для данной операции вывода. Затем ядро проверяет, действительно ли запрашиваемый адрес отправителя является адресом направленной передачи, присвоенным узлу.
Когда структура in6_pktinfo
возвращается в качестве вспомогательных данных функцией recvmsg
, элемент ipi6_addr
содержит IPv6-адрес получателя из полученного пакета. По сути, это аналог параметра сокета IP_RECVDSTADDR
для IPv4.
Задание и получение предельного количества транзитных узлов
Предельное количество транзитных узлов обычно задается параметром сокета IPV6_UNICAST_HOPS
для дейтаграмм направленной передачи (см. раздел 7.8) или параметром сокета IPV6_MULTICAST_HOPS
для дейтаграмм многоадресной передачи (см. раздел 21.6). Задавая предельное количество транзитных узлов в составе вспомогательных данных, мы можем заменить как значение этого предела, задаваемое ядром по умолчанию, так и ранее заданное значение — и для направленной, и для многоадресной передачи, но только для одной операции вывода. Предел количества транзитных узлов полученного пакета используется в таких программах, как traceroute
, и в некоторых приложениях IPv6, которым нужно проверять, что полученное значение равно 255 (то есть что пакет не пересылался маршрутизаторами).