/******************************************************************************
*Func Name   : PTPV2_ANN_PrintAnn
*Description : announce报文打印接口
*Input       : PTPV2_ANNOUNCE_MSG_S *pstAnnMsg: 消息头
*              TCPIP_PTP_ADDRINFO_S *pstAddrInfo:  接收/发送报文的地址以及UDP信息
*              ULONG ulFlag:        标记:0-发送报文;非0-接收报文
*Output      : 
*Return      : 
*Caution     : 
*Calls       : 
*Called by   : 
*-----------------------------------------------------------------------------
*  Modification History
*  DATE                 NAME           DESCRIPTION
*  2014-05-14           dutianyi       Create
*******************************************************************************/
VOID PTPV2_ANN_PrintAnn(PTPV2_ANNOUNCE_MSG_S *pstAnnMsg, TCPIP_PTP_ADDRINFO_S *pstAddrInfo, ULONG ulFlag)
{    
    CHAR szBuf[LEN_512] = {0};  /* 缓冲区长度512个字节,存放报文信息 */
    CHAR szInOrOut[10] = {0};
    INT32 i32Offset = 0;
    
    if ((NULL == pstAnnMsg) || (NULL == pstAddrInfo))
    {
        return;
    }
    
    if (0 == ulFlag)
    {
        i32Offset = TCPIP_SNPRINTF0(szInOrOut, 10, P0("send"));
    }
    else
    {
        i32Offset = TCPIP_SNPRINTF0(szInOrOut, 10, P0("receive"));
    }
    
    /* 先打印提示信息 */
    (VOID)TCPIP_SNPRINTF(szBuf + i32Offset, LEN_512 - i32Offset, P1("\r\n----------announce msg %s begin----------",szInOrOut));
    
    TCPIP_InfoOutput(szBuf);

    (VOID)TCPIP_Mem_Set(szBuf, 0, LEN_512);
    
    /* 打印消息头 */
    PTPV2_PrintHeader((PTPV2_MSGHEADER_S *)pstAnnMsg, pstAddrInfo);
    
    i32Offset = TCPIP_SNPRINTF0(szBuf, LEN_512, P0("\r\nANNOUNCE INFO:"));    

    /* 打印announce消息的其他内容 */
    i32Offset += TCPIP_SNPRINTF(szBuf + i32Offset, LEN_512 - i32Offset, P8("\r\n    originTimestamp : Nano-%u,Low-%u,High-%u \r\n    utcoffset : %d\r\n    grandmasterPri1 : %u\r\n    grandmasterQuality : Accuracy-%u,class-%u,offset-%u ",
                              pstAnnMsg->stOriginTimestamp.ulNanoseconds,
                              pstAnnMsg->stOriginTimestamp.ulSecondsLow,
                              pstAnnMsg->stOriginTimestamp.usSecondsHigh,
                              VOS_NTOHS(pstAnnMsg->sCurrentUtcOffset),
                              pstAnnMsg->ucGrandmasterPriority1,
                              pstAnnMsg->stGrandmasterClockQuality.ucClockAccuracy,
                              pstAnnMsg->stGrandmasterClockQuality.ucClockClass,
                              VOS_NTOHS(pstAnnMsg->stGrandmasterClockQuality.usOffsetScaledLogVariance)));

    i32Offset += TCPIP_SNPRINTF(szBuf + i32Offset, LEN_512 - i32Offset, P11("\r\n    grandmasterPri2 : %u\r\n    grandmasterId : %02x%02x%02x%02x%02x%02x%02x%02x\r\n    stepsremoved : %u\r\n    timesource : %u",
                              pstAnnMsg->ucGrandmasterPriority2,
                              pstAnnMsg->stGrandmasterIdentity[0],
                              pstAnnMsg->stGrandmasterIdentity[1],
                              pstAnnMsg->stGrandmasterIdentity[2],
                              pstAnnMsg->stGrandmasterIdentity[3],
                              pstAnnMsg->stGrandmasterIdentity[4],
                              pstAnnMsg->stGrandmasterIdentity[5],
                              pstAnnMsg->stGrandmasterIdentity[6],
                              pstAnnMsg->stGrandmasterIdentity[7],
                              VOS_NTOHS(pstAnnMsg->usStepsRemoved),
                              pstAnnMsg->ucTimeSource));
    (VOID)TCPIP_SNPRINTF(szBuf + i32Offset, LEN_512 - i32Offset, P1("\r\n----------announce msg %s end------------",szInOrOut));

    TCPIP_InfoOutput(szBuf);
    
}
/*****************************************************************************
 函 数 名  : ChapBufferResponsePacket
 功能描述  : 备份收到的CHAP response packet
 输入参数  : chap - 链路中的CHAP记录信息
             ucHashSize - response中hash-size
             aucHashValue - response中hash-value
             lNameLen - response中name字段的长度, 单位: 字节
 输出参数  : 无
 返 回 值  : NULL
 调用函数  :
 被调函数  :
 说    明  : 备份response packet, 为了在IPCP阶段提供给NAS在PDP激活中使用

 修改历史      :
  1.日    期   : 2008年11月4日
    作    者   : liukai
    修改内容   : created

*****************************************************************************/
VOS_VOID ChapBufferResponsePacket(struct chap *chap, VOS_UCHAR ucHashSize,
                                  VOS_UCHAR aucHashValue[], VOS_INT32 lNameLen)
{
    VOS_UINT8 *pucResponseNextPos;    /* the start address to store response in buffer for next time */

    pucResponseNextPos = chap->RecordData.BufResponse;

    PS_MEM_CPY(pucResponseNextPos, &(chap->auth.in.hdr), sizeof(struct fsmheader));    /* record packet header */
    pucResponseNextPos += sizeof(struct fsmheader);

    *pucResponseNextPos = ucHashSize;
    pucResponseNextPos++;    /* hash-size always use one octet */

    if (ucHashSize != 0)    /* with hash-value */
    {
        PS_MEM_CPY(pucResponseNextPos, aucHashValue, ucHashSize);
        pucResponseNextPos += ucHashSize;
    }
    if (('\0' != *chap->auth.in.name) && (lNameLen > 0))    /* with name */
    {
        /*
            why do NOT use strcpy, as "The Name should not be NUL or CR/LF terminated."
            in RFC1994. However, rx-ed response packets of peer may use NUL as terminate,
            so use @lNameLen, not to use strlen to calculate itself.
        */
        PS_MEM_CPY(pucResponseNextPos, chap->auth.in.name, (VOS_UINT32)lNameLen);
    }
    else
    {
        *pucResponseNextPos = '\0';
    }

    chap->RecordData.LenOfResponse = VOS_NTOHS(chap->auth.in.hdr.length);

    return ;
}    /* ChapBufferResponsePacket */
/*****************************************************************************
 函 数 名  : chap_Input
 功能描述  : 收到CHAP帧的处理入口函数
 输入参数  : l - PPP链接
             pstMem - 收到的CHAP帧
 输出参数  : 无
 返 回 值  : NULL
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2008年10月24日
    作    者   : liukai
    修改内容   : porting from BSD

*****************************************************************************/
PPP_ZC_STRU *chap_Input(struct link *l, PPP_ZC_STRU *pstMem)
{
    struct chap *chap;
    VOS_INT32 len;
    VOS_UCHAR alen;    /* answer length: challenge or response body length */
    struct ppp_mbuf *bp;
    VOS_UCHAR aucHashValue[MD5DIGESTSIZE];

    bp = ppp_m_get_from_ttfmem(pstMem);
    PPP_MemFree(pstMem);

    if (VOS_NULL_PTR == bp)
    {
        return VOS_NULL_PTR;
    }

    if (VOS_NULL_PTR == l) {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "Chap Input: Not a physical link - dropped\r\n");
        ppp_m_freem(bp);
        return VOS_NULL_PTR;
    }

    if ((PHASE_NETWORK != l->phase) &&
            (PHASE_AUTHENTICATE != l->phase)) {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Unexpected Chap input - dropped\r\n");
        ppp_m_freem(bp);
        return VOS_NULL_PTR;
    }

    chap = &(l->chap);
    if ((VOS_NULL_PTR == (bp = auth_ReadHeader(&chap->auth, bp))) &&
            (0 == VOS_NTOHS(chap->auth.in.hdr.length)))
    {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "Chap Input: Truncated header\r\n");
    }
    else if ((0 == chap->auth.in.hdr.code) || ((VOS_UINT8)(chap->auth.in.hdr.code) > MAXCHAPCODE))
    {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                      "Chap Input: Bad CHAP code %d !\r\n", chap->auth.in.hdr.code);
    }
    else {
        len = ppp_m_length(bp);

        /* Identifier of rx-ed Response, Success, Fail should match Challenge tx-ed */
        if ((CHAP_CHALLENGE != chap->auth.in.hdr.code) &&
                (chap->auth.id != chap->auth.in.hdr.id)) {
            /* Wrong conversation dude ! */
            PPP_MNTN_LOG3(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL,
                          "Chap Input: code <1> dropped (got id <2> not equal to previous id <3>)\r\n",
                          chap->auth.in.hdr.code, chap->auth.in.hdr.id, chap->auth.id);
            ppp_m_freem(bp);
            return VOS_NULL_PTR;
        }
        chap->auth.id = chap->auth.in.hdr.id;    /* We respond with this id */

        if (CHAP_CHALLENGE == chap->auth.in.hdr.code)    /* rx-ed challenge */
        {
            bp = ppp_mbuf_Read(bp, &alen, 1);    /* fetch length of peer's challenge */
            len -= (alen + 1);    /* after this step, len is length of peer's name */
            if (len < 0) {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: Truncated challenge (len %d, alen %d)!\r\n", len, alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }
            if (AUTHLEN < len)
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: name of challenge too long (len %d, alen %d)!\r\n", len, alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }
            if (CHAPCHALLENGELEN < alen)
            {
                PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: challenge too long (len %d)!\r\n", alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }

            *chap->challenge.peer = alen;
            bp = ppp_mbuf_Read(bp, chap->challenge.peer + 1, alen);    /* record peer's challenge */
            bp = auth_ReadName(&chap->auth, bp, len);    /* record peer's name */

            if (*chap->auth.in.name)    /* challenge with name */
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: challenge (len %d, alen %d) with name\r\n",
                              len, alen);
            }
            else    /* without name */
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: challenge (len %d, alen %d) without name\r\n",
                              len, alen);
            }

            chap_Respond(l, "HUAWEI_CHAP_CLNT");    /* we always use "HUAWEI_CHAP_CLNT" as Name of Response */
        }    /* end of rx-ed challenge */
        else if (CHAP_RESPONSE == chap->auth.in.hdr.code)    /* rx-ed response */
        {
            bp = ppp_mbuf_Read(bp, &alen, 1);    /* read HASH-Size */
            if (MD5DIGESTSIZE != alen)    /* as just support MD5, must be 16 octets */
            {
                PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: Hash-Size %f is not correct !\r\n", alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }
            len -= (alen + 1);    /* after this step, len is length of Name Field */
            if (len < 0) {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: Truncated response (len %d, alen %d)!\r\n", len, alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }
            if (AUTHLEN < len)
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                              "Chap Input: name of response too long (len %d, alen %d)!\r\n", len, alen);
                ppp_m_freem(bp);
                return VOS_NULL_PTR;
            }

            bp = ppp_mbuf_Read(bp, aucHashValue, MD5DIGESTSIZE);    /* cut HASH value */
            bp = auth_ReadName(&chap->auth, bp, len);

            if (*chap->auth.in.name)
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL,"Chap Input: response (len <1>, alen <2>) with name\r\n",
                              len, alen);
            }
            else
            {
                PPP_MNTN_LOG2(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL,"Chap Input: response (len <1>, alen <2>) without name\r\n",
                              len, alen);
            }

            if (PHASE_AUTHENTICATE == l->phase)    /* 需要注意只备份在认证阶段中与challenge id匹配的response */
            {
                ChapBufferResponsePacket(chap, MD5DIGESTSIZE, aucHashValue, len);
            }

            chap_Success(l);

            /*
               Moves code to here as the last step of dealing with response by liukai,
               it should stop authentication timer after authentication pass or fail.
               Stops timer at first, a response frame format is not correct and discards it(way of BSD),
               UE has no chance to send challenge again
            */
            auth_StopTimer(&(chap->auth));
        }    /* end of rx-ed response */
        else if (CHAP_SUCCESS == chap->auth.in.hdr.code)    /* rx-ed success */
        {
            /* chap->auth.in.name is already set up at CHALLENGE time, need NOT to print again */
            if (0 < len)
            {
                PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Chap Input: success with message\r\n");
            }
            else
            {
                PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Chap Input: success without message\r\n");
            }

            if (PROTO_CHAP == l->lcp.auth_iwait) {
                l->lcp.auth_iwait = 0;
                if (0 == l->lcp.auth_ineed)    /* auth_ineed: 0, authentication by peer is not complete or no need to authentication,
                                                       !0, authentication by peer is complete */
                {
                    /*
                     * We've succeeded in our ``login''
                     * If we're not expecting  the peer to authenticate (or he already
                     * has), proceed to network phase.
                     */
                    chap_ReInit(&(l->chap));
                    if (PHASE_AUTHENTICATE == l->phase)
                    {
                        l->phase = PHASE_NETWORK;
                        l->ipcp.fsm.state = ST_CLOSED;
                        fsm_Open(&(l->ipcp.fsm));
                        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "goto ipcp stage!\r\n");
                    }
                }
            }
        }    /* end of rx-ed success */
        else    /* rx-ed fail */
        {
            /* chap->auth.in.name is already set up at CHALLENGE time, need NOT to print again */
            if (0 < len)
            {
                PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Chap Input: fail with message\r\n");
            }
            else
            {
                PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Chap Input: fail without message\r\n");
            }

            chap_Cleanup(&(l->chap));
            l->phase = PHASE_TERMINATE;
            fsm_Close(&(l->lcp.fsm));
            PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "goto lcp stage!\r\n");
        }    /* end of rx-ed fail */
    }

    ppp_m_freem(bp);
    return VOS_NULL_PTR;
}    /* chap_Input */
PPP_ZC_STRU *
pap_Input(/*struct bundle *bundle,*/ struct link *l, PPP_ZC_STRU *pstMem)
{
/*  struct physical *p = link2physical(l);*/
#if 0 /* delete for transplant */
  VOS_CHAR nlen, *key;
#endif

  struct authinfo *authp =/* &p->dl*/&(l->pap.auth);
  VOS_CHAR nlen;
  VOS_UINT8 klen;
  const VOS_CHAR *txt;
  VOS_INT32 txtlen;
  struct ppp_mbuf *bp;


  bp = ppp_m_get_from_ttfmem(pstMem);
  PPP_MemFree(pstMem);

  if (VOS_NULL_PTR == bp)
  {
    return VOS_NULL_PTR;
  }

  if (l == VOS_NULL_PTR) {
    PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "pap input, Not a physical link - dropped\r\n");
    ppp_m_freem(bp);
    return VOS_NULL_PTR;
  }

  if (/*bundle_Phase(bundle)*/ l->phase!= PHASE_NETWORK &&
      /*bundle_Phase(bundle)*/ l->phase!= PHASE_AUTHENTICATE) {
    PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Unexpected pap input - dropped\r\n");
    ppp_m_freem(bp);
    return VOS_NULL_PTR;
  }

  if ((bp = auth_ReadHeader(authp, bp)) == VOS_NULL_PTR &&
      VOS_NTOHS(authp->in.hdr.length) == 0) {
    PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "Pap Input: Truncated header\r\n");
    return VOS_NULL_PTR;
  }

  if (authp->in.hdr.code == 0 || authp->in.hdr.code > MAXPAPCODE) {
    PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                  "Bad PAP code: %d", authp->in.hdr.code);
    ppp_m_freem(bp);
    return VOS_NULL_PTR;
  }

  if (authp->in.hdr.code != PAP_REQUEST && authp->id != authp->in.hdr.id)
    {
    /* Wrong conversation dude ! */
    PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "pap input, dropped (got id not equal to previous id)\r\n");
    ppp_m_freem(bp);
    return VOS_NULL_PTR;
    }
  authp->id = authp->in.hdr.id;        /* We respond with this id */

  /*fanzhibin f49086 add it begin*/
  if (authp->in.hdr.code == PAP_REQUEST)
  {
    /*将config req报文头部拷贝到缓存中*/
    PS_MEM_CPY(l->pap.RecordData.BufRequest,&(authp->in.hdr),sizeof(authp->in.hdr));

    ppp_mbuf_View(bp,(l->pap.RecordData.BufRequest + sizeof(authp->in.hdr)),
                    VOS_NTOHS(authp->in.hdr.length) - sizeof(authp->in.hdr));
    l->pap.RecordData.LenOfRequest = VOS_NTOHS(authp->in.hdr.length);

  }
  /*fanzhibin f49086 add it end*/



  if (bp) {
    bp = ppp_mbuf_Read(bp, &nlen, 1);
    if (authp->in.hdr.code == PAP_ACK) {
      /*
       * Don't restrict the length of our acknowledgement freetext to
       * nlen (a one-byte length).  Show the rest of the ack packet
       * instead.  This isn't really part of the protocol.....
       */
      bp = ppp_m_pullup(bp);
      txt = PPP_MBUF_CTOP(bp);
      txtlen = ppp_m_length(bp);
    } else {
      bp = auth_ReadName(authp, bp, nlen);
      txt = authp->in.name;
      txtlen = VOS_StrNLen(authp->in.name,AUTHLEN);
      PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "username:"******"";
    txtlen = 0;
  }

  PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "\r\nPap Input\r\n");

  switch (authp->in.hdr.code) {
    case PAP_REQUEST:
      if (bp == VOS_NULL_PTR) {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Pap Input: No key given !\r\n");
        break;
      }
      bp = ppp_mbuf_Read(bp, &klen, 1);
      if (ppp_m_length(bp) < klen) {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "Pap Input: Truncated key !\r\n");
        break;
      }

#if 0/*fanzhibin f49086 delete it*/
      if ((key = VOS_MemAlloc(PS_PID_APP_PPP, DYNAMIC_DOPRA_MEM_PT,klen+1)) == VOS_NULL_PTR) {
        PS_LOG(PS_PID_APP_PPP, 0, PS_PRINT_ERROR, "Pap Input: Out of memory !\n");
        break;
      }
      bp = ppp_mbuf_Read(bp, key, klen);
      key[klen] = '\0';


#ifndef NORADIUS
      if (*bundle->radius.cfg.file) {
        if (!radius_Authenticate(&bundle->radius, authp, authp->in.name,
                                 key, strlen(key), VOS_NULL_PTR, 0))
          pap_Failure(authp);
      } else
#endif
/*下面这句在改造的时候要添进去*/
      if (auth_Validate(bundle, authp->in.name, key, p))
        pap_Success(authp);
      else
        pap_Failure(authp);

      VOS_MemFree(PS_PID_APP_PPP,key);
#endif

/*fanzhibin f49086 add it begin*/
      if (klen > sizeof l->pap.RecordData.password- 1)
      {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                      "auth_ReadPassword: PassWord too long,len= %d", klen);
      }
      else {
        if (klen > ppp_m_length(bp))
        {
          PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                        "auth_ReadPassword: Short packet, pass_len = %d", klen);
        }
        else {
          bp = ppp_mbuf_Read(bp, l->pap.RecordData.password, klen);
          l->pap.RecordData.password[klen] = '\0';
          PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "password:");
          PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, l->pap.RecordData.password);

        }
      }

      pap_Success(l);
/*fanzhibin f49086 add it end*/

      break;

    case PAP_ACK:
#if 0/*fanzhibin f49086 delete it*/
      auth_StopTimer(authp);
      if (p->link.lcp.auth_iwait == PROTO_PAP) {
        p->link.lcp.auth_iwait = 0;
        if (p->link.lcp.auth_ineed == 0)
          /*
           * We've succeeded in our ``login''
           * If we're not expecting  the peer to authenticate (or he already
           * has), proceed to network phase.
           */
          datalink_AuthOk(p->dl);
      }
#endif
      break;

    case PAP_NAK:

#if 0/*fanzhibin f49086 delete it*/
      auth_StopTimer(authp);
      datalink_AuthNotOk(p->dl);
#endif

      break;
  }

  ppp_m_freem(bp);
  return VOS_NULL_PTR;
}
/*******************************************************************************
*    Func Name: PTPV2_Ann_RcvMsg
* Date Created: 2014-03-14
*       Author: luogaowei & dutianyi61496
*  Description:
*        Input: UCHAR* pucBuffer:
*               ULONG ulPacketLen:
*               TCPIP_PTP_ADDRINFO_S* pstAddrInfo:
*               PTPV2_PORT_S *pstPortInfo:
*       Output:
*       Return:
*      Caution:
*------------------------------------------------------------------------------
*  Modification History
*  DATE         NAME                    DESCRIPTION
*  ----------------------------------------------------------------------------
*  2014-03-14   luogaowei & dutianyi61496  Create
*
*******************************************************************************/
ULONG PTPV2_Ann_RcvMsg (UCHAR* pucBuffer, ULONG ulPacketLen, 
                                  TCPIP_PTP_ADDRINFO_S* pstAddrInfo, PTPV2_PORT_S *pstPortInfo)
{
    ULONG ulRet = TCPIP_PTP_OK;
    PTPV2_ANNOUNCE_MSG_S* pstAnnMsg = NULL;
    PTPV2_FOREIGN_MASTER_S* pstSelectMaster = NULL;
    ULONG ulPtpV2ClockType = 0;

    VOS_DBGASSERT(NULL != pucBuffer);
    VOS_DBGASSERT(NULL != pstAddrInfo);

    /*全局报文统计*/
    g_stGlobalPtpV2PktStat.ulRcvAnnPackets ++;
    /*端口报文统计*/
    pstPortInfo->stPacketStat.ulRcvAnnPackets ++;

    pstAnnMsg = (PTPV2_ANNOUNCE_MSG_S*) pucBuffer;

    ulPtpV2ClockType = PTPV2_GetClockType();

    /*
      是否可以处理ann报文
      条件:1、端口必须有效   && 2、启动已经start &&  3、不能是OC master
    */
    if (NULL == pstPortInfo->pstSubPortInfo || PTPV2_NO == pstPortInfo->pstSubPortInfo->ucWorkState
        || (PTPV2_CLOCK_TYPE_OC == ulPtpV2ClockType
            && TCPIP_PTP_PORT_ROLE_MASTER == pstPortInfo->pstSubPortInfo->ucPtpPortRole))
    {
        ulRet =  TCPIP_PTP_ERR_NO_START;

        goto EXIT_LABEL;
    }

    /*模式是否匹配*/
    ulRet =  PTPV2_PktWithCastModeMatch(pstPortInfo, pstAddrInfo);
    if (TCPIP_PTP_OK != ulRet)
    {
        goto EXIT_LABEL;
    }
        
    /*announce报文的正确性检查*/
    ulRet = PTPV2_PktHeaderCheck(pstPortInfo,
                               pucBuffer,
                               TCPIP_PTP_MSG_ANNOUNCE,
                               ulPacketLen,
                               pstAddrInfo);
    if (TCPIP_PTP_OK != ulRet)
    {
        goto EXIT_LABEL;
    }

    /*If the stepsRemoved field of S is 255 or greater, S shall not be qualified.*/
    if (PTPV2_MAX_STEPSREMOVED <= VOS_NTOHS(pstAnnMsg->usStepsRemoved))
    {
        ulRet = TCPIP_PTP_ERR_STEPSREMOVED;
        goto EXIT_LABEL;
    }

    ulRet = PTPV2_GrandMasterIDCheck(pstAnnMsg);
    if (TCPIP_PTP_OK != ulRet)
    {
        goto EXIT_LABEL;
    }

    /*BMC 预处理:添加新的时钟源或者更新旧的*/ /*创建forgein  matser*/
    ulRet = PTPV2_BMCPreProcess(pstPortInfo, pstAnnMsg, pstAddrInfo);
    if (TCPIP_PTP_OK != ulRet)
    {
        goto EXIT_LABEL;
    }

    /*选源处理*/
    (VOID)PTPV2_BMCProcess(&pstSelectMaster);

    /*选源后处理,更新参数*/
    (VOID)PTPV2_BMCNotify(pstSelectMaster);

EXIT_LABEL:
    if (TCPIP_PTP_OK != ulRet)
    {
        /*丢包并统计*/
        g_stGlobalPtpV2PktStat.ulRcvErrorForeMasterPackets ++;
        pstPortInfo->stPacketStat.ulRcvErrorForeMasterPackets ++;
    }

    return ulRet;
}