📄 ppp.c
字号:
ppp_settings.user[0] = '\0'; } if(passwd) { strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1); ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0'; } else { ppp_settings.passwd[0] = '\0'; }}#if PPPOS_SUPPORT/** Open a new PPP connection using the given I/O device. * This initializes the PPP control block but does not * attempt to negotiate the LCP session. If this port * connects to a modem, the modem connection must be * established before calling this. * Return a new PPP connection descriptor on success or * an error code (negative) on failure. * * pppOpen() is directly defined to this function. */intpppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx){ PPPControl *pc; int pd; if (linkStatusCB == NULL) { /* PPP is single-threaded: without a callback, * there is no way to know when the link is up. */ return PPPERR_PARAM; } /* Find a free PPP session descriptor. */ for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); if (pd >= NUM_PPP) { pd = PPPERR_OPEN; } else { pc = &pppControl[pd]; /* @todo: is this correct or do I overwrite something? */ memset(pc, 0, sizeof(PPPControl)); pc->rx.pd = pd; pc->rx.fd = fd; pc->openFlag = 1; pc->fd = fd;#if VJ_SUPPORT vj_compress_init(&pc->vjComp);#endif /* VJ_SUPPORT */ /* * Default the in and out accm so that escape and flag characters * are always escaped. */ pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ pc->outACCM[15] = 0x60; pc->linkStatusCB = linkStatusCB; pc->linkStatusCtx = linkStatusCtx; /* * Start the connection and handle incoming events (packet or timeout). */ PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); pppStart(pd);#if PPP_INPROC_OWNTHREAD sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);#endif } 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); if (linkStatusCB == NULL) { /* PPP is single-threaded: without a callback, * there is no way to know when the link is up. */ return PPPERR_PARAM; } /* 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 { pc = &pppControl[pd]; memset(pc, 0, sizeof(PPPControl)); pc->openFlag = 1; pc->ethif = ethif; pc->linkStatusCB = linkStatusCB; pc->linkStatusCtx = linkStatusCtx; 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; if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { pc->openFlag = 0; return PPPERR_OPEN; } pppoe_connect(pc->pppoe_sc); } 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; PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); /* Disconnect */#if PPPOE_SUPPORT if(pc->ethif) { PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); pc->errCode = PPPERR_USER; /* This will leave us at PHASE_DEAD. */ pppStop(pd); } else#endif /* PPPOE_SUPPORT */ {#if PPPOS_SUPPORT PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); pc->errCode = PPPERR_USER; /* This will leave us at PHASE_DEAD. */ pppStop(pd); pppRecvWakeup(pd);#endif /* PPPOS_SUPPORT */ } return st;}/* This function is called when carrier is lost on the PPP channel. */voidpppSigHUP(int pd){ PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); pppHup(pd);}#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(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); LINK_STATS_INC(link.err); pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ snmp_inc_ifoutdiscards(&pc->netif); pbuf_free(nb); return; } } snmp_add_ifoutoctets(&pc->netif, nb->tot_len); snmp_inc_ifoutucastpkts(&pc->netif); 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; u16_t tot_len; /* @todo: try to use pbuf_header() here! */ pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); if(!pb) { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.proterr); snmp_inc_ifoutdiscards(&pc->netif); return ERR_MEM; } pbuf_header(pb, -(s16_t)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); tot_len = pb->tot_len; if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { LINK_STATS_INC(link.err); snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_DEVICE; } snmp_add_ifoutoctets(&pc->netif, tot_len); snmp_inc_ifoutucastpkts(&pc->netif); 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, ip_addr_t *ipaddr){ int pd = (int)(size_t)netif->state; PPPControl *pc = &pppControl[pd];#if PPPOS_SUPPORT u_short protocol = PPP_IP; 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, PPP_IP, pb)); LINK_STATS_INC(link.opterr); LINK_STATS_INC(link.drop); snmp_inc_ifoutdiscards(netif); 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); snmp_inc_ifoutdiscards(netif); 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); snmp_inc_ifoutdiscards(netif); 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); snmp_inc_ifoutdiscards(netif); 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); snmp_inc_ifoutdiscards(netif); return ERR_MEM; } /* Send it. */ PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\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: /* Get the fd associated with the ppp */ if (arg) { *(sio_fd_t *)arg = pc->fd; } else { st = PPPERR_PARAM; } break;#endif /* PPPOS_SUPPORT */ default: st = PPPERR_PARAM; break; } } return st;}/* * Return the Maximum Transmission Unit for the given PPP connection. */u_shortpppMTU(int pd){ PPPControl *pc = &pppControl[pd]; u_short st; /* Validate parameters. */ if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; } else { st = pc->mtu; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -