UNIX: разработка сетевых приложений
Исходящий и входящий интерфейсы
Интерфейсы на узле IPv6 идентифицируются небольшими целыми положительными числами, как мы сказали в разделе 18.6. Вспомните, что ни одному интерфейсу не может быть присвоен нулевой индекс. При задании исходящего интерфейса ядро само выберет исходящий интерфейс, если значение
нулевое. Если приложение задает исходящий интерфейс для пакета многоадресной передачи, то любой интерфейс, заданный параметром сокетаipi6_ifindex, заменяется на интерфейс, заданный вспомогательными данными (но только для данной дейтаграммы).IPV6_MULTICAST_IFАдрес отправителя и адрес получателя IPv6
IPv6-адрес отправителя обычно определяется при помощи функции
. Но если адрес отправителя поставляется вместе с данными, это может снизить непроизводительные затраты. Этот параметр также позволяет серверу гарантировать, что адрес отправителя ответа совпадает с адресом получателя клиентского запроса — некоторым клиентам требуется такое условие, которое сложно выполнить в случае IPv4 (см. упражнение 22.4).bindКогда IPv6-адрес отправителя задан в качестве вспомогательных данных и элемент
структурыipi6_addrимеет значениеin6_pktinfo, возможны следующие сценарии: если адрес в настоящий момент связан с сокетом, он используется в качестве адреса отправителя; если в настоящий момент никакой адрес не связан с сокетом, ядро выбирает адрес отправителя. Если же элементIN6ADDR_ANY_INITне является неопределенным адресом, но сокет уже связался с адресом отправителя, то значением элементаipi6_addrперекрывается уже связанный адрес, но только для данной операции вывода. Затем ядро проверяет, действительно ли запрашиваемый адрес отправителя является адресом направленной передачи, присвоенным узлу.ipi6_addrКогда структура in6_
возвращается в качестве вспомогательных данных функциейpktinfo, элементrecvmsgсодержит IPv6-адрес получателя из полученного пакета. По сути, это аналог параметра сокетаipi6_addrдля IPv4.IP_RECVDSTADDRЗадание и получение предельного количества транзитных узлов
Предельное количество транзитных узлов обычно задается параметром сокета
для дейтаграмм направленной передачи (см. раздел 7.8) или параметром сокетаIPV6_UNICAST_HOPSдля дейтаграмм многоадресной передачи (см. раздел 21.6). Задавая предельное количество транзитных узлов в составе вспомогательных данных, мы можем заменить как значение этого предела, задаваемое ядром по умолчанию, так и ранее заданное значение — и для направленной, и для многоадресной передачи, но только для одной операции вывода. Предел количества транзитных узлов полученного пакета используется в таких программах, какIPV6_MULTICAST_HOPS, и в некоторых приложениях IPv6, которым нужно проверять, что полученное значение равно 255 (то есть что пакет не пересылался маршрутизаторами).tracerouteПолученное предельное количество транзитных узлов возвращается в виде вспомогательных данных функцией
, только если приложение включает параметр сокетаrecvmsg. В структуреIPV6_RECVHOPLIMIT, содержащей эти вспомогательные данные, элементcmsghdrбудет иметь значениеcmsg_level, элементIPPROTO_IPV6— значениеcmsg_type, а первый байт данных будет первым байтом целочисленного предела повторных передач. Мы показали это на рис. 22.5. Нужно понимать, что значение, возвращаемое в качестве вспомогательных данных, — это действительное значение из полученной дейтаграммы, в то время как значение, возвращаемое функциейIPV6_HOPLIMITс параметромgetsockopt, является значением по умолчанию, которое ядро будет использовать для исходящих дейтаграмм на сокете.IPV6_UNICAST_HOPSЧтобы задать предельное количество транзитных узлов для исходящих пакетов, никаких специальных действий не требуется — нам нужно только указать управляющую информацию в виде вспомогательных данных для функции
. Обычные значения для предельного количества транзитных узлов лежат в диапазоне от 0 до 255 включительно, но если целочисленное значение равно -1, это указывает ядру, что следует использовать значение по умолчанию.sendmsgПРИМЕЧАНИЕПредельное количество транзитных узлов не содержится в структуре in6_pktinfo — некоторые серверы UDP хотят отвечать на запросы клиентов, посылая ответы на том же интерфейсе, на котором был получен запрос, с совпадением IPv6-адреса отправителя ответа и IPv6-адреса получателя запроса. Для этого приложение может включить параметр сокета IPV6_RECVPKTINFO, а затем использовать полученную управляющую информацию из функции recvmsg в качестве управляющей информации для функции sendmsg при отправке ответа. Приложению вообще никак не нужно проверять или изменять структуру in6_pktinfo. Но если в этой структуре содержался бы предел количества транзитных узлов, приложение должно было бы проанализировать полученную управляющую информацию и изменить значение этого предела, поскольку полученный предел не является желательным значением для исходящего пакета.
Задание адреса следующего транзитного узла
Объект вспомогательных данных
задает адрес следующего транзитного узла дейтаграммы в виде структуры адреса сокета. В структуреIPV6_NEXTHOP, содержащей эти вспомогательные данные, элементcmsghdrбудет иметь значениеcmsg_level, элементIPPROTO_IPV6— значениеcmsg_type, а первый байт данных будет первым байтом структуры адреса сокета.IPV6_NEXTHOPНа рис. 22.5 мы показали пример такого объекта вспомогательных данных, считая, что структура адреса сокета — это 24-байтовая структура
. В этом случае узел, идентифицируемый данным адресом, должен быть соседним для отправляющего узла. Если этот адрес совпадает с адресом получателя IPv6-дейтаграммы, мы получаем эквивалент параметра сокетаsockaddr_in6. Установка этого параметра требует прав привилегированного пользователя. Адрес следующего транзитного узла можно устанавливать для всех пакетов на сокете, если включить параметр сокетаSO_DONTROUTEсо значениемIPV6_NEXTHOP(раздел 27.7). Для этого необходимо обладать правами привилегированного пользователя.sockaddr_in6Задание и получение класса трафика
Объект вспомогательных данных
задает класс трафика для дейтаграммы. ЭлементIPV6_TCLASSструктурыcmsg_level, содержащей эти данные, будет равенcmsghdr, элементIPPROTO_IPV6будет равенcmsg_type, а первый байт данных будет первым байтом целочисленного (4-байтового) значения класса трафика (см. рис. 22.5). Согласно разделу А.3, класс трафика состоит из полейIPV6_TCLASSиDSCP. Эти поля должны устанавливаться одновременно. Ядро может маскировать или игнорировать указанное пользователем значение, если ему это нужно (например, если ядро реализуетECN, оно может установить битыECNравными какому-либо значению, игнорируя два бита, указанных с параметромECN). Класс трафика обычно лежит в диапазоне 0–255. Значение -1 говорит ядру о необходимости использовать значение по умолчанию.IPV6_TCLASS