📄 p16_ppp.c
字号:
/* 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 + -