📄 ppp.c
字号:
intpppOverSerialOpen(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_SUPPORTstatic void pppOverEthernetLinkStatusCB(int pd, int up);voidpppOverEthernetClose(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. */intpppClose(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. */voidpppSigHUP(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_SUPPORTstatic voidnPut(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_SUPPORTstatic err_tpppifOutputOverEthernet(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_tpppifOutput(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. */intpppIOCtl(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 case PPPCTLG_FD: if (arg) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -