主模式第二包:main_inI1_outR1()
文章目录
1. 序言
main_inI1_outR1()
函数是ISAKMP协商过程中第二包的核心处理函数,同时也是响应端口的首包。这里我们主要说明main_inI1_outR1
的处理流程,关于main_inI1_outR1
的上下文环境暂不叙述,留给后面的文章进行更新。
ISAKMP协商报文的处理流程都比较复杂,一个函数有几百行都是很常见的,因此个人学习期间难免有遗漏和理解错误的地方,请大家多多批评指正。
2. main_inI1_outR1()
处理流程图
下面的流程图不仅包括main_inI1_outR1
,还包括它其中的一个重要函数:parse_isakmp_sa_body
。此函数的作用就是解析对端的SA信息,然后根据对端的建议载荷,选择本地支持的算法,并构造自己的应答SA载荷。
3. main_inI1_outR1()源码
/* State Transition Functions.
*
* The definition of state_microcode_table in demux.c is a good
* overview of these routines.
*
* - Called from process_packet; result handled by complete_v1_state_transition
* - struct state_microcode member "processor" points to these
* - these routine definitionss are in state order
* - these routines must be restartable from any point of error return:
* beware of memory allocated before any error.
* - output HDR is usually emitted by process_packet (if state_microcode
* member first_out_payload isn't ISAKMP_NEXT_NONE).
*
* The transition functions' functions include:
* - process and judge payloads
* - update st_iv (result of decryption is in st_new_iv)
* - build reply packet
*/
/* Handle a Main Mode Oakley first packet (responder side).
* HDR;SA --> HDR;SA
*/
/********************************
*main_inI1_outR1函数被process_packet函数调用
*它的返回结果由complete_v1_state_transition处理
*
*********************************/
stf_status
main_inI1_outR1(struct msg_digest *md)
{
#ifdef DMALLOC
if (_dm_initialized != 0) {
/* log unfreed pointers that have been added to the heap since mark */
dmalloc_log_changed(_dm_mark, 1, 0, 1);
dmalloc_log_stats ();
}
_dm_mark = dmalloc_mark() ;
_dm_initialized = 1;
#endif
/*接收到的数据包中的SA载荷部分*/
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
struct state *st;
struct connection *c;
/*准备作为应答的SA载荷缓冲区*/
pb_stream r_sa_pbs;
lset_t policy_hint = 0;
/* we are looking for an OpenPGP Vendor ID sent by the peer */
bool openpgp_peer = FALSE;
/* Determin how many Vendor ID payloads we will be sending */
int next;
int numvidtosend = 1; /* we always send DPD VID */
/*至少会发送DPD的VID,因此初始值为1*/
#ifdef NAT_TRAVERSAL /*支持NAT-T,则增加一个nat-t探测的VID*/
if (md->quirks.nat_traversal_vid && nat_traversal_enabled) {
DBG(DBG_NATT, DBG_log("nat-t detected, sending nat-t VID"));
numvidtosend++;
}
#endif
/*如果预定义了PLUUO VID 或openpgp 对端, 增加VID 数量*/
#if SEND_PLUTO_VID || defined(openpgp_peer)
numvidtosend++;
#endif
#if defined(openpgp_peer)
{
struct payload_digest *p;
/*遍历接收到的数据包中的VID 载荷链表*/
for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
{
int vid_len = sizeof(pgp_vendorid) - 1 < pbs_left(&p->pbs)
? sizeof(pgp_vendorid) - 1 : pbs_left(&p->pbs);
/*检查是否是pgp VID, 是则设置openpgp_peer 标志为TRUE*/
if (memcmp(pgp_vendorid, p->pbs.cur, vid_len) == 0)
{
openpgp_peer = TRUE;
DBG(DBG_PARSING,
DBG_log("we have an OpenPGP peer")
)
}
}
}
#endif