本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源: http://yfydz.cublog.cn

12.4.3 处理数据包

处理数据包是个非常大的函数, 用于处理接收到UDP数据, 根据数据包中的参数查找相关的状态, 然后再进行状态的转换操作, 数据包格式见9.2节。
/* process an input packet, possibly generating a reply.
 *
 * If all goes well, this routine eventually calls a state-specific
 * transition function.
 */
void
process_packet(struct msg_digest **mdp)
{
    struct msg_digest *md = *mdp;
    const struct state_microcode *smc;
    bool new_iv_set = FALSE;
// 相关状态初始化为空
    struct state *st = NULL;
// 起始状态, 初始化为未定义状态
    enum state_kind from_state = STATE_UNDEFINED; /* state we started in */
// 向发送通知的宏,通常是错误信息
#define SEND_NOTIFICATION(t) { \
    if (st) send_notification_from_state(st, from_state, t); \
    else send_notification_from_md(md, t); }
// 读取ISAKMP数据头
    if (!in_struct(&md->hdr, &isakmp_hdr_desc, &md->packet_pbs, &md->message_pbs))
    {
// 以下是数据头失败的情况
 /* Identify specific failures:
  * - bad ISAKMP major/minor version numbers
  */
// 先看长度够不够长
 if (md->packet_pbs.roof - md->packet_pbs.cur >= (ptrdiff_t)isakmp_hdr_desc.size)
 {
     struct isakmp_hdr *hdr = (struct isakmp_hdr *)md->packet_pbs.cur;
// 检查主版本号是否错误
     if ((hdr->isa_version >> ISA_MAJ_SHIFT) != ISAKMP_MAJOR_VERSION)
     {
  SEND_NOTIFICATION(INVALID_MAJOR_VERSION);
  return;
     }
// 检查次版本号是否错误
     else if ((hdr->isa_version & ISA_MIN_MASK) != ISAKMP_MINOR_VERSION)
     {
  SEND_NOTIFICATION(INVALID_MINOR_VERSION);
  return;
     }
 }
// 否则直接就说格式错误
 SEND_NOTIFICATION(PAYLOAD_MALFORMED);
 return;
    }
// 检查数据长度是否和标称的一致, 不匹配的话直接返回, 不发送错误消息
    if (md->packet_pbs.roof != md->message_pbs.roof)
    {
 openswan_log("size (%u) differs from size specified in ISAKMP HDR (%u)"
     , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
 return;
    }
    DBG(DBG_CONTROL
 , DBG_log(" processing packet with exchange type=%s (%d)"
    , enum_name(&exchange_names, md->hdr.isa_xchg)
    , md->hdr.isa_xchg));
// 交换类型, 取值如下:
//                  Exchange Type      Value
//               NONE                    0
//               Base                    1
//               Identity Protection     2
//               Authentication Only     3
//               Aggressive              4
//               Informational           5
//               ISAKMP Future Use     6 - 31
//               DOI Specific Use     32 - 239
//               Private Use         240 - 255
    switch (md->hdr.isa_xchg)
    {
#ifdef NOTYET
    case ISAKMP_XCHG_NONE:
    case ISAKMP_XCHG_BASE:
    case ISAKMP_XCHG_AO:
#endif
    case ISAKMP_XCHG_AGGR:
    case ISAKMP_XCHG_IDPROT: /* part of a Main Mode exchange */
// 对于这5种类型的交换类型,必须是MAINMODE_MSGID(0),否则错误
 if (md->hdr.isa_msgid != MAINMODE_MSGID)
 {
     openswan_log("Message ID was 0x%08lx but should be zero in phase 1",
  (unsigned long) md->hdr.isa_msgid);
     SEND_NOTIFICATION(INVALID_MESSAGE_ID);
     return;
 }
// 如果该数据包的发送方的cookie为全0, 是错误的
 if (is_zero_cookie(md->hdr.isa_icookie))
 {
     openswan_log("Initiator Cookie must not be zero in phase 1 message");
     SEND_NOTIFICATION(INVALID_COOKIE);
     return;
 }
// 如果该数据包的响应方cookie全0, 只能是协商过程的第一个数据包
 if (is_zero_cookie(md->hdr.isa_rcookie))
 {
     /* initial message from initiator
      * ??? what if this is a duplicate of another message?
      */
// 检查是否有加密标志, 第一个包是不能加密的, 否则没法解密
     if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
     {
  openswan_log("initial phase 1 message is invalid:"
      " its Encrypted Flag is on");
  SEND_NOTIFICATION(INVALID_FLAGS);
  return;
     }
     /* don't build a state until the message looks tasty */
// 这时起始状态设置MAIN_R0(主模式)或AGGR_R0(野蛮模式)
// 注意这里有个缺陷: 并没有查找状态, 纯粹将其作为第一个包, 这样很容易构成DOS***,
// 只要持续不停地发内容相同的协商首包, 就可以让pluto不停的新建状态, 和TCP的SYN flood
// 及其类似, 不过似乎也没办法, 只要更改发起方cookie, 就会认为是不同的连接
     from_state = (md->hdr.isa_xchg == ISAKMP_XCHG_IDPROT
    ? STATE_MAIN_R0 : STATE_AGGR_R0);
 }
 else
 {
     /* not an initial message */
// 响应方cookie非全0, 非初始化数据包, 根据cookie和源地址,消息ID来查找状态
     st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
  , &md->sender, md->hdr.isa_msgid);
// 没找到
     if (st == NULL)
     {
  /* perhaps this is a first message from the responder
   * and contains a responder cookie that we've not yet seen.
   */
// 按响应方cookie为0进行状态查找
  st = find_state(md->hdr.isa_icookie, zero_cookie
      , &md->sender, md->hdr.isa_msgid);
// 如果还是没找到, 直接返回, 不发送相关错误信息
  if (st == NULL)
  {
      openswan_log("phase 1 message is part of an unknown exchange");
      /* XXX Could send notification back */
      return;
  }
     }
// 状态找到, 设置为当前状态
     set_cur_state(st);
// 起始状态类型
     from_state = st->st_state;
 }
 break;
    case ISAKMP_XCHG_INFO: /* an informational exchange */
// 信息交换, 属于协商过程中间的数据包
// 根据双方的cookie, 发送方和消息ID查找状态
 st = find_info_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
        , &md->sender, MAINMODE_MSGID);
