Два параметра заполнения (pad options) определены в RFC 2460 [27] и могут быть использованы как в заголовке параметров для транзитных узлов, так и в заголовке параметров получателя. Один из параметров транзитных узлов — параметр размера увеличенного поля данных( jumbo pay load length option) — определен в RFC 2675 [9]. Ядро генерирует этот параметр по мере необходимости и обрабатывает при получении. Новый параметр увеличенного объема данных для IPv6, аналогичный параметру извещения маршрутизатора( router alert), описан в RFC 2711 [87]. Эти параметры изображены на рис. 27.5. Есть и другие параметры (например, для Mobile-IPv6), но мы их на рисунке не показываем.
Рис. 27.5.
Параметры IPv6 для транзитных узлов
Параметр
pad1
— это единственный параметр, для которого не указывается длина и значение. Его назначение — вставка одного пустого байта для заполнения. Параметр
padN
используется, когда требуется вставить 2 или более байта заполнения. Для 2 байт заполнения длина параметра будет иметь нулевое значение, а сам параметр будет состоять из поля типа и поля длины. В случае 3 байт заполнения длина будет равна 1, а следом за полем длины будет стоять один нулевой байт. Параметр размера увеличенного поля данных допускает увеличение поля размера дейтаграмм до 32 бит и используется, когда 16-разрядное поле размера, показанное на рис. А.2, оказывается недостаточно большим.
Мы показываем эти параметры схематически, потому что для всех параметров получателя и транзитных узлов действует так называемое условие выравнивания( alignment requirement), записываемое как xn + y. Это означает, что сдвиг данного параметра относительно начала заголовка равен числу, nраз кратному xбайтам, к которому добавлено убайтов (то есть величина сдвига в байтах равна xn + y). Например, условие выравнивания для параметра размера увеличенного поля данных записывается как 4 n+ 2. Это означает, что 4-байтовое значение параметра (длина размера увеличенного поля данных) будет выровнено по 4-байтовой границе. Причина, по которой значение y для этого параметра равно 2, заключается в том, что параметры транзитных узлов и получателя начинаются именно с двух байтов — один байт используется для указания типа, другой — для указания длины (см. рис. 27.4). Для параметра уведомления маршрутизатора условие выравнивания записывается как 2 n + 0, благодаря чему 2-байтовое значение параметра оказывается выровненным по 2-байтовой границе.
Параметры транзитных узлов и параметры получателя обычно задаются как вспомогательные данные в функции
sendmsg
и возвращаются функцией
recvmsg
также в виде вспомогательных данных. От приложения не требуется никаких специальных действий для отправки этих параметров — нужно только задать их при вызове функции
sendmsg
. Но для получения этих параметров должен быть включен соответствующий параметр сокета:
IPV6_RECVHOPOPTS
для параметра транзитных узлов и
IPV6_RECVDSTOPTS
для параметров получателя. Например, чтобы можно было получить оба параметра, нужен следующий код:
На рис. 27.6 показан формат объектов вспомогательных данных, используемый для отправки и получения параметров транзитных узлов и параметров получателя.
Рис. 27.6. Объекты вспомогательных данных, используемые для параметров транзитных узлов и параметров получателя
Чтобы уменьшить объем дублированного кода, определены семь функций, которые создают и обрабатывают эти вспомогательные объекты данных. Следующие четыре функции формируют отправляемый параметр.
#include <netinet/in.h>
int inet6_opt_init(void * extbuf, socklen_t extlen);
Возвращает:
количество байтов для размещения пустого заголовка расширения, -1 в случае ошибки
int inet6_opt_append(void * extbuf, socklen_t extlen,
Возвращает: длину расширяющего заголовка после добавления параметра, -1 в случае ошибки
int inet6_opt_finish(void * extbuf, socklen_t extlen, int offset);
Возвращает: длину законченного заголовка расширения, -1 в случае ошибки
int inet6_opt_set_val(void * databuf, int offset,
const void * val, socklen_t vallen);
Возвращает: новое смещение в буфере databuf
Функция
inet6_opt_init
возвращает количество байтов, необходимое для данного параметра. Если аргумент
extbuf
не является нулевым указателем, функция инициализирует заголовок расширения. Значение -1 возвращается при аварийном завершении работы в том случае, если аргумент
extlen
не кратен 8. (Все заголовки параметров транзитных узлов и получателя в IPv6 должны быть кратны 8.)
Функция
inet6_opt_append
возвращает общую длину заголовка расширения после добавления указанного при вызове параметра. Если аргумент
extbuf
не является нулевым указателем, функция дополнительно выполняет инициализацию параметра и вставляет необходимое заполнение. Значение -1 возвращается в случае аварийного завершения работы, если параметр не помещается в выделенный буфер. Аргумент
offset
представляет собой текущую полную длину, то есть значение, возвращенное при предыдущем вызове
inet6_opt_append
или
inet6_opt_init
. Аргументы
type
и
len
задают тип и длину параметра, они копируются непосредственно в его заголовок. Аргумент
align
указывает условие выравнивания, то есть значение x из выражения xn + y. Значение у вычисляется по
align
и
len
, поэтому указывать его явным образом необходимости нет. Аргумент
databufp
представляет собой адрес будущего указателя на значение параметра. Значение параметра копируется вызывающим процессом при помощи функции
inet6_opt_set_val
или любым другим методом.
Для завершения расширяющего заголовка вызывается функция
inet6_opt_finish
, которая добавляет в заголовок заполнение, делая его длину кратной 8 байтам. Как и раньше, заполнение добавляется в буфер только в том случае, если аргумент
extbuf
представляет собой непустой указатель. В противном случае функция вычисляет обновленное значение длины. Подобно
inet6_opt_append
, аргумент
offset
задает текущую полную длину (значение, возвращаемое
inet6_opt_append
и
inet6_opt_init
). Функция
inet6_opt_finish
возвращает полную длину возвращаемого заголовка или -1, если требуемое заполнение не помещается в предоставленный буфер.