/*fanzhibin f49086 add it end*/
#if(FEATURE_ON == FEATURE_PPP)

static const VOS_CHAR * const papcodes[] = {
  "???", "REQUEST", "SUCCESS", "FAILURE"
};
#define MAXPAPCODE (sizeof papcodes / sizeof papcodes[0] - 1)


#if 0/*fanzhibin f49086 delete it*/
static void
pap_Req(struct authinfo *authp)
{
  struct bundle *bundle = authp->physical->dl->bundle;
  struct fsmheader lh;
  struct ppp_mbuf *bp;
  VOS_CHAR *cp;
  VOS_INT32 namelen, keylen, plen;

  namelen = strlen(bundle->cfg.auth.name);
  keylen = strlen(bundle->cfg.auth.key);
  plen = namelen + keylen + 2;
  PS_LOG(PS_PID_APP_PPP, 0, PS_PRINT_NORMAL, "pap_Req: namelen = %d, keylen = %d\n", namelen, keylen);
  log_Printf(LogPHASE, "Pap Output: %s ********\n", bundle->cfg.auth.name);
  if (*bundle->cfg.auth.name == '\0')
    log_Printf(LogWARN, "Sending empty PAP authname!\n");
  lh.code = PAP_REQUEST;
  lh.id = authp->id;
  lh.length = htons(plen + sizeof(struct fsmheader));
  bp = ppp_m_get(plen + sizeof(struct fsmheader));
  PS_MEM_CPY(PPP_MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));
  cp = PPP_MBUF_CTOP(bp) + sizeof(struct fsmheader);
  *cp++ = namelen;
  PS_MEM_CPY(cp, bundle->cfg.auth.name, namelen);
  cp += namelen;
  *cp++ = keylen;
  PS_MEM_CPY(cp, bundle->cfg.auth.key, keylen);
  link_PushPacket(&authp->physical->link, bp,/* bundle,*/
                  LINK_QUEUES(&authp->physical->link) - 1, PROTO_PAP);
}
struct ppp_mbuf *
ppp_m_pullup(struct ppp_mbuf *bp)
{
  /* Put it all in one contigous (aligned) ppp_mbuf */

  if (bp != VOS_NULL_PTR) {
    if (bp->m_next != VOS_NULL_PTR) {
      struct ppp_mbuf *nbp;
      VOS_CHAR *cp;

      nbp = ppp_m_get(ppp_m_length(bp));
      if(nbp == VOS_NULL)
        return bp;

      for (cp = PPP_MBUF_CTOP(nbp); bp; bp = ppp_m_free(bp)) {
        PS_MEM_CPY(cp, PPP_MBUF_CTOP(bp), bp->m_len);
        cp += bp->m_len;
      }
      bp = nbp;
    }
#ifndef __i386__    /* Do any other archs not care about alignment ? */
    else if ((bp->m_offset & (sizeof(long) - 1)) != 0) {

/*fanzhibin f49086 change it begin*/
/*函数修改了,参数换了位置*/
      PS_MEM_CPY(bp + 1, PPP_MBUF_CTOP(bp), bp->m_len);
/*fanzhibin f49086 change it end*/

      bp->m_offset = 0;
    }
#endif
  }

  return bp;
}
struct ppp_mbuf *
ppp_m_prepend(struct ppp_mbuf *bp, const void *ptr, VOS_INT32 len, VOS_INT32 extra)
{
  struct ppp_mbuf *head;

  if (bp && bp->m_offset) {
    if (bp->m_offset >= len) {
      bp->m_offset -= (VOS_INT16)len;
      bp->m_len += len;
      PS_MEM_CPY(PPP_MBUF_CTOP(bp), ptr, len);
      return bp;
    }
    len -= bp->m_offset;
    PS_MEM_CPY(bp + 1, (const VOS_CHAR *)ptr + len, bp->m_offset);
    bp->m_len += bp->m_offset;
    bp->m_offset = 0;
  }

  head = ppp_m_get(len + extra);

  if(head != VOS_NULL)
  {

      head->m_offset = (VOS_INT16)extra;
      head->m_len -= extra;
      if (ptr)
        PS_MEM_CPY(PPP_MBUF_CTOP(head), ptr, len);
      head->m_next = bp;
      return head;

  }

  PPP_MNTN_LOG(PS_PID_APP_PPP, 0, PS_PRINT_WARNING,"Failed to ppp_m_prepend\r\n");
  return bp;
}
struct ppp_mbuf *
ppp_m_getm(VOS_INT32 m_len)
{
    struct ppp_mbuf    *pRtn;
    struct ppp_mbuf   **ppCurrMem;
    VOS_INT32           lCurrLen;


    if (m_len <= 0)
    {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                      "Request for ppp_mbuf denied,m_len %d", m_len);
        return VOS_NULL_PTR;
    }

    if (m_len > (VOS_INT32)M_MAXLEN)
    {
        PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                      "Request for ppp_mbuf too long, m_len %d", m_len);
    }

    pRtn        = VOS_NULL_PTR;
    ppCurrMem   = &pRtn;

    while(m_len > 0)
    {
        lCurrLen    = (m_len < (VOS_INT32)M_MAXLEN) ? m_len : (VOS_INT32)M_MAXLEN;
        m_len      -= lCurrLen;

        *ppCurrMem  = ppp_m_get(lCurrLen);

        if (VOS_NULL_PTR == *ppCurrMem)
        {
            PPP_MNTN_LOG1(PS_PID_APP_PPP, 0, LOG_LEVEL_WARNING,
                          "Request for ppp_mbuf denied,ulCurrLen %d", lCurrLen);
            break;
        }

        /* 取当前Mem的下个节点地址,为下一次申请的内存挂接上 */
        ppCurrMem   = &((*ppCurrMem)->m_next);
    }

    return pRtn;
}
struct ppp_mbuf *
ppp_m_get_from_ttfmem(PPP_ZC_STRU *pstMem)
{
    VOS_UINT16          usLen;
    struct ppp_mbuf    *bp;
    PPP_ZC_STRU        *pstCurrMem;
    VOS_CHAR           *pcMbufData;


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


    usLen   = PPP_ZC_GET_DATA_LEN(pstMem);

    bp      = ppp_m_get(usLen);

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

    pstCurrMem  = pstMem;
    pcMbufData  = PPP_MBUF_CTOP(bp);

    /* 目前的零拷贝暂不支持链式 */
    /*
    while (VOS_NULL_PTR != pstCurrMem)
    {
    */
        PS_MEM_CPY(pcMbufData, PPP_ZC_GET_DATA_PTR(pstCurrMem), PPP_ZC_GET_DATA_LEN(pstCurrMem));

        pcMbufData += PPP_ZC_GET_DATA_LEN(pstCurrMem);
    /*
        pstCurrMem  = pstCurrMem->pNext;
    }
    */

    return bp;
}
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);
}
/*****************************************************************************
 函 数 名  : 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 */