eay_init();//opensll初始化
initlcconf();//本地配置文件初始化
initrmconf();//远端配置文件初始化
oakley_dhinit();//dh算法初始化
compute_vendorids();//dpd
parse(ac, av);//传进来的参数分析
ploginit();//本地日志初始化
pfkey_init()//内核接口af_key初始化,主要是向内核注册
isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))//isakmp配置初始化
cfparse();//配置文件分析,别且赋值给相应结构体
session();//主要会话
下面是session函数里面的实现:
sched_init();//调度初始化
init_signal();//信号初始化
admin_init()//和setkey, racoonctl的连接口初始化
initmyaddr();//初始化本地地址
isakmp_init()//isakmp初始化
initfds();//初始化select的套接字
natt_keepalive_init ();//初始化nat协商的相关内容
for (i = 0; i <= NSIG; i++)//信号的相应保存变量初始化
sigreq[i] = 0;
check_sigreq();//检测是否收到有信号
error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);//多路监听
admin_handler();//监听到setkey和racoonctl的fd触发,调用该函数处理
isakmp_handler(p->sock);//监听到ike连接信息和ike协商信息处理函数
pfkey_handler();//监听的内核af_key发上来的信息处理函数(包含发起ike协商等)
isakmp_handler(p->sock);函数里最重要的函数是isakmp_main()
isakmp_handler(p->sock);()这个函数里面除了数据包有效性检查外,ph1_main()第一阶段函数,quick_main()第二阶段处理函数,这两个函数最重要。
这两个函数内分别用了一个重要的结构体:如下
ph1exchange[][] 整个racoon就靠这个结构体来进行协商。(可以说是贯穿整个racoon)
static int (*ph1exchange[][2][PHASE1ST_MAX])
__P((struct ph1handle *, vchar_t *)) = {
/* error */
{ {}, {}, },
/* Identity Protection exchange */
{
{ nostate1, ident_i1send, nostate1, ident_i2recv, ident_i2send,
ident_i3recv, ident_i3send, ident_i4recv, ident_i4send, nostate1, },
{ nostate1, ident_r1recv, ident_r1send, ident_r2recv, ident_r2send,
ident_r3recv, ident_r3send, nostate1, nostate1, nostate1, },
},
/* Aggressive exchange */
{
{ nostate1, agg_i1send, nostate1, agg_i2recv, agg_i2send,
nostate1, nostate1, nostate1, nostate1, nostate1, },
{ nostate1, agg_r1recv, agg_r1send, agg_r2recv, agg_r2send,
nostate1, nostate1, nostate1, nostate1, nostate1, },
},
/* Base exchange */
{
{ nostate1, base_i1send, nostate1, base_i2recv, base_i2send,
base_i3recv, base_i3send, nostate1, nostate1, nostate1, },
{ nostate1, base_r1recv, base_r1send, base_r2recv, base_r2send,
nostate1, nostate1, nostate1, nostate1, nostate1, },
},
};
可以看的到上面有第一阶段有三个模式的发送和接受函数(main , Aggressive, base);
其中有每一个模式下的交互消息 一个函数。同时也有验证函数。如果熟悉几种模式的发包流程,
相信通过函数定义的名字 就可以轻松知道 函数是干嘛用的了。(注意存在状态判断函数,发送
和接收函数,每个阶段都不同)以上函数会在ph1_main()调用,在pfkey_handler()调用的则是
协商发起方。
static int (*ph2exchange[][2][PHASE2ST_MAX])
__P((struct ph2handle *, vchar_t *)) = {
/* error */
{ {}, {}, },
/* Quick mode for IKE */
{
{ nostate2, nostate2, quick_i1prep, nostate2, quick_i1send,
quick_i2recv, quick_i2send, quick_i3recv, nostate2, nostate2, },
{ nostate2, quick_r1recv, quick_r1prep, nostate2, quick_r2send,
quick_r3recv, quick_r3prep, quick_r3send, nostate2, nostate2, }
},
};
可以看到上面的第二阶段即快速模式下的发送和接受函数,这些函数就是ike第二阶段协商使用的。
其中有二阶段的每个包的发送和接受,状态函数。具体是怎么实现的 请参看相应的源代码。以上的
ph2handle会在,quick_main()中调用。
各个处理方法和流程参考代码就可以了。这就是大概流程,其中可能会涉及到openssl编码问题(第一
阶段的算法为二阶段的传递信息编码)。