openswan中的in_struct和out_struct函数
文章目录
1. 花絮
有什么比openswan中的in_struct和out_struct更让人难以理解的呢??? 如果存在的话,那就是:女朋友为啥又生气了?
算了,不管了,今天我是找不到她生气的原因了;还是把openswan中的in_struct()函数整理下吧,感觉这个更容易些
在学习openswan源码的过程中,有两个函数是想逃不能逃的,但是有很难看懂它是怎么个原理,它的功能很明确,但是就算如此,还是看不懂它的原理。我看这个接口花了很长的时间。哎,没办法,基础有点菜。下面就把个人的心得分享下:
2. in_struct代码实现分析
在源代码中in_struct和out_struct都有一段较为详细的注释:
/* "parse" a network struct into a host struct.
*
* This code assumes that the network and host structure
* members have the same alignment and size! This requires
* that all padding be explicit.
*
* If obj_pbs is supplied, a new pb_stream is created for the
* variable part of the structure (this depends on their
* being one length field in the structure). The cursor of this
* new PBS is set to after the parsed part of the struct.
*
* This routine returns TRUE iff it succeeds.
*/
这里对in_struct进行描述:它的功能也比较明确:
将网络字节序结构体转换为主机字节序结构体
这里假设网络结构体和主机结构体拥有相同的对齐方式和大小, 这要求他们所有的填充字节都是明确的。
如果参数obj_pbs是非空,则会创建一个新的pb_stream结构。它用来描述ins中sd的部分,但是cur指针是指向已经解析完毕的数据后后一个字节。
操作成功返回TRUE
是的,它转换的是结构体,而不是单个的short类型或者int类型。这样处理更加方便,模块化。简单的说:
htonl(), htons()分别转换的为四个字节,两个字节类型的变量,而in_struct(), out_struct()一次性转换一个结构体。只要你传入的结构体描述信息(struct_desc)正确就可以
也许我们对这个种方式不习惯,但是它的好处大大滴。既然使用了人家代码,那就接收人家的规则。
很多刚开始看的人不明白为什么要使用“obj_pbs”形参,既然解析完毕了为什么还要保存该信息呢???
实际上这个操作在变长的载荷中是必须的,因为变长部分数据并没有被转换到struct_ptr中。下面慢慢说明:
我是直接在源码上进行的注释:
/****************************************************
* 功能: 将网络字节序结构体转化为主机字节序结构体
* struct_ptr: 解析后的输出数据
* sd : 描述信息
* ins : 输入的网络字节序数据流
* obj_pbs : 指向该结构后面尚未解析的ins数据部分
*****************************************************/
bool
in_struct(void *struct_ptr, struct_desc *sd
, pb_stream *ins, pb_stream *obj_pbs)
{
err_t ugh = NULL;
u_int8_t *cur = ins->cur;/*待解析数据开始*/
/*确保有待解析的数据大小足够,否则无法成功解析为sd描述的大小*/
if (ins->roof - cur < (ptrdiff_t)sd->size)
{
ugh = builddiag("not enough room in input packet for %s"
" (remain=%li, sd->size=%zu)"
, sd->name, (long int)(ins->roof - cur), sd->size);
}
else
{
/*root指向待解析数据的末尾*/
u_int8_t *roof = cur + sd->size; /* may be changed by a length field *//*未考虑变长属性*/
u_int8_t *outp = struct_ptr;/*outp指向输出结构体*/
bool immediate = FALSE;
field_desc *fp;
for (fp = sd->fields; ugh == NULL; fp++)
{
size_t i = fp->size;
/*passert条件成立,继续执行;不成立,直接退出*/
passert(ins->roof - cur >= (ptrdiff_t)i);
passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i));
passert(outp - (cur - ins->cur) == struct_ptr);/*解析长度相同*/
switch (fp->field_type)
{
case ft_mbz: /* must be zero *//*全零域,*/
for (; i != 0; i--)
{
if (<