// 找到状态, 设置为当前状态
 if (st != NULL)
     set_cur_state(st);
// 如果数据包是加密的
 if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
 {
// 如果状态不存在, 直接返回, 不能直接解密一个无状态的加密包的
     if (st == NULL)
     {
  openswan_log("Informational Exchange is for an unknown (expired?) SA");
  /* XXX Could send notification back */
  return;
     }
// 如果状态存在, 但当前状态还是不需要加密的, 也就是密钥还没协商好, 这时加密包也是非法的
// 直接返回
     if (!IS_ISAKMP_ENCRYPTED(st->st_state))
     {
  loglog(RC_LOG_SERIOUS, "encrypted Informational Exchange message is invalid"
      " because no key is known");
  /* XXX Could send notification back */
  return;
     }
// 检查消息ID是否为0, 是则错误, 直接返回
     if (md->hdr.isa_msgid == MAINMODE_MSGID)
     {
  loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
      " it has a Message ID of 0");
  /* XXX Could send notification back */
  return;
     }
// 检查消息ID是否是保留的ID值, 是则错误, 直接返回
     if (!reserve_msgid(st, md->hdr.isa_msgid))
     {
  loglog(RC_LOG_SERIOUS, "Informational Exchange message is invalid because"
      " it has a previously used Message ID (0x%08lx)"
      , (unsigned long)md->hdr.isa_msgid);
  /* XXX Could send notification back */
  return;
     }
// 没有以上错误情况, 根据消息ID初始化加密算法的初始化向量
     init_phase2_iv(st, &md->hdr.isa_msgid);
// 初始化向量已设置标志
     new_iv_set = TRUE;
// 起始状态
     from_state = STATE_INFO_PROTECTED;
 }
 else
 {
// 数据包非加密
// 如果状态存在而且是已经认证过的, 这时的数据应该是加密的, 所以非加密包是非法的
// 出错返回
     if (st != NULL &&
  (IS_ISAKMP_AUTHENTICATED(st->st_state)))
     {
  loglog(RC_LOG_SERIOUS, "Informational Exchange message"
      " must be encrypted");
  /* XXX Could send notification back */
  return;
     }
// 起始状态
     from_state = STATE_INFO;
 }
 break;
    case ISAKMP_XCHG_QUICK: /* part of a Quick Mode exchange */
// 快速交换, 类型32
// 检查发起方cookie是否为全0, 是则错误, 发送非法cookie消息, 返回
 if (is_zero_cookie(md->hdr.isa_icookie))
 {
     openswan_log("Quick Mode message is invalid because"
  " it has an Initiator Cookie of 0");
     SEND_NOTIFICATION(INVALID_COOKIE);
     return;
 }
// 检查响应方cookie是否为全0, 是则错误, 发送非法cookie消息, 返回
 if (is_zero_cookie(md->hdr.isa_rcookie))
 {
     openswan_log("Quick Mode message is invalid because"
  " it has a Responder Cookie of 0");
     SEND_NOTIFICATION(INVALID_COOKIE);
     return;
 }
// 检查消息ID是否为0, 是则错误, 发送非法消息ID消息, 返回
 if (md->hdr.isa_msgid == MAINMODE_MSGID)
 {
     openswan_log("Quick Mode message is invalid because"
  " it has a Message ID of 0");
     SEND_NOTIFICATION(INVALID_MESSAGE_ID);
     return;
 }
// 根据双方的cookie, 发送方和消息ID查找状态
 st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
     , &md->sender, md->hdr.isa_msgid);
 if (st == NULL)
 {
     /* No appropriate Quick Mode state.
      * See if we have a Main Mode state.
      * ??? what if this is a duplicate of another message?
      */
// 如果没找到状态, 则将查找条件中消息ID改为0后重新查找
     st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
  , &md->sender, MAINMODE_MSGID);
// 还是没找到状态, 出错返回
     if (st == NULL)
     {
  openswan_log("Quick Mode message is for a non-existent (expired?)"
      " ISAKMP SA");
  /* XXX Could send notification back */
  return;
     }
#ifdef XAUTH
// 如果状态中XAUTH标志非0, 出错, 因为在快速模式时XAUTH已经完成了
     if(st->st_oakley.xauth != 0)
     {
  openswan_log("Cannot do Quick Mode until XAUTH done.");
  return;
     }
#endif
#ifdef MODECFG 
// 如果状态类型是扩展的STATE_MODE_CFG_R2, 改为STATE_MAIN_R3, 表示是主模式的结束状态
     if(st->st_state == STATE_MODE_CFG_R2)   /* Have we just give an IP address to peer? */
     {
  st->st_state = STATE_MAIN_R3;     /* ISAKMP is up... */
     }
#endif
// 设置为当前状态
     set_cur_state(st);
// 如果ISAKMP SA还未建立出错, 因为第一阶段中就是要协商出ISAKMP SA, 然后进入快速模式
// 出错发送载荷错误消息, 返回
     if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
     {
  loglog(RC_LOG_SERIOUS, "Quick Mode message is unacceptable because"
      " it is for an incomplete ISAKMP SA");
  SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
  return;
     }
     /* only accept this new Quick Mode exchange if it has a unique message ID */
// 如果用的是保留的消息ID, 出错, 发送非法ID信息
     if (!reserve_msgid(st, md->hdr.isa_msgid))
     {
  loglog(RC_LOG_SERIOUS, "Quick Mode I1 message is unacceptable because"
      " it uses a previously used Message ID 0x%08lx"
      " (perhaps this is a duplicated packet)"
      , (unsigned long) md->hdr.isa_msgid);
  SEND_NOTIFICATION(INVALID_MESSAGE_ID);
  return;
     }
     /* Quick Mode Initial IV */
// 没有以上错误情况, 根据消息ID初始化加密算法的初始化向量
     init_phase2_iv(st, &md->hdr.isa_msgid);
     new_iv_set = TRUE;
// 起始状态为QUICK_R0
     from_state = STATE_QUICK_R0;
 }
 else
 {
// 直接就找到状态了
#ifdef XAUTH
// 如果XAUTH还未完成, 错误
     if(st->st_oakley.xauth != 0)
     {
  openswan_log("Cannot do Quick Mode until XAUTH done.");
  return;
     }
#endif
     set_cur_state(st);
// 起始状态类型为当前状态的类型
     from_state = st->st_state;
 }
 break;
#ifdef MODECFG
    case ISAKMP_XCHG_MODE_CFG:
// 配置交换(6)
// 如果发起方cookie全0, 出错返回
 if (is_zero_cookie(md->hdr.isa_icookie))
 {
     openswan_log("Mode Config message is invalid because"
  " it has an Initiator Cookie of 0");
     /* XXX Could send notification back */
     return;
 }
// 如果响应方cookie全0, 出错返回
 if (is_zero_cookie(md->hdr.isa_rcookie))
 {
     openswan_log("Mode Config message is invalid because"
  " it has a Responder Cookie of 0");
     /* XXX Could send notification back */
     return;
 }
// 如果消息ID为0, 出错返回
 if (md->hdr.isa_msgid == 0)
 {
     openswan_log("Mode Config message is invalid because"
  " it has a Message ID of 0");
     /* XXX Could send notification back */
     return;
 }
// 查找状态
 st = find_info_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
        , &md->sender, md->hdr.isa_msgid);
 if (st == NULL)
 {
     /* No appropriate Mode Config state.
      * See if we have a Main Mode state.
      * ??? what if this is a duplicate of another message?
      */
// 状态没找到, 则用为0的消息ID重新查找
     st = find_state(md->hdr.isa_icookie, md->hdr.isa_rcookie
     , &md->sender, 0);
// 没找到状态, 返回
     if (st == NULL)
     {
  openswan_log("Mode Config message is for a non-existent (expired?)"
      " ISAKMP SA");
  /* XXX Could send notification back */
  return;
     }
// 设置为当前状态
     set_cur_state(st);
// 如果该状态下ISAKMP SA仍然未协商好, 错误
     if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
     {
  loglog(RC_LOG_SERIOUS, "Mode Config message is unacceptable because"
          " it is for an incomplete ISAKMP SA (state=%s)"
          , enum_name(&state_names, st->st_state));
  /* XXX Could send notification back */
  return;
     }
// 没有以上错误情况, 根据消息ID初始化加密算法的初始化向量
     init_phase2_iv(st, &md->hdr.isa_msgid);
     new_iv_set = TRUE;
     /*
      * okay, now we have to figure out if we are receiving a bogus
      * new message in an oustanding XAUTH server conversation
      * (i.e. a reply to our challenge)
      * (this occurs with some broken other implementations).
      *
      * or if receiving for the first time, an XAUTH challenge.
      *
      * or if we are getting a MODECFG request.
      *
      * we distinguish these states because we can not both be an
      * XAUTH server and client, and our policy tells us which
      * one we are.
      *
      * to complicate further, it is normal to start a new msgid
      * when going from one state to another, or when restarting
      * the challenge.
      *
      */
// 如果本地是XAUTH服务器, 当前状态类型为XAUTH_R1,而且xauth_ack_msgid非0
     if(st->st_connection->spd.this.xauth_server
        && st->st_state == STATE_XAUTH_R1
        && st->quirks.xauth_ack_msgid)
     {
// 起始状态设置为XAUTH_R1
  from_state = STATE_XAUTH_R1;
     }
// 如果本地是XAUTH客户端, 而且处于阶段1
     else if(st->st_connection->spd.this.xauth_client
      && IS_PHASE1(st->st_state))
     {
// 起始状态设置为XAUTH_I0
  from_state = STATE_XAUTH_I0;
     }
// 如果本地是XAUTH客户端, 而且处于XAUTH_I1阶段, 是想重新协商MODECFG
     else if(st->st_connection->spd.this.xauth_client
      && st->st_state == STATE_XAUTH_I1)
     {
         /*
   * in this case, we got a new MODECFG message after I0, maybe
   * because it wants to start over again.
   */
// 起始状态设置为XAUTH_I0
  from_state = STATE_XAUTH_I0;
     }
// 如果本地是MODECFG服务器, 而且处于阶段1
     else if(st->st_connection->spd.this.modecfg_server
      && IS_PHASE1(st->st_state))
     {
// 起始状态设置为MODE_CFG_R0
  from_state = STATE_MODE_CFG_R0;
     }
// 如果本地是MODECFG客户端, 而且处于阶段1
     else if(st->st_connection->spd.this.modecfg_client
      && IS_PHASE1(st->st_state))
     {
// 起始状态设置为MODE_CFG_R1
  from_state = STATE_MODE_CFG_R1;
     }
     else {
// 否则不能处理该MODECFG, 出错返回
  /* XXX check if we are being a mode config server here */
  openswan_log("received MODECFG message when in state %s, and we aren't xauth client"
       , enum_name(&state_names, st->st_state));
  return;
     }
 }
 else
 {
// 直接就找到状态
// 如果是XAUTH服务器而且还是阶段1的状态
     if(st->st_connection->spd.this.xauth_server
        && IS_PHASE1(st->st_state)) /* Switch from Phase1 to Mode Config */
     {
  openswan_log("We were in phase 1, with no state, so we went to XAUTH_R0");
// 将状态类型改为XAUTH_R0, 准备进入XAUTH处理
  st->st_state = STATE_XAUTH_R0;
     }
     /* otherweise, this is fine, we continue in the state we are in */
// 设置为当前状态
     set_cur_state(st);
// 起始状态类型
     from_state = st->st_state;
 }
 break;
#endif
    case ISAKMP_XCHG_ECHOREQUEST_PRIVATE:
    case ISAKMP_XCHG_ECHOREQUEST:
// 接收到保活的echo请求
 receive_ike_echo_request(md);
 return;
 
    case ISAKMP_XCHG_ECHOREPLY_PRIVATE:
    case ISAKMP_XCHG_ECHOREPLY:
// 接收到保活的echo请求回应消息
 receive_ike_echo_reply(md);
 return;
#ifdef NOTYET
    case ISAKMP_XCHG_NGRP:
    case ISAKMP_XCHG_ACK_INFO:
#endif
// 其他数据交换类型不支持, 发送未知交换类型通知
    default:
 openswan_log("unsupported exchange type %s in message"
     , enum_show(&exchange_names, md->hdr.isa_xchg));
 SEND_NOTIFICATION(UNSUPPORTED_EXCHANGE_TYPE);
 return;
    }
    /* We have found a from_state, and perhaps a state object.
     * If we need to build a new state object,
     * we wait until the packet has been sanity checked.
     */
    /* We don't support the Commit Flag.  It is such a bad feature.
     * It isn't protected -- neither encrypted nor authenticated.
     * A man in the middle turns it on, leading to DoS.
     * We just ignore it, with a warning.
     * By placing the check here, we could easily add a policy bit
     * to a connection to suppress the warning.  This might be useful
     * because the Commit Flag is expected from some peers.
     */
// pluto不支持COMMIT标志
    if (md->hdr.isa_flags & ISAKMP_FLAG_COMMIT)
    {
 openswan_log("IKE message has the Commit Flag set but Pluto doesn't implement this feature; ignoring flag");
    }
    /* Set smc to describe this state's properties.
     * Look up the appropriate microcode based on state and
     * possibly Oakley Auth type.
     */
    passert(STATE_IKE_FLOOR <= from_state && from_state <= STATE_IKE_ROOF);
// 起始状态对应的微码索引号, 准备索引对应的微码结构
    smc = ike_microcode_index[from_state - STATE_IKE_FLOOR];
    if (st != NULL)
    {
// 如果状态非空
// 获取认证算法标志
#if defined(XAUTH)
      oakley_auth_t baseauth = xauth_calcbaseauth(st->st_oakley.auth);
#else
      oakley_auth_t baseauth = st->st_oakley.auth;
#endif
// 如果相应微码结构中没设置该认证标志, 在起始状态相同的情况下更新到下一个微码结构
      while (!LHAS(smc->flags, baseauth))
 {
   smc++;
   passert(smc->state == from_state);
 }
    }
    /* Ignore a packet if the state has a suspended state transition
     * Probably a duplicated packet but the original packet is not yet
     * recorded in st->st_rpacket, so duplicate checking won't catch.
     * ??? Should the packet be recorded earlier to improve diagnosis?
     */
// 如果状态非空, 而且有正在处理的消息摘要, 可能是个重发包, 不处理了, 返回
    if (st != NULL && st->st_suspended_md != NULL)
    {
 loglog(RC_LOG, "discarding packet received during asynchronous work (DNS or crypto) in %s"
     , enum_name(&state_names, st->st_state));
 return;
    }
    /*
     * if this state is busy calculating in between state transitions,
     * (there will be no suspended state), then we silently ignore the
     * packet, as there is nothing we can do right now.
     */
// 如果状态非空而且正在计算中, 返回
    if(st!=NULL && st->st_calculating) {
 openswan_log("message received while calculating. Ignored.");
 return;
    }
    /* Detect and handle duplicated packets.
     * This won't work for the initial packet of an exchange
     * because we won't have a state object to remember it.
     * If we are in a non-receiving state (terminal), and the preceding
     * state did transmit, then the duplicate may indicate that that
     * transmission wasn't received -- retransmit it.
     * Otherwise, just discard it.
     * ??? Notification packets are like exchanges -- I hope that
     * they are idempotent!
     */
// 状态非空, 表示非初始化包
    if (st != NULL
// 状态中数据空间指针非空
 && st->st_rpacket.ptr != NULL
// 状态中数据长度和当前数据包的一致
 && st->st_rpacket.len == pbs_room(&md->packet_pbs)
// 比较数据完全匹配成功, 是重发包
 && memcmp(st->st_rpacket.ptr, md->packet_pbs.start, st->st_rpacket.len) == 0)
    {
// 如果该微码节点设置了重发包的重新发送数据标志, 准备重新发送该状态相关数据包,
// 否则忽略返回
 if (smc->flags & SMF_RETRANSMIT_ON_DUPLICATE)
 {
// 如果重发次数没超过最大限值, 就重新发送状态数据包
     if (st->st_retransmit < MAXIMUM_RETRANSMISSIONS)
     {
  st->st_retransmit++;
  loglog(RC_RETRANSMISSION
      , "retransmitting in response to duplicate packet; already %s"
      , enum_name(&state_names, st->st_state));
  send_packet(st, "retransmit in response to duplicate", TRUE);
     }
     else
     {
  loglog(RC_LOG_SERIOUS, "discarding duplicate packet -- exhausted retransmission; already %s"
      , enum_name(&state_names, st->st_state));
     }
 }
 else
 {
     loglog(RC_LOG_SERIOUS, "discarding duplicate packet; already %s"
  , enum_name(&state_names, st->st_state));
 }
 return;
    }
    /*
     * look for encrypt packets. We can not handle them if we have not
     * yet calculated the skeyids. We will just store the packet in
     * the suspended state, since the calculation is likely underway.
     *
     * note that this differs from above, because skeyid is calculated
     * in between states. (or will be, once DH is async)
     *
     */
// 如果数据包中有加密标志
    if((md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
// 状态非空,但指数计算还在计算中
       && st!=NULL && !st->hidden_variables.st_skeyid_calculated )
    {
 DBG(DBG_CRYPT|DBG_CONTROL
     , DBG_log("received encrypted packet from %s:%u but exponentiation still in progress"
        , ip_str(&md->sender), (unsigned)md->sender_port));
// 将该数据包暂时挂起, 等计算完再处理
 if(st->st_suspended_md) { release_md(st->st_suspended_md); }
 st->st_suspended_md = md;
 md->st = st;
 *mdp = NULL;
 return;
    }
// 如果数据包中有加密标志
    if (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
    {
 DBG(DBG_CRYPT, DBG_log("received encrypted packet from %s:%u"
     , ip_str(&md->sender), (unsigned)md->sender_port));
// 如果状态为空, 不处理这种无状态加密包, 发送错误消息, 返回
 if (st == NULL)
 {
     openswan_log("discarding encrypted message for an unknown ISAKMP SA");
     SEND_NOTIFICATION(PAYLOAD_MALFORMED /* XXX ? */);
     return;
 }
// 到这里时指数计算已经完成
// 但计算结果为空, 发送错误消息, 返回
 if (st->st_skeyid_e.ptr == (u_char *) NULL)
 {
     loglog(RC_LOG_SERIOUS, "discarding encrypted message"
  " because we haven't yet negotiated keying materiel");
     SEND_NOTIFICATION(INVALID_FLAGS);
     return;
 }
 /* Mark as encrypted */
// 加密标志
 md->encrypted = TRUE;
 DBG(DBG_CRYPT, DBG_log("decrypting %u bytes using algorithm %s"
     , (unsigned) pbs_left(&md->message_pbs)
     , enum_show(&oakley_enc_names, st->st_oakley.encrypt)));
 /* do the specified decryption
  *
  * IV is from st->st_iv or (if new_iv_set) st->st_new_iv.
  * The new IV is placed in st->st_new_iv
  *
  * See RFC 2409 "IKE" Appendix B
  *
  * XXX The IV should only be updated really if the packet
  * is successfully processed.
  * We should keep this value, check for a success return
  * value from the parsing routines and then replace.
  *
  * Each post phase 1 exchange generates IVs from
  * the last phase 1 block, not the last block sent.
  */
// 进入解密处理
 {
     const struct encrypt_desc *e = st->st_oakley.encrypter;
// 检查加密数据长度是否算法块长度的整数倍, 不是则是错误包, 返回
     if (pbs_left(&md->message_pbs) % e->enc_blocksize != 0)
     {
  loglog(RC_LOG_SERIOUS, "malformed message: not a multiple of encryption blocksize");
  SEND_NOTIFICATION(PAYLOAD_MALFORMED);
  return;
     }
     /* XXX Detect weak keys */
     /* grab a copy of raw packet (for duplicate packet detection) */
// 复制原始数据
     clonetochunk(md->raw_packet, md->packet_pbs.start
    , pbs_room(&md->packet_pbs), "raw packet");
     /* Decrypt everything after header */
// 如果没有初始化向量, 生成之
     if (!new_iv_set)
     {
  if(st->st_iv_len == 0) {
      init_phase2_iv(st, &md->hdr.isa_msgid);
  } else {
      /* use old IV */
      passert(st->st_iv_len <= sizeof(st->st_new_iv));
      st->st_new_iv_len = st->st_iv_len;
      init_new_iv(st);
  }
     }
// 进行解密操作, 不管哪种加密算法都都是用CBC模式的
     crypto_cbc_encrypt(e, FALSE, md->message_pbs.cur,
       pbs_left(&md->message_pbs) , st);
 }
// 打印解密出的数据
 DBG_cond_dump(DBG_CRYPT, "decrypted:\n", md->message_pbs.cur
        , md->message_pbs.roof - md->message_pbs.cur);
 DBG_cond_dump(DBG_CRYPT, "next IV:"
        , st->st_new_iv, st->st_new_iv_len);
    }
    else
    {
 /* packet was not encryped -- should it have been? */
// 进入这里则是非加密数据
// 检查微码结构中是否设置了需要加密的标志, 是则发送错误消息, 返回
 if (smc->flags & SMF_INPUT_ENCRYPTED)
 {
     loglog(RC_LOG_SERIOUS, "packet rejected: should have been encrypted");
     SEND_NOTIFICATION(INVALID_FLAGS);
     return;
 }
    }
    /* Digest the message.
     * Padding must be removed to make hashing work.
     * Padding comes from encryption (so this code must be after decryption).
     * Padding rules are described before the definition of
     * struct isakmp_hdr in packet.h.
     */
// 填充数据摘要结构
    {
// 载荷摘要
 struct payload_digest *pd = md->digest;
// 下一个载荷
 int np = md->hdr.isa_np;
 lset_t needed = smc->req_payloads;
 const char *excuse
     = LIN(SMF_PSK_AUTH | SMF_FIRST_ENCRYPTED_INPUT, smc->flags)
  ? "probable authentication failure (mismatch of preshared secrets?): "
  : "";
// 遍历数据包的所有载荷, 直到为ISAKMP_NEXT_NONE时表示是最后一个载荷
 while (np != ISAKMP_NEXT_NONE)
 {
// 载荷描述结构
     struct_desc *sd = np < ISAKMP_NEXT_ROOF? payload_descs[np] : NULL;
// 载荷太多, 发错误信息, 返回
     if (pd == &md->digest[PAYLIMIT])
     {
  loglog(RC_LOG_SERIOUS, "more than %d payloads in message; ignored", PAYLIMIT);
  SEND_NOTIFICATION(PAYLOAD_MALFORMED);
  return;
     }
#ifdef NAT_TRAVERSAL
// 支持NAT穿越情况
     switch (np)
     {
// 如果是这两种类型的载荷
  case ISAKMP_NEXT_NATD_RFC:
  case ISAKMP_NEXT_NATOA_RFC:
// 如果状态为空(初始化包)或无NAT_T_WITH_RFC_VALUES标志, 载荷描述结构为空
      if ((!st) || (!(st->hidden_variables.st_nat_traversal & NAT_T_WITH_RFC_VALUES))) {
   /*
    * don't accept NAT-D/NAT-OA reloc directly in message,
    * unless we're using NAT-T RFC
    */
   sd = NULL;
      }
      break;
     }
#endif
// 无载荷描述结构的情况
     if (sd == NULL)
     {
  /* payload type is out of range or requires special handling */
// 以下根据下一载荷类型和起始状态类型来确定载荷描述结构
  switch (np)
  {
  case ISAKMP_NEXT_ID:
      sd = IS_PHASE1(from_state)
   ? &isakmp_identification_desc : &isakmp_ipsec_identification_desc;
      break;
#ifdef NAT_TRAVERSAL
  case ISAKMP_NEXT_NATD_DRAFTS:
      np = ISAKMP_NEXT_NATD_RFC;  /* NAT-D relocated */
      sd = payload_descs[np];
      break;
  case ISAKMP_NEXT_NATOA_DRAFTS:
      np = ISAKMP_NEXT_NATOA_RFC;  /* NAT-OA relocated */
      sd = payload_descs[np];
      break;
  case ISAKMP_NEXT_NATD_BADDRAFTS:
      if (st && (st->hidden_variables.st_nat_traversal & NAT_T_WITH_NATD_BADDRAFT_VALUES)) {
   /*
    * Only accept this value if we're in compatibility mode with
    * the bad drafts of the RFC
    */
      np = ISAKMP_NEXT_NATD_RFC;  /* NAT-D relocated */
      sd = payload_descs[np];
      break;
  }
#endif
  default:
// 其他没法找到描述结构的, 出错返回
      loglog(RC_LOG_SERIOUS, "%smessage ignored because it contains an unknown or"
   " unexpected payload type (%s) at the outermost level"
   , excuse, enum_show(&payload_names, np));
      SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
      return;
  }
     }
// 现在就都有相应的载荷描述结构了
     {
  lset_t s = LELEM(np);
// 进行标志和载荷类型检查, 错误则返回
  if (LDISJOINT(s
  , needed | smc->opt_payloads| LELEM(ISAKMP_NEXT_N) | LELEM(ISAKMP_NEXT_D)))
  {
      loglog(RC_LOG_SERIOUS, "%smessage ignored because it "
      "contains an unexpected payload type (%s)"
   , excuse, enum_show(&payload_names, np));
      SEND_NOTIFICATION(INVALID_PAYLOAD_TYPE);
      return;
  }
  needed &= ~s;
     }
// 读取载荷
     if (!in_struct(&pd->payload, sd, &md->message_pbs, &pd->pbs))
     {
  loglog(RC_LOG_SERIOUS, "%smalformed payload in packet", excuse);
  SEND_NOTIFICATION(PAYLOAD_MALFORMED);
  return;
     }
     /* place this payload at the end of the chain for this type */
// 将该载荷结构挂接到相应类型的链表的最后
     {
  struct payload_digest **p;
  for (p = &md->chain[np]; *p != NULL; p = &(*p)->next)
      ;
  *p = pd;
  pd->next = NULL;
     }
// 更新下一载荷, 循环
     np = pd->payload.generic.isag_np;
     pd++;
     /* since we've digested one payload happily, it is probably
      * the case that any decryption worked.  So we will not suggest
      * encryption failure as an excuse for subsequent payload
      * problems.
      */
     excuse = "";
 }
// 载荷尾, 即填充数据
 md->digest_roof = pd;
 DBG(DBG_PARSING,
     if (pbs_left(&md->message_pbs) != 0)
  DBG_log("removing %d bytes of padding", (int) pbs_left(&md->message_pbs)));
 md->message_pbs.roof = md->message_pbs.cur;
 /* check that all mandatory payloads appeared */
// needed标志非0,表示还有需要的载荷但当前数据包中没有提供,错误返回
 if (needed != 0)
 {
     loglog(RC_LOG_SERIOUS, "message for %s is missing payloads %s"
  , enum_show(&state_names, from_state)
  , bitnamesof(payload_name, needed));
     SEND_NOTIFICATION(PAYLOAD_MALFORMED);
     return;
 }
    }

// 对载荷数据进行检查
    /* more sanity checking: enforce most ordering constraints */
// 起始状态是第一阶段的状态: 主模式或野蛮模式
    if (IS_PHASE1(from_state))
    {
 /* rfc2409: The Internet Key Exchange (IKE), 5 Exchanges:
  * "The SA payload MUST precede all other payloads in a phase 1 exchange."
  */
// 检查SA载荷是否是阶段1交换过程中数据的第一个载荷, 不是则出错
 if (md->chain[ISAKMP_NEXT_SA] != NULL
 && md->hdr.isa_np != ISAKMP_NEXT_SA)
 {
     loglog(RC_LOG_SERIOUS, "malformed Phase 1 message: does not start with an SA payload");
     SEND_NOTIFICATION(PAYLOAD_MALFORMED);
     return;
 }
    }
// 如果起始状态是快速模式(第2阶段)的状态
    else if (IS_QUICK(from_state))
    {
 /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode
  *
  * "In Quick Mode, a HASH payload MUST immediately follow the ISAKMP
  *  header and a SA payload MUST immediately follow the HASH."
  * [NOTE: there may be more than one SA payload, so this is not
  *  totally reasonable.  Probably all SAs should be so constrained.]
  *
  * "If ISAKMP is acting as a client negotiator on behalf of another
  *  party, the identities of the parties MUST be passed as IDci and
  *  then IDcr."
  *
  * "With the exception of the HASH, SA, and the optional ID payloads,
  *  there are no payload ordering restrictions on Quick Mode."
  */
// 快速模式必须以哈希载荷开头
 if (md->hdr.isa_np != ISAKMP_NEXT_HASH)
 {
     loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: does not start with a HASH payload");
     SEND_NOTIFICATION(PAYLOAD_MALFORMED);
     return;
 }
 {
     struct payload_digest *p;
     int i;
// 遍历SA链表
     for (p = md->chain[ISAKMP_NEXT_SA], i = 1; p != NULL
     ; p = p->next, i++)
     {
// 检查SA载荷是否在合适的位置, 应该根在哈希载荷之后,错误则返回
  if (p != &md->digest[i])
  {
      loglog(RC_LOG_SERIOUS, "malformed Quick Mode message: SA payload is in wrong position");
      SEND_NOTIFICATION(PAYLOAD_MALFORMED);
      return;
  }
     }
 }
 /* rfc2409: The Internet Key Exchange (IKE), 5.5 Phase 2 - Quick Mode:
  * "If ISAKMP is acting as a client negotiator on behalf of another
  *  party, the identities of the parties MUST be passed as IDci and
  *  then IDcr."
  */
 {
// 阶段2的ID载荷
     struct payload_digest *id = md->chain[ISAKMP_NEXT_ID];
     if (id != NULL)
     {
// 如果有ID载荷,就必须是两个
  if (id->next == NULL || id->next->next != NULL)
  {
      loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
   " if any ID payload is present,"
   " there must be exactly two");
      SEND_NOTIFICATION(PAYLOAD_MALFORMED);
      return;
  }
// 而且这两个ID载荷是相邻的
  if (id+1 != id->next)
  {
      loglog(RC_LOG_SERIOUS, "malformed Quick Mode message:"
   " the ID payloads are not adjacent");
      SEND_NOTIFICATION(PAYLOAD_MALFORMED);
      return;
  }
     }
 }
    }
    /* Ignore payloads that we don't handle:
     * Delete, Notification, VendorID
     */
    /* XXX Handle deletions */
    /* XXX Handle Notifications */
    /* XXX Handle VID payloads */
    {
 struct payload_digest *p;
// 通知(notification)载荷链表
 for (p = md->chain[ISAKMP_NEXT_N]; p != NULL; p = p->next)
 {
// 看看如果不是DPD保活通知, 不是载荷错误通知
                if(p->payload.notification.isan_type != R_U_THERE
     && p->payload.notification.isan_type != R_U_THERE_ACK
     && p->payload.notification.isan_type != PAYLOAD_MALFORMED) {
// 按错误进行记录
      loglog(RC_LOG_SERIOUS
      , "ignoring informational payload, type %s"
      , enum_show(&ipsec_notification_names
           , p->payload.notification.isan_type));
  }
// 对上面3种类型只普通记录
     DBG_cond_dump(DBG_PARSING, "info:", p->pbs.cur, pbs_left(&p->pbs));
 }
// 删除载荷链表
 for (p = md->chain[ISAKMP_NEXT_D]; p != NULL; p = p->next)
 {
// 接受删除
     accept_delete(st, md, p);
     DBG_cond_dump(DBG_PARSING, "del:", p->pbs.cur, pbs_left(&p->pbs));
 }
// 提供者ID链表
 for (p = md->chain[ISAKMP_NEXT_VID]; p != NULL; p = p->next)
 {
#if 0
     char vid_string[48];
     size_t vid_len = sizeof(vid_string) - 1 < pbs_left(&p->pbs)
  ? sizeof(vid_string) - 1 : pbs_left(&p->pbs);
     size_t i;
     /* make it printable by forcing bits; truncate if long */
     for (i = 0; i < vid_len; i++)
  vid_string[i] = (p->pbs.cur[i] & 0x7f);
     vid_string[vid_len] = '\0';
     loglog(RC_LOG, "received Vendor ID Payload; ASCII hash: %s"
  , vid_string);
     DBG_cond_dump(DBG_PARSING, "VID:", p->pbs.cur, pbs_left(&p->pbs));
#endif
// 处理提供者信息
     handle_vendorid(md, p->pbs.cur, pbs_left(&p->pbs), st);
 }
    }
// 填充消息摘要参数
    md->from_state = from_state;
    md->smc = smc;
    md->st = st;
    /* possibly fill in hdr */
    if (smc->first_out_payload != ISAKMP_NEXT_NONE)
 echo_hdr(md, (smc->flags & SMF_OUTPUT_ENCRYPTED) != 0
     , smc->first_out_payload);
// 先执行smc->processor函数, 然后才执行complete_state_transition函数
// smc->processor就是微码结构的状态处理函数, 大都在ipsec_doi.c中定义
    complete_state_transition(mdp, smc->processor(md));
}

...... 待续 ......