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

📄 netppp.c

📁 UCOS下添加TCP/IP和PPP协议,实现TCP,UDP点到点等功能.
💻 C
📖 第 1 页 / 共 4 页
字号:
/***********************************/
/*** PUBLIC FUNCTION DEFINITIONS ***/
/***********************************/
/* Initialize the PPP subsystem. */

/*
void pppInit(Interface* pInterface)
{
}
 */
void pppInit(void)
{
    struct protent *protp;
    int i, j;
    
    for (i = 0; i < NUM_PPP; i++) {
        pppControl[i].openFlag = 0;
        sprintf(pppControl[i].ifname, "ppp%d", i);
    
        /*
         * Initialize to the standard option set.
         */
        for (j = 0; (protp = protocols[j]) != NULL; ++j)
            (*protp->init)(i);
    }
    
#if STATS_SUPPORT > 0
    /* Clear the statistics. */
    memset(&pppStats, 0, sizeof(pppStats));
    pppStats.headLine.fmtStr        = "\t\tPPP STATISTICS\r\n";
    pppStats.ppp_ibytes.fmtStr      = "\tBYTES IN    : %5lu\r\n";
    pppStats.ppp_ipackets.fmtStr    = "\tPACKETS IN  : %5lu\r\n";
    pppStats.ppp_ierrors.fmtStr     = "\tIN ERRORS   : %5lu\r\n";
    pppStats.ppp_derrors.fmtStr     = "\tDISPATCH ERR: %5lu\r\n";
    pppStats.ppp_obytes.fmtStr      = "\tBYTES OUT   : %5lu\r\n";
    pppStats.ppp_opackets.fmtStr    = "\tPACKETS OUT : %5lu\r\n";
    pppStats.ppp_oerrors.fmtStr     = "\tOUT ERRORS  : %5lu\r\n";
#endif
}

/* 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. */
int pppOpen(int fd)
{
    PPPControl *pc;
    char c;
    int pd;
    
    /* XXX
     * Ensure that fd is not already used for PPP
     */

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

    /*
     * Save the old line discipline of fd, and set it to PPP.
     *  (For the Accu-Vote, save and set the framing character).
     *  Set the user name and password in case we need PAP
     *  authentication.
     */
    if (pd >= 0) {
        c = PPP_FLAG;
#ifdef OS_DEPENDENT
        if (ioctl(fd, GETFRAME, &pppControl[pd].oldFrame) < 0
                || ioctl(fd, SETFRAME, &c) < 0) {
            pd = PPPERR_DEVICE;
            pppControl[pd].openFlag = 0;
        }
#else
        pppControl[pd].openFlag = 1;
#endif
        upap_setloginpasswd(pd, user, passwd);
    }
    
    /* Launch a deamon thread. */
    if (pd >= 0) {
        lcp_init(pd);
        pc = &pppControl[pd];
        pc->fd = fd;
        pc->kill_link = 0;
        pc->if_up = 0;
        pc->errCode = 0;
        pc->inState = PDIDLE;
        pc->inHead = NULL;
        pc->inTail = NULL;
        pc->inEscaped = 0;
        pc->lastXMit = mtime() - MAXIDLEFLAG;
        pc->traceOffset = 0;
        
#if VJ_SUPPORT > 0
        pc->vjEnabled = 0;
        vj_compress_init(&pc->vjComp);
#endif

        /* 
         * 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;

//#ifdef OS_DEPENDENT
        OSTaskCreate(pppMain, (void*)pd, pc->pppStack + STACK_SIZE, (UBYTE)(PRI_PPP0 + pd));
//#endif
    
        while(pd >= 0 && !pc->if_up) {
            msleep(500);
            if (lcp_phase[pd] == PHASE_DEAD) {
                pppClose(pd);
                if (pc->errCode)
                    pd = pc->errCode;
                else
                    pd = PPPERR_CONNECT;
            }
//            else if (buttonStatus() == YESNOBUTTON) {
//                pppClose(pd);
//                pd = PPPERR_USER;
//            }
        }
        pc->traceOffset = 2;
    }

    return pd;
}

/* 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 */
    pc->kill_link = !0;
    pc->traceOffset = 0;
    
    while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
        msleep(500);
//        if (buttonStatus() == YESNOBUTTON)
//            st = PPPERR_USER;
		break;
    }

#ifdef OS_DEPENDENT
    /* Reset fd line discipline.  In our case, the framing character. */
    if (ioctl(pc->fd, SETFRAME, &pppControl[pd].oldFrame) < 0)
        st = PPPERR_DEVICE;
#endif
        
    pc->openFlag = 0;
    
    return st;
}

/* Send a packet on the given connection.
 * Return 0 on success, an error code on failure. */
#pragma argsused
int pppOutput(int pd, u_short protocol, NBuf *nb)
{
    PPPControl *pc = &pppControl[pd];
    u_int fcsOut = PPP_INITFCS;
    NBuf *headMB = NULL, *tailMB = NULL, *tnb;
    int st = 0;
    u_char c = 0;
    int n;
    u_char *sPtr;

    /* Grab an output buffer. */
    nGET(headMB);
    if (headMB == NULL) {
        st = PPPERR_ALLOC;
        PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: first alloc fail", pd));
#if STATS_SUPPORT > 0
        pppStats.PPPoerrors++;
#endif
    
    /* 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. */
    } else if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !nb) {
        st = PPPERR_PARAM;
        PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: bad parms prot=%d nb=%P",
                    pd, protocol, nb));
#if STATS_SUPPORT > 0
        pppStats.PPPoerrors++;
#endif
        
    /* Check that the link is up. */
    } else if (lcp_phase[pd] == PHASE_DEAD) {
        PPPDEBUG((LOG_ERR, TL_PPP, "pppOutput[%d]: link not up", pd));
#if STATS_SUPPORT > 0
        pppStats.PPPderrors++;
#endif
        st = PPPERR_OPEN;
        
    } else {
#if VJ_SUPPORT > 0
        /* 
         * 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, nb)) {
            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, TL_PPP, "pppOutput[%d]: bad IP packet", pd));
#if STATS_SUPPORT > 0
                pppStats.PPPderrors++;
#endif
                return PPPERR_PROTOCOL;
            }
        }
#endif
        
        headMB->len = 0;
        tailMB = headMB;
            
        /* Build the PPP header. */
        if (diffTime(pc->lastXMit) <= MAXIDLEFLAG)
            tailMB = pppMPutRaw(PPP_FLAG, tailMB);
        if (!pc->accomp) {
            fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
            tailMB = pppMPutC(PPP_ALLSTATIONS, &pc->outACCM, tailMB);
            fcsOut = PPP_FCS(fcsOut, PPP_UI);
            tailMB = pppMPutC(PPP_UI, &pc->outACCM, tailMB);
        }
        if (!pc->pcomp || protocol > 0xFF) {
            c = (protocol >> 8) & 0xFF;
            fcsOut = PPP_FCS(fcsOut, c);
            tailMB = pppMPutC(c, &pc->outACCM, tailMB);
        }
        c = protocol & 0xFF;
        fcsOut = PPP_FCS(fcsOut, c);
        tailMB = pppMPutC(c, &pc->outACCM, tailMB);
        
        /* Load packet. */
        while (nb) {
            sPtr = nBUFTOPTR(nb, u_char *);
            n = nb->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 = pppMPutC(c, &pc->outACCM, tailMB);
            }
            nFREE(nb, tnb);
            nb = tnb;
        }
            
        /* Add FCS and trailing flag. */
        c = ~fcsOut & 0xFF;
        tailMB = pppMPutC(c, &pc->outACCM, tailMB);
        c = (~fcsOut >> 8) & 0xFF;
        tailMB = pppMPutC(c, &pc->outACCM, tailMB);
        tailMB = pppMPutRaw(PPP_FLAG, tailMB);
            
        /* If we failed to complete the packet, throw it away.
         * Otherwise send it. */
        if (!tailMB) {
            st = PPPERR_ALLOC;
            PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
                        "pppOutput[%d]: Alloc err - dropping proto=%d", 
                        pd, protocol));
            nFreeChain(headMB);
#if STATS_SUPPORT > 0
            pppStats.PPPoerrors++;
#endif
        }
        else {
            PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
//                        "pppOutput[%d]: proto=x%X %d:%.*H", pd, protocol, headMB->chainLen, MIN(headMB->len * 2, 50), headMB->data));
                        "pppOutput[%d]: proto=x%X len=%d", pd, protocol, headMB->chainLen));
            nPut(pc->fd, headMB);
#if STATS_SUPPORT > 0
            pppStats.PPPopackets++;
#endif
        }
        headMB = NULL;
    }
    /* If we didn't consume the source buffer, drop it. */
    if (nb)
        nFreeChain(nb);
    /* If we didn't send the output buffer, drop it. */
    if (headMB) {
        nFreeChain(headMB);
#if STATS_SUPPORT > 0
        pppStats.PPPoerrors++;
#endif
    }
        
    return st;
}

/* Process an nBuf chain received on given connection.
 * The nBuf chain is always passed on or freed making the original
 * nBuf pointer invalid.  Note that this does not check for packet
 * chains.  This does not require complete packets but if a packet
 * spans calls, those calls must be in the correct order.  This is
 * designed to handle packets received from the serial interface
 * but could be used for a loopback interface.
 * Return 0 on success, an error code on failure.
 */
int pppInput(int pd, NBuf *nb)
{
    NBuf *nextNBuf;

    while (nb != NULL) {
        /* Consume the buffer.  Ideally we could just work on the
         * recieved buffer but unless we get the serial driver to
         * preprocess the escape sequences, it's easier to just
         * work from one buffer to another. */
        pppInProc(pd, nb->data, nb->len);
        nFREE(nb, nextNBuf);
        nb = nextNBuf;
    }
    return 0;
}

/* 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;
        case PPPCTLG_FD:
            if (arg) 
                *(int *)arg = (int)(pc->fd);
            else
                st = PPPERR_PARAM;
            break;
        default:

⌨️ 快捷键说明

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