⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppp.c

📁 STM32F107_ETH_LwIP_V1.0.0.rar
💻 C
📖 第 1 页 / 共 4 页
字号:
 * an error code (negative) on failure. */
int
pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
  PPPControl *pc;
  int pd;

  /* Find a free PPP session descriptor. Critical region? */
  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);

  if (pd >= NUM_PPP) {
    pd = PPPERR_OPEN;
  } else {
    pppControl[pd].openFlag = !0;
  }

  /* Launch a deamon thread. */
  if (pd >= 0) {
    pppControl[pd].openFlag = 1;

    lcp_init(pd);
    pc = &pppControl[pd];
    pc->fd = fd;
#if PPPOE_SUPPORT
    pc->ethif= NULL;
#endif /* PPPOE_SUPPORT */
    pc->kill_link = 0;
    pc->sig_hup = 0;
    pc->if_up = 0;
    pc->errCode = 0;
    pc->inState = PDIDLE;
    pc->inHead = NULL;
    pc->inTail = NULL;
    pc->inEscaped = 0;
    pc->lastXMit = 0;

#if VJ_SUPPORT
    pc->vjEnabled = 0;
    vj_compress_init(&pc->vjComp);
#endif /* VJ_SUPPORT */

    /* 
     * Default the in and out accm so that escape and flag characters
     * are always escaped. 
     */
    memset(pc->inACCM, 0, sizeof(ext_accm));
    pc->inACCM[15] = 0x60;
    memset(pc->outACCM, 0, sizeof(ext_accm));
    pc->outACCM[15] = 0x60;

    pc->linkStatusCB = linkStatusCB;
    pc->linkStatusCtx = linkStatusCtx;

    sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
    if(!linkStatusCB) {
      while(pd >= 0 && !pc->if_up) {
        sys_msleep(500);
        if (lcp_phase[pd] == PHASE_DEAD) {
          pppClose(pd);
          if (pc->errCode) {
            pd = pc->errCode;
          } else {
            pd = PPPERR_CONNECT;
          }
        }
      }
    }
  }

  return pd;
}
#endif /* PPPOS_SUPPORT */

#if PPPOE_SUPPORT
static void pppOverEthernetLinkStatusCB(int pd, int up);

void
pppOverEthernetClose(int pd)
{
  PPPControl* pc = &pppControl[pd];

  /* *TJL* There's no lcp_deinit */
  lcp_close(pd, NULL);

  pppoe_destroy(&pc->netif);
}

int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
{
  PPPControl *pc;
  int pd;

  LWIP_UNUSED_ARG(service_name);
  LWIP_UNUSED_ARG(concentrator_name);

  /* Find a free PPP session descriptor. Critical region? */
  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
  if (pd >= NUM_PPP) {
    pd = PPPERR_OPEN;
  } else {
    pppControl[pd].openFlag = !0;
  }

  /* Launch a deamon thread. */
  if (pd >= 0) {

    pppControl[pd].openFlag = 1;

    lcp_init(pd);

    lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
    lcp_wantoptions[pd].neg_asyncmap = 0;
    lcp_wantoptions[pd].neg_pcompression = 0;
    lcp_wantoptions[pd].neg_accompression = 0;

    lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
    lcp_allowoptions[pd].neg_asyncmap = 0;
    lcp_allowoptions[pd].neg_pcompression = 0;
    lcp_allowoptions[pd].neg_accompression = 0;

    pc = &pppControl[pd];
    pc->if_up = 0;
    pc->errCode = 0;
    pc->lastXMit = 0;
#if PPPOS_SUPPORT
    pc->kill_link = 0;
    pc->sig_hup = 0;
    pc->inState = PDIDLE;
    pc->inHead = NULL;
    pc->inTail = NULL;
    pc->inEscaped = 0;
#if VJ_SUPPORT
    pc->vjEnabled = 0;
#endif /* VJ_SUPPORT */
#endif /* PPPOS_SUPPORT */
    pc->ethif= ethif;

    memset(pc->inACCM,  0, sizeof(ext_accm));
    memset(pc->outACCM, 0, sizeof(ext_accm));

    pc->linkStatusCB  = linkStatusCB;
    pc->linkStatusCtx = linkStatusCtx;

    if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
      pc->openFlag = 0;
      return PPPERR_OPEN;
    }

    pppoe_connect(pc->pppoe_sc);

    if(!linkStatusCB) {
      while(pd >= 0 && !pc->if_up) {
        sys_msleep(500);
        if (lcp_phase[pd] == PHASE_DEAD) {
          pppClose(pd);
          if (pc->errCode) {
            pd = pc->errCode;
          } else {
            pd = PPPERR_CONNECT;
          }
        }
      }
    }
  }

  return pd;
}
#endif /* PPPOE_SUPPORT */


/* Close a PPP connection and release the descriptor. 
 * Any outstanding packets in the queues are dropped.
 * Return 0 on success, an error code on failure. */
int
pppClose(int pd)
{
  PPPControl *pc = &pppControl[pd];
  int st = 0;

  /* Disconnect */
#if PPPOE_SUPPORT
  if(pc->ethif) {
    PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd));
    pc->errCode = PPPERR_USER;
    /* This will leave us at PHASE_DEAD. */
    tcpip_callback(pppStopCB, (void*)pd);
  } else
#endif /* PPPOE_SUPPORT */
  {
#if PPPOS_SUPPORT
    pc->kill_link = !0;
    pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
  }

  if(!pc->linkStatusCB) {
    while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
      sys_msleep(500);
      break;
    }
  }

  return st;
}

/* This function is called when carrier is lost on the PPP channel. */
void
pppSigHUP(int pd)
{
  PPPControl *pc = &pppControl[pd];

#if PPPOE_SUPPORT
  if(pc->ethif) {
    PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
    tcpip_callback(pppHupCB, (void*)pd);
  } else
#endif /* PPPOE_SUPPORT */
  {
#if PPPOS_SUPPORT
    pc->sig_hup = 1;
    pppMainWakeup(pd);
#endif /* PPPOS_SUPPORT */
  }
}

#if PPPOS_SUPPORT
static void
nPut(PPPControl *pc, struct pbuf *nb)
{
  struct pbuf *b;
  int c;

  for(b = nb; b != NULL; b = b->next) {
    if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
      PPPDEBUG((LOG_WARNING,
               "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
      LINK_STATS_INC(link.err);
      pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
      break;
    }
  }

  pbuf_free(nb);
  LINK_STATS_INC(link.xmit);
}

/* 
 * pppAppend - append given character to end of given pbuf.  If outACCM
 * is not NULL and the character needs to be escaped, do so.
 * If pbuf is full, append another.
 * Return the current pbuf.
 */
static struct pbuf *
pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
{
  struct pbuf *tb = nb;
  
  /* Make sure there is room for the character and an escape code.
   * Sure we don't quite fill the buffer if the character doesn't
   * get escaped but is one character worth complicating this? */
  /* Note: We assume no packet header. */
  if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
    tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
    if (tb) {
      nb->next = tb;
    } else {
      LINK_STATS_INC(link.memerr);
    }
    nb = tb;
  }

  if (nb) {
    if (outACCM && ESCAPE_P(*outACCM, c)) {
      *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
      *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
    } else {
      *((u_char*)nb->payload + nb->len++) = c;
    }
  }

  return tb;
}
#endif /* PPPOS_SUPPORT */

#if PPPOE_SUPPORT
static err_t
pppifOutputOverEthernet(int pd, struct pbuf *p)
{
  PPPControl *pc = &pppControl[pd];
  struct pbuf *pb;
  u_short protocol = PPP_IP;
  int i=0;

  pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM);
  if(!pb) {
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.proterr);
    return ERR_MEM;
  }

  pbuf_header(pb, -pppoe_hdrlen);

  pc->lastXMit = sys_jiffies();

  if (!pc->pcomp || protocol > 0xFF) {
    *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
  }
  *((u_char*)pb->payload + i) = protocol & 0xFF;

  pbuf_chain(pb, p);

  if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
    LINK_STATS_INC(link.err);
    return PPPERR_DEVICE;
  }

  LINK_STATS_INC(link.xmit);
  return ERR_OK;
}
#endif /* PPPOE_SUPPORT */

