void
SendPapCode(struct link *l, VOS_CHAR code, VOS_CHAR *message)
{
  struct fsmheader lh;
  struct ppp_mbuf *bp;
  VOS_CHAR *cp;
  VOS_UINT32 plen, mlen;


  lh.code = code;
  lh.id = l->pap.auth.id;
  mlen = VOS_StrNLen(message,20);
  plen = mlen + 1;
  lh.length = (VOS_UINT16)VOS_HTONS(plen + sizeof(struct fsmheader));
  bp = ppp_m_get(plen + PPP_RECIEVE_RESERVE_FOR_HEAD + PPP_RECIEVE_RESERVE_FOR_TAIL + sizeof(struct fsmheader));

  if(bp == VOS_NULL)
  {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "no mbuf");
    return;
  }
    /*预留头部*/
    bp->m_offset = PPP_RECIEVE_RESERVE_FOR_HEAD;

    /*头部与尾部都留出来了*/
    bp->m_len = plen + sizeof(struct fsmheader);

  PS_MEM_CPY(PPP_MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
  cp = PPP_MBUF_CTOP(bp) + sizeof(struct fsmheader);
  /*
   * If our message is longer than 255 bytes, truncate the length to
   * 255 and send the entire message anyway.  Maybe the other end will
   * display it... (see pap_Input() !)
   */
  *cp++ = (VOS_CHAR)(mlen > 255 ? 255 : mlen);
  PS_MEM_CPY(cp, message, mlen);
  PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Pap Output\r\n");

  link_PushPacket(l, bp,/* authp->physical->dl->bundle,*/
                  LINK_QUEUES(l) - 1, PROTO_PAP);
}
/*****************************************************************************
 函 数 名  : ChapBufferChallengePacket
 功能描述  : 备份CHAP challenge packet
 输入参数  : chap - 链路中的CHAP记录信息
             id - 待填写到头部的Identifier值
             ptr - 待备份的CHAP challenge body数据
             count - 待备份的CHAP challenge body数据的长度, 单位: 字节
 输出参数  : 无
 返 回 值  : NULL
 调用函数  :
 被调函数  :
 说    明  : 备份challenge packet, 为了在IPCP阶段提供给NAS在PDP激活中使用

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

*****************************************************************************/
VOS_VOID ChapBufferChallengePacket(struct chap *chap, VOS_CHAR id,
                                   const VOS_UCHAR *ptr, VOS_UINT32 count)
{
    VOS_UINT32 len;    /* length of a CHAP frame */
    struct fsmheader lh;
    VOS_UINT8 *pucChallengeBuf;

    len = sizeof(struct fsmheader) + count;
    lh.code = CHAP_CHALLENGE;
    lh.id = id;
    lh.length = (VOS_UINT16)VOS_HTONS(len);

    pucChallengeBuf = chap->RecordData.BufChallenge;
    PS_MEM_CPY(pucChallengeBuf, &lh, sizeof(struct fsmheader));
    if (count > 0)
    {
        PS_MEM_CPY(pucChallengeBuf + sizeof(struct fsmheader), ptr, count);
    }
    chap->RecordData.LenOfChallenge = (VOS_UINT16)len;

    return;
}    /* ChapBufferChallengePacket */
/*****************************************************************************
 函 数 名  : ChapOutput
 功能描述  : 构造CHAP帧并发送
 输入参数  : l - PPP链接
             code - 待填写到头部的Code值
             id - 待填写到头部的Identifier值
             ptr - 待填写的CHAP数据
             count - 待填写的CHAP数据的长度, 单位: 字节
             text - 字符串, 用于日志
 输出参数  : 无
 返 回 值  : NULL
 调用函数  :
 被调函数  :
 说    明  : 不对ptr与code进行组合检查, 如code为某值时, ptr不应为空等等,
             因为此函数为一通用函数, 支持生成所有的CHAP帧, 并能扩展为支持
             MS-CHAP帧等, 各种code, ptr组合情况众多, 一切相关检查交由外部
             调用者来完成

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

*****************************************************************************/
VOS_VOID ChapOutput(struct link *l, VOS_INT32 code, VOS_CHAR id,
                    const VOS_UCHAR *ptr, VOS_UINT32 count, const VOS_CHAR *text)
{
    VOS_UINT32 len;    /* length of a CHAP frame */
    struct fsmheader lh;
    struct ppp_mbuf *bp;

    len = sizeof(struct fsmheader) + count;
    lh.code = (VOS_CHAR)code;
    lh.id = id;
    lh.length = (VOS_UINT16)VOS_HTONS(len);
    bp = ppp_m_get((VOS_INT32)len);

    if (VOS_NULL_PTR == bp)
    {
        PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING, "no mbuf\r\n");
        return;
    }

    PS_MEM_CPY(PPP_MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
    if ((count > 0) && (VOS_NULL_PTR != ptr))
    {
        PS_MEM_CPY(PPP_MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);
    }

    if (VOS_NULL_PTR == text)
    {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "Chap Output: code %d\r\n", code);
    }
    else
    {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL,"Chap Output: code %d with text\r\n", code);
    }

    /* now a CHAP frame is ready */
    link_PushPacket(l, bp, LINK_QUEUES(l) - 1, PROTO_CHAP);

    return;
}    /* ChapOutput */
ULONG PTPV2_OC_MasterBuildAnnPkt(VOID* pThis, VOID** ppData)
{
    ULONG ulRet = TCPIP_PTP_OK;
    USHORT usAnnPktLen = LEN_64;
    PTPV2_PORT_S* pstPtpPort = NULL;
    MBUF_S* pstSndBuf = NULL;
    PTPV2_ANNOUNCE_MSG_S* pstAnnMsg = NULL;

    pstPtpPort = (PTPV2_PORT_S*)pThis;
    VOS_DBGASSERT(NULL != pstPtpPort);
 
    /*OC master要自行构造announce报文*/
    pstSndBuf = (MBUF_S*)MBUF_CreateForControlPacket(LEN_128, sizeof(PTPV2_ANNOUNCE_MSG_S),
                MBUF_TYPE_DATA, PTPV2_MID);
    if (NULL == pstSndBuf)
    {
        TCPIP_LOG_FIXLEN(RUN_LOG_VISP_2818, TCPIP_LOG_LEVEL_INFO, LOG_TYPE_CFG,
                "TCPIP PTPV2 LOG: PTPV2_OC_MasterBuildAnnPkt!\r\n",
                0, 0, 0, 0);
        return TCPIP_PTP_ERR;
    }

    pstAnnMsg = MBUF_MTOD(pstSndBuf, PTPV2_ANNOUNCE_MSG_S*);

    (VOID)TCPIP_Mem_Set((CHAR *)pstAnnMsg, 0, sizeof(PTPV2_ANNOUNCE_MSG_S)); 

    ulRet = PTPV2_BuildAnnPktHeader(pstPtpPort, &(pstAnnMsg->stMsgHeader));
    if (TCPIP_PTP_OK != ulRet)
    {
        /*报文统计*/
        g_stGlobalPtpV2PktStat.ulSndBuildDropPackets ++;
        pstPtpPort->stPacketStat.ulSndBuildDropPackets ++;
        
        TCPIP_LOG_FIXLEN(RUN_LOG_VISP_2819, TCPIP_LOG_LEVEL_INFO, LOG_TYPE_CFG,
                "TCPIP PTPV2 LOG: PTPV2_OC_MasterBuildAnnPkt fail to build ann header! Ret = %u!\r\n",
                ulRet, 0, 0, 0);
        /*丢包*/
        MBUF_Destroy(pstSndBuf);
        return ulRet;
    }

    pstAnnMsg->stMsgHeader.usmessageLength = VOS_HTONS(usAnnPktLen);

    if (BOOL_TRUE == g_pstPtpGlobalInfo->stCfgDefaultDs.bCurrentUtcOffsetValid)
    {
        pstAnnMsg->sCurrentUtcOffset = VOS_HTONS(g_pstPtpGlobalInfo->stCfgDefaultDs.sCurrentUtcOffset);
    }
    else
    {
        pstAnnMsg->sCurrentUtcOffset = 0; /*utc 无效,则值为0*/
    }

    pstAnnMsg->ucGrandmasterPriority1 = g_pstPtpGlobalInfo->stCfgDefaultDs.ucPriority1;
    pstAnnMsg->ucGrandmasterPriority2 = g_pstPtpGlobalInfo->stCfgDefaultDs.ucPriority2;
    /*时钟质量以本端配置为准*/
    (VOID)PTPV2_BuildAnnPktClockQa(pstAnnMsg,&(g_pstPtpGlobalInfo->stCfgDefaultDs.stCfgClockQa));

    (VOID)TCPIP_Mem_Copy((VOID*)(pstAnnMsg->stGrandmasterIdentity), TCPIP_PTP_CLOCK_ID_LEN,(VOID*)(g_pstPtpGlobalInfo->szClockId), TCPIP_PTP_CLOCK_ID_LEN);
    pstAnnMsg->usStepsRemoved = VOS_HTONS(g_pstPtpGlobalInfo->usStepsRemoved);
    pstAnnMsg->ucTimeSource =  g_pstPtpGlobalInfo->ucTimeSource;

    *ppData = pstSndBuf;
    return ulRet;
}
ULONG PTPV2_BC_MasterBuildAnnPkt(VOID* pThis, VOID** ppData)
{
    ULONG ulRet = TCPIP_PTP_OK;
    USHORT usAnnPktLen = LEN_64;
    PTPV2_PORT_S* pstPtpPort = NULL;
    MBUF_S* pstSndBuf = NULL;
    PTPV2_ANNOUNCE_MSG_S* pstAnnMsg = NULL;
    PTPV2_FOREIGN_MASTER_S *pstVirutalD0 = g_pstVirtualD0;

    pstPtpPort = (PTPV2_PORT_S*)pThis;
    VOS_DBGASSERT(NULL != pstPtpPort);

    /*只允许端口为MASTER角色可发报文,AR-IP-PTP.002*/
    if (pstPtpPort->pstSubPortInfo->ucPtpPortRole != TCPIP_PTP_PORT_ROLE_MASTER)
    {        
        return TCPIP_PTP_ERR;
    }    

    /*构造announce报文*/
    pstSndBuf = (MBUF_S*)MBUF_CreateForControlPacket(LEN_128, sizeof(PTPV2_ANNOUNCE_MSG_S),
                MBUF_TYPE_DATA, PTPV2_MID);
    if (NULL == pstSndBuf)
    {
        TCPIP_LOG_FIXLEN(RUN_LOG_VISP_2816, TCPIP_LOG_LEVEL_INFO, LOG_TYPE_CFG,
                "TCPIP PTPV2 LOG: PTPV2_BC_MasterBuildAnnPkt fail to create mbuf!\r\n",
                0, 0, 0, 0);
        
        return TCPIP_PTP_ERR;
    }

    pstAnnMsg = MBUF_MTOD(pstSndBuf, PTPV2_ANNOUNCE_MSG_S*);

    (VOID)TCPIP_Mem_Set((CHAR *)pstAnnMsg, 0, sizeof(PTPV2_ANNOUNCE_MSG_S)); 

    ulRet = PTPV2_BuildAnnPktHeader(pstPtpPort, &(pstAnnMsg->stMsgHeader));
    if (TCPIP_PTP_OK != ulRet)
    {
        /*报文统计*/
        g_stGlobalPtpV2PktStat.ulSndBuildDropPackets ++;
        pstPtpPort->stPacketStat.ulSndBuildDropPackets ++;
        
        TCPIP_LOG_FIXLEN(RUN_LOG_VISP_2817, TCPIP_LOG_LEVEL_INFO, LOG_TYPE_CFG,
                "TCPIP PTPV2 LOG: PTPV2_BC_MasterBuildAnnPkt fail to build ann header! Ret = %u!\r\n",
                ulRet, 0, 0, 0);
        MBUF_Destroy(pstSndBuf);
        return ulRet;
    }

    pstAnnMsg->stMsgHeader.usmessageLength = VOS_HTONS(usAnnPktLen);

    /*存在源Ebest时,utc/优先级/stepRemoved/timesource/GMid都从源获取,否则从VirtualD0获取*/
    if (PTPV2_YES == PTPV2_HaveParent())
    {
        pstAnnMsg->sCurrentUtcOffset = VOS_HTONS(g_pstPtpGlobalInfo->stParentDs.sCurrentUtcOffset);
        pstAnnMsg->ucGrandmasterPriority1 = g_pstPtpGlobalInfo->stParentDs.ucGrandmasterPriority1;
        pstAnnMsg->ucGrandmasterPriority2 = g_pstPtpGlobalInfo->stParentDs.ucGrandmasterPriority2;
        pstAnnMsg->usStepsRemoved = VOS_HTONS(g_pstPtpGlobalInfo->stParentDs.usStepsRemoved + 1);
        pstAnnMsg->ucTimeSource = g_pstPtpGlobalInfo->stParentDs.ucTimeSource;
        (VOID)TCPIP_Mem_Copy((VOID*)(pstAnnMsg->stGrandmasterIdentity), TCPIP_PTP_CLOCK_ID_LEN,
                           (VOID*)(g_pstPtpGlobalInfo->stParentDs.szGrandMasterId), TCPIP_PTP_CLOCK_ID_LEN);

        if (0xFE != g_pstPtpGlobalInfo->stCfgDefaultDs.stCfgClockQa.ucClockAccuracy)
        {   
            /*选到源,且有配置到visp,则取本地配置的时钟质量*/
            (VOID)PTPV2_BuildAnnPktClockQa(pstAnnMsg,&(g_pstPtpGlobalInfo->stCfgDefaultDs.stCfgClockQa));
        }
        else
        {
            /*选到源,没有配置到visp,则取选源的时钟质量*/
            (VOID)PTPV2_BuildAnnPktClockQa(pstAnnMsg,&(g_pstPtpGlobalInfo->stParentDs.stParentClockQA));
        }
    }
    else if (NULL != pstVirutalD0)
    {
        /*没有选到源,按D0值构包*/
        pstAnnMsg->sCurrentUtcOffset = VOS_HTONS(pstVirutalD0->sCurrentUtcOffset);
        pstAnnMsg->ucGrandmasterPriority1 = pstVirutalD0->ucGrandmasterPriority1;
        pstAnnMsg->ucGrandmasterPriority2 = pstVirutalD0->ucGrandmasterPriority2;
        pstAnnMsg->usStepsRemoved = VOS_HTONS(pstVirutalD0->usStepsRemoved + 1);
        pstAnnMsg->ucTimeSource = pstVirutalD0->ucTimeSource;
        (VOID)TCPIP_Mem_Copy((VOID*)(pstAnnMsg->stGrandmasterIdentity), TCPIP_PTP_CLOCK_ID_LEN,
                           (VOID*)&(pstVirutalD0->szForeignMasterPortId), TCPIP_PTP_CLOCK_ID_LEN);

        /*没有选到源,或者选到源却没有配置到visp,则取D0的时钟质量*/
        (VOID)PTPV2_BuildAnnPktClockQa(pstAnnMsg,&(pstVirutalD0->stGrandmasterClockQuality));
    }

    *ppData = pstSndBuf;
    return ulRet;

}