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

📄 p16_ppp.c

📁 一个由PIC单片机组成的Web服务器源码
💻 C
📖 第 1 页 / 共 3 页
字号:

/* Get an incoming byte value, return 0 if end of message */
BOOL get_byte(BYTE *bp)
{
    BYTE b;

    if (rxout >= net_rxin)
    {
        atend = 1;
        return(0);
    }
    b = rxbuff[rxout];
    rxout++;
    if (!rx_checkoff)
        check_byte(b);
    *bp = b;
#if DEBUG
    disp_hexbyte(b);
#endif
    return(!atend);
}

/* Send a byte to the network buffer, then add to checksum
** Return 0 if no more data can be accepted */
BOOL put_byte(BYTE b)
{
    if (txin >= TXBUFFLEN)
        return(0);
#if NET_TXBUFFERS > 1
    if (txbuffnum)
        txbuff2[txin++] = b;
    else
        txbuff[txin++] = b;
#else
    txbuff[txin++] = b;
#endif
    check_byte(b);
    return(1);
}

/* Copy data from Rx to Tx buffers, return actual byte count */
WORD copy_rx_tx(WORD maxlen)
{
    WORD count=0;

    count = (WORD)min(maxlen, net_rxin-rxout);
    count = (WORD)min(count, TXBUFFLEN-txin);
#if NET_TXBUFFERS > 1
    if (txbuffnum)
        memcpy(&txbuff2[txin], &rxbuff[rxout], count);
    else
        memcpy(&txbuff[txin], &rxbuff[rxout], count);
#else
    memcpy(&txbuff[txin], &rxbuff[rxout], count);
#endif
    txin += count;
    rxout += count;
    save_txbuff();
    return(count);
}

/* Check for incoming PPP frame, return 0 if none */
BOOL get_net(void)
{
    BYTE ok=0;
    WORD mlen;

    if (timeout(&pppticks, PPP_TIMEOUT))        // If PPP timeout..
    {                                           // If LCP is active..
        if (lcp_state>=PPP_CLOSING && lcp_state<=PPP_ACK_SENT)
        {
            if (lcp_rest)                       // ..and any LCP retries left
            {
                lcp_event_handler(EVENT_TO_OK); // ..signal timeout
                lcp_rest--;
            }
            else                                // ..otherwise final timeout
                lcp_event_handler(EVENT_TO_ERR);
            do_lcp_actions();                   // Process the event
        }                                       // If IPCP is active..
        else if (ipcp_state>=PPP_CLOSING && ipcp_state<=PPP_ACK_SENT)
        {
            if (ipcp_rest)                      // ..and any IPCP retries left
            {
                ipcp_event_handler(EVENT_TO_OK);// ..signal timeout
                ipcp_rest--;
            }
            else                                // ..otherwise final timeout
                ipcp_event_handler(EVENT_TO_ERR);
            do_ipcp_actions();
        }
    }
    poll_net();                                 // If incoming frame..
    if (net_rxin)
    {
        init_rxbuff();                          // Prepare Rx buffer
        rx_checkoff = 1;
        if (skip_byte() && skip_byte() &&       // Skip HDLC addr & ctrl bytes
            get_word(&ppp_pcol))                // Get PPP protocol
        {
            init_txbuff(0);
            if (ppp_pcol == PPP_IP_DATA)        // If IP data, just return
            {                                   // (data left for IP handler)
                return(1);
            }
            setpos_txin(PPP_HEADLEN);           // If LCP, IPCP or PAP..
#if INCLUDE_CLIENT_AUTH || INCLUDE_SERVER_AUTH
            if (ppp_pcol==PPP_LCP || ppp_pcol==PPP_IPCP || ppp_pcol==PPP_PAP)
#else
            if (ppp_pcol==PPP_LCP || ppp_pcol==PPP_IPCP)
#endif
            {                                   // ..get header
                if (get_byte(&ppp_code) && get_byte(&ppp_rxid) &&
                    get_word(&mlen) && mlen>=4 && net_rxin>=mlen+2)
                {                               // ..and call handler
                    if (ppp_pcol == PPP_LCP)
                        lcp_rx_handler();
#if INCLUDE_CLIENT_AUTH || INCLUDE_SERVER_AUTH
                    else if (ppp_pcol == PPP_PAP)
                        pap_rx_handler();
#endif
                    else
                        ipcp_rx_handler();
                }
            }
            else
            {
                put_word(ppp_pcol);             // Reject unknown protocol
                ppp_pcol = PPP_LCP;
                send_ppp(PPP_PCOL_REJ, ppp_rxid, 1);
            }
        }
        net_rxin = 0;
    }                                           // Modem emulation: 'AT' cmd?
    if (mdm_rxin>=2  && rxbuff[0]=='A' && rxbuff[1]=='T')
    {
        if (rxbuff[2] == 'D')
            put_ser("\r\nCONNECT\r\n");         // If dialling, 'connect'
        else if (rxbuff[2] == 'H')
            put_ser("\r\nNO CARRIER\r\n");      // If hangup, 'disconnect'
        else
            ok = 1;
    }
    else if (mdm_rxin>=3 && rxbuff[0]=='+')     // '+++' escape sequence?
        ok = 1;
    else if (mdm_rxin>=5  && rxbuff[0]=='C'&& rxbuff[1]=='L')
        put_ser("CLIENTSERVER");                // Msoft CLIENT/SERVER pcol?
    if (ok)
        put_ser("\r\nOK\r\n");
    mdm_rxin = 0;
    return(0);
}

/* Rx handler for Link Control Protocol */
void lcp_rx_handler(void)
{
    BYTE opt, optlen, code;
    BYTE rejects=0;
    WORD auth=0;
    LWORD lw;

    if (ppp_code == PPP_CFG_REQ)                // LCP Config request?
    {                                           // Check option list
        while (get_byte(&opt) && get_byte(&optlen) && optlen>=2)
        {
            if (opt==LCP_OPT_AUTH && optlen>=4) // Authentication option?
            {                                   // (may be accepted)
                get_word(&auth);
                skip_data(optlen - 4);
            }
            else
            {
                put_byte(opt);                  // Skip other options
                put_byte(optlen);               // (will be rejected)
                copy_rx_tx(optlen - 2);
                rejects++;
            }
        }
        if (rejects)                            // If any rejected options..
        {
            lcp_event_handler(EVENT_RCR_ERR);   // ..inform state machine
            if (lcp_action & SCN)               // If OK to respond..
                send_ppp(PPP_CFG_REJ, ppp_rxid, 1); // ..send rejection
        }
        else if (auth)                          // If authentication request..
        {
            client_auth = auth==PPP_PAP;        // ..only PAP is acceptable
            lcp_event_handler(client_auth ? EVENT_RCR_OK : EVENT_RCR_ERR);
            if (lcp_action & (SCA|SCN))         // If OK to respond..
            {
                put_byte(LCP_OPT_AUTH);         // ..send my response
                put_byte(4);                    // (either ACK PAP..
                put_word(PPP_PAP);              // ..or NAK with PAP hint)
                code = (lcp_action & SCA) ? PPP_CFG_ACK : PPP_CFG_NAK;
                send_ppp(code, ppp_rxid, 1);
            }
        }
        else
        {
            lcp_event_handler(EVENT_RCR_OK);    // Request is all OK
            if (lcp_action & SCA)               // If OK to respond, do so
                send_ppp(PPP_CFG_ACK, ppp_rxid, 0);
        }
    }
    else if (ppp_code == PPP_ECHO_REQ)          // LCP echo request?
    {
        if ((lcp_state&0xf) == PPP_OPENED && get_lword(&lw))
        {                                       // Get magic num
            lw.l++;                             // Return magic num + 1
            put_lword(&lw);
            copy_rx_tx(net_rxin-rxout);         // Echo the data
            send_ppp(PPP_ECHO_REP, ppp_rxid, 1);
        }                                       // Others to state machine..
    }
    else if (ppp_code == PPP_TERM_REQ)          // ..terminate request
        lcp_event_handler(EVENT_RTR);
    else if (ppp_code == PPP_CFG_ACK)           // ..config ACK
        lcp_event_handler(EVENT_RCA);
    else if (ppp_code == PPP_CFG_NAK)           // ..config NAK
        lcp_event_handler(EVENT_RCN);
    else if (ppp_code == PPP_TERM_ACK)          // ..terminate ACK
        lcp_event_handler(EVENT_RTA);
    else if (ppp_code == PPP_CODE_REJ)          // ..code reject
        lcp_event_handler(EVENT_RXJ_ERR);
    do_lcp_actions();
}

/* Handle an LCP event */
void lcp_event_handler(BYTE event)
{
    BYTE newstate, state;

    ppp_pcol = PPP_LCP;
    state = newstate = lcp_state & 0xf;         // Get new state & action
    if (state<=PPP_STOPPED || state==PPP_OPENED)
        lcp_reqs = lcp_terms = 0;
    if (state <= PPP_STOPPED)
        client_auth = server_auth = client_auth_ok = server_auth_ok = 0;
    if (state<=PPP_OPENED && event<=EVENT_RXJ_ERR)
    {
        newstate = lcp_states[event][state];
        lcp_action = lcp_actions[event][state];
        if (lcp_action & SCR)                   // Send config req?
        {
            if (lcp_reqs >= MAX_REQS)           // Error if too many requests
            {
                newstate = lcp_states[EVENT_TO_ERR][state];
                lcp_action = lcp_actions[EVENT_TO_ERR][state];
            }
            lcp_reqs++;
        }
        if (lcp_action & STR)                   // Send terminate req?
        {
            if (lcp_terms >= MAX_TERMS)         // Error if too many requests
            {
                newstate = lcp_states[EVENT_TO_ERR][state];
                lcp_action = lcp_actions[EVENT_TO_ERR][state];
            }
            lcp_terms++;
        }
    }
    if (newstate != XXX)
        lcp_state = newstate;                   // Set new state
}

/* Do the LCP actions (all except config ACK/NAK) */
void do_lcp_actions(void)
{
    ppp_pcol = PPP_LCP;
    if (lcp_action & SCR)                       // Send config request?
    {
        if (server_auth)                        // If incoming authentication
        {
            init_txbuff(0);
            setpos_txin(PPP_HEADLEN);
            put_byte(LCP_OPT_AUTH);             // ..include PAP option in req
            put_byte(4);
            put_word(PPP_PAP);
            send_ppp(PPP_CFG_REQ, ++ppp_txid, 1);
        }
        else                                    // Else no options in request
            send_ppp(PPP_CFG_REQ, ++ppp_txid, 0);
    }
    if (lcp_action & STR)                       // Send termination req?
        send_ppp(PPP_TERM_REQ, ppp_txid, 0);
    if (lcp_action & STA)                       // Send termination ack?
        send_ppp(PPP_TERM_ACK, ppp_rxid, 0);
    if (lcp_action & SCJ)                       // Send code reject?
        send_ppp(PPP_CODE_REJ, ppp_txid, 0);
    if (lcp_action & IRC)                       // Init restart count?
        lcp_rest = lcp_action & STR ? MAX_TERMS : MAX_REQS;
    if (lcp_action & ZRC)                       // Zero restart count?
        lcp_rest = 0;
    if (lcp_state & TLU)                        // This layer up?
        pap_event_handler(EVENT_UP);
    if (lcp_state & TLD)                        // This layer down?
        pap_event_handler(EVENT_DOWN);
}

/* Rx handler for Internet Protocol Control Protocol */
void ipcp_rx_handler(void)
{
    BYTE opt, optlen;
    BYTE rejects=0;

    ppp_pcol = PPP_IPCP;
    if (ppp_code == PPP_CFG_REQ)                // IPCP config request?
    {                                           // Check option list
        while (get_byte(&opt) && get_byte(&optlen) && optlen>=2)
        {
            if (opt==IPCP_OPT_ADDR && optlen==6)// IP address option?
                get_lword(&hostip);             // (will be accepted)
            else
            {
                put_byte(opt);                  // Skip other options
                put_byte(optlen);               // (will be rejected)
                copy_rx_tx(optlen - 2);
                rejects++;
            }
        }
        if (rejects)                            // If any rejected options..
        {
            ipcp_event_handler(EVENT_RCR_ERR);  // ..inform state machine
            if (ipcp_action & SCN)              // If OK to respond..
                send_ppp(PPP_CFG_REJ, ppp_rxid, 1); //..send response
        }
        else if (!hostip.l)                     // If null IP address

⌨️ 快捷键说明

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