/* Send a packet on the given connection. */
static err_t
pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
{
  int pd = (int)netif->state;
  u_short protocol = PPP_IP;
  PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
  u_int fcsOut = PPP_INITFCS;
  struct pbuf *headMB = NULL, *tailMB = NULL, *p;
  u_char c;
#endif /* PPPOS_SUPPORT */

  LWIP_UNUSED_ARG(ipaddr);

  /* Validate parameters. */
  /* We let any protocol value go through - it can't hurt us
   * and the peer will just drop it if it's not accepting it. */
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
    PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
              pd, protocol, pb));
    LINK_STATS_INC(link.opterr);
    LINK_STATS_INC(link.drop);
    return ERR_ARG;
  }

  /* Check that the link is up. */
  if (lcp_phase[pd] == PHASE_DEAD) {
    PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
    LINK_STATS_INC(link.rterr);
    LINK_STATS_INC(link.drop);
    return ERR_RTE;
  }

#if PPPOE_SUPPORT
  if(pc->ethif) {
    return pppifOutputOverEthernet(pd, pb);
  }
#endif /* PPPOE_SUPPORT */

#if PPPOS_SUPPORT
  /* Grab an output buffer. */
  headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
  if (headMB == NULL) {
    PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    return ERR_MEM;
  }

#if VJ_SUPPORT
  /* 
   * Attempt Van Jacobson header compression if VJ is configured and
   * this is an IP packet. 
   */
  if (protocol == PPP_IP && pc->vjEnabled) {
    switch (vj_compress_tcp(&pc->vjComp, pb)) {
      case TYPE_IP:
        /* No change...
           protocol = PPP_IP_PROTOCOL; */
        break;
      case TYPE_COMPRESSED_TCP:
        protocol = PPP_VJC_COMP;
        break;
      case TYPE_UNCOMPRESSED_TCP:
        protocol = PPP_VJC_UNCOMP;
        break;
      default:
        PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
        LINK_STATS_INC(link.proterr);
        LINK_STATS_INC(link.drop);
        pbuf_free(headMB);
        return ERR_VAL;
    }
  }
#endif /* VJ_SUPPORT */

  tailMB = headMB;

  /* Build the PPP header. */
  if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
    tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
  }

  pc->lastXMit = sys_jiffies();
  if (!pc->accomp) {
    fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
    tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
    fcsOut = PPP_FCS(fcsOut, PPP_UI);
    tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
  }
  if (!pc->pcomp || protocol > 0xFF) {
    c = (protocol >> 8) & 0xFF;
    fcsOut = PPP_FCS(fcsOut, c);
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
  }
  c = protocol & 0xFF;
  fcsOut = PPP_FCS(fcsOut, c);
  tailMB = pppAppend(c, tailMB, &pc->outACCM);

  /* Load packet. */
  for(p = pb; p; p = p->next) {
    int n;
    u_char *sPtr;

    sPtr = (u_char*)p->payload;
    n = p->len;
    while (n-- > 0) {
      c = *sPtr++;

      /* Update FCS before checking for special characters. */
      fcsOut = PPP_FCS(fcsOut, c);
      
      /* Copy to output buffer escaping special characters. */
      tailMB = pppAppend(c, tailMB, &pc->outACCM);
    }
  }

  /* Add FCS and trailing flag. */
  c = ~fcsOut & 0xFF;
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
  c = (~fcsOut >> 8) & 0xFF;
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);

  /* If we failed to complete the packet, throw it away. */
  if (!tailMB) {
    PPPDEBUG((LOG_WARNING,
             "pppifOutput[%d]: Alloc err - dropping proto=%d\n", 
              pd, protocol));
    pbuf_free(headMB);
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    return ERR_MEM;
  }

  /* Send it. */
  PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));

  nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */

  return ERR_OK;
}

/* Get and set parameters for the given connection.
 * Return 0 on success, an error code on failure. */
int
pppIOCtl(int pd, int cmd, void *arg)
{
  PPPControl *pc = &pppControl[pd];
  int st = 0;

  if (pd < 0 || pd >= NUM_PPP) {
    st = PPPERR_PARAM;
  } else {
    switch(cmd) {
    case PPPCTLG_UPSTATUS:      /* Get the PPP up status. */
      if (arg) {
        *(int *)arg = (int)(pc->if_up);
      } else {
        st = PPPERR_PARAM;
      }
      break;
    case PPPCTLS_ERRCODE:       /* Set the PPP error code. */
      if (arg) {
        pc->errCode = *(int *)arg;
      } else {
        st = PPPERR_PARAM;
      }
      break;
    case PPPCTLG_ERRCODE:       /* Get the PPP error code. */
      if (arg) {
        *(int *)arg = (int)(pc->errCode);
      } else {
        st = PPPERR_PARAM;
      }
      break;
#if PPPOS_SUPPORT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -