主模式第一包:main_outI1()
1. 序言
main_outI1()
作为主模式主动发起连接请求的核心处理函数,我们可以通过学习该函数的处理流程来探究openswan中报文封装的基本思想。如果之前没有学习基本的函数接口(如in_struct, out_struct, out_sa等),那么直接学习main_outI1()
流程是比较困难的。如果想快速学习这几个函数接口,可以查看我先前的文章,我把需要的基本知识、思想等做了基本介绍,看完那几个接口再来学习此后的ISAKMP协商流程会容易很多,起到事半功倍的效果。
ISAKMP协商报文的处理流程都比较复杂,一个函数有几百行都是很常见的,因此个人学习期间难免有遗漏和理解错误的地方,请大家多多批评指正。
2. main_outI1()流程图
下面两个流程图中主要描述了三个函数的处理流程,后面我会分别附上这三个函数的源码信息。
3. main_outI1()源码注释
stf_status
main_outI1(int whack_sock
, struct connection *c
, struct state *predecessor
, so_serial_t *newstateno
, lset_t policy
, unsigned long try
, enum crypto_importance importance
, struct xfrm_user_sec_ctx_ike * uctx
)
{
struct state *st = new_state();/*创建一个新的状态*/
struct msg_digest md; /* use reply/rbody found inside */
int numvidtosend = 1; /* we always send DPD VID */
#ifdef NAT_TRAVERSAL
if (nat_traversal_enabled) {
numvidtosend++;
}
#endif
#if SEND_PLUTO_VID || defined(openpgp_peer)
numvidtosend++;
#endif
#ifdef XAUTH
if(c->spd.this.xauth_client || c->spd.this.xauth_server) {
numvidtosend++;
}
#endif
/*统计VID个数*/
/* set up new state *//*根据对端IP地址信息生成一个新的cookie*/
get_cookie(TRUE, st->st_icookie, COOKIE_SIZE, &c->spd.that.host_addr);
/*初始化新的state结构*/
initialize_new_state(st, c, policy, try, whack_sock, importance);
if(newstateno) *newstateno = st->st_serialno;
/* IKE version numbers -- used mostly in logging */
st->st_ike_maj = IKEv1_MAJOR_VERSION;
st->st_ike_min = IKEv1_MINOR_VERSION;
change_state(st, STATE_MAIN_I1);/*设置当前的状态为STATE_MAIN_I1*/
if (HAS_IPSEC_POLICY(policy))
add_pending(dup_any(whack_sock), st, c, policy, 1
, predecessor == NULL? SOS_NOBODY : predecessor->st_serialno
, uctx
);
#ifdef HAVE_LABELED_IPSEC
/*For main modes states, sec ctx is always null*/
st->sec_ctx = NULL;
#endif
if (predecessor == NULL)
openswan_log("initiating Main Mode");
else
openswan_log("initiating Main Mode to replace #%lu", predecessor->st_serialno);
/* set up reply */
zero(reply_buffer);/*初始化应答报文(发送的报文)的结构*/
init_pbs(&reply_stream, reply_buffer, sizeof(reply_buffer), "reply packet");
/* HDR out */
{
/*添加isakmp头部信息*/
struct isakmp_hdr hdr;
zero(&hdr); /* default to 0 */
hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION;
hdr.isa_np = ISAKMP_NEXT_SA;
hdr.isa_xchg = ISAKMP_XCHG_IDPROT;
memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE);
/* R-cookie, flags and MessageID are left zero */
/*长度字段最后设置: close_output_pbs(&reply_stream);*/
if (!out_struct(&hdr, &isakmp_hdr_desc, &reply_stream, &md.rbody))
{
reset_cur_state();
return STF_INTERNAL_ERROR;
}
}