📄 ppp.c
字号:
/******************************************************************************************
ppp.c (v1.0)
-------------------------------------------------------------------------------------
This code is from the book:
"Embedded Internet: TCP/IP Basics, Implementation and Applications" by Sergio Scaglia
[Pearson Education, 2006 - ISBN: 0-32-130638-4]
This code is copyright (c) 2006 by Sergio Scaglia, and it may only be used for educational
purposes. For commercial use, please contact me at sscaglia@intramarket.com.ar
For more information and updates, please visit www.embeddedinternet.org
******************************************************************************************/
#include "Stack.h"
#include "ppp.h"
#include "uart.h"
#include "uart1.h"
#include "timer.h"
#include <stdio.h>
#include <string.h>
#define PPP_INITIAL_STATE 0x00
#define LCP_ACK_SENT 0x01 // we sent an ACK
#define LCP_ACK_RCVD 0x02 // we received an ACK
#define LCP_OK 0x03
#define PAP_REQ_SENT 0x04 // we sent a PAP REQ
#define PAP_ACK_RCVD 0x0C // we received an ACK for the user and password
#define IPCP_REQ1_SENT 0x10 // we sent an IPCP REQ (with IP: 0.0.0.0)
#define IPCP_NAK_RCVD 0x30 // we received a NAK with the assigned IP address
#define IPCP_REQ2_SENT 0x40 // we sent an IPCP REQ (with the assigned IP)
#define PPP_OK 0x80 // we are connected!!!
char ppp_state = PPP_INITIAL_STATE;
#define PPP_NO_ACTION 0x00
#define PPP_START 0x01
#define PPP_STOP 0x02
char ppp_start_stop = PPP_NO_ACTION;
#define MODEM_DISCONNECTED 0x00
#define MODEM_RESETTING 0x01
#define MODEM_RESET_OK 0x02
#define MODEM_DIALING 0x04
#define MODEM_CONNECTED 0x08
#define MODEM_DISCONNECTING 0x10
#define MODEM_WAITING_DIAL 0x20
char modem_state = MODEM_DISCONNECTED;
#define MODEM_NO_STATUS 0x00
#define MODEM_OK 0x01
#define MODEM_ERROR 0x02
#define MODEM_TIMEOUT 0x04
#define MODEM_BUSY 0x08
#define MODEM_NO_CARRIER 0x10
#define MODEM_NO_DIALTONE 0x20
char modem_status = MODEM_NO_STATUS;
#define MAX_RETRIES 3
char ppp_status = PPP_CLOSED;
const char LCP_REQ[]={0x01,0x00,0x00,0x0E,0x02,0x06,0x00,0x0A,0x00,0x00,
0x07,0x02,0x08,0x02};
const char PAP_REQ[]={0x01,0x00,0x00,0x00};
char IPCP_REQ[]={0x01,0x00,0x00,0x0A,0x03,0x06,0x00,0x00,0x00,0x00};
struct ppp_hdr {
char address;
char control;
unsigned short protocol;
};
struct ppp_ctl_hdr {
char type;
char id;
unsigned short length;
};
struct {
char number[20];
char user[20];
char pass[20];
} isp;
int c;
char rx_buf[PACKET_BUF_SIZE+2]; // 2 bytes more for the FCS
char tx_buf[PACKET_BUF_SIZE+2]; // 2 bytes more for the FCS
char id=85; // we start with this id number
char MyIP[4]; // The IP assigned by the RAS Server
char server[4]; // RAS Server IP address
/**********************************/
/* PPP PRIVATE FUNCTIONS */
/**********************************/
void ppp_display(char *ptr) {
int i;
unsigned short len;
len = (*(ptr+6)<<8)+(*(ptr+7));
for(i=0;i < len+4+2;i++) { // len + lcp_hdr (4) + CRC (2)
printf("%02x ", *ptr++);
}
printf("\n");
}
void lcp_req_scan(void) {
int i;
int rx_ptr;
int tx_ptr;
char result=0; // ACK (bit0=0 and bit1=0)
short size;
size = HTONS(CTRL->length)+4; // packet size
rx_ptr = 8;
while(rx_ptr < size) {
switch(rx_buf[rx_ptr]) {
case 2:
break;
case 3:
if (rx_buf[rx_ptr+2] == 0xC2) // if CHAP
result |= 1; // NAK (bit0=1)
break;
case 7:
break;
case 8:
break;
default: // any other option
result |= 2; // REJ (bit1=1)
break;
}
rx_ptr += rx_buf[rx_ptr+1];
}
if (result&2) { // REJ
tx_buf[4]=REJ;
rx_ptr = 8;
tx_ptr = 8;
while(rx_ptr < size) {
if (rx_buf[rx_ptr]!=2 && rx_buf[rx_ptr]!=3 &&
rx_buf[rx_ptr]!=7 && rx_buf[rx_ptr]!=8) {
for(i=rx_ptr;i<(rx_ptr+rx_buf[rx_ptr+1]); i++) {
tx_buf[tx_ptr++] = rx_buf[i];
}
}
rx_ptr += rx_buf[rx_ptr+1];
}
tx_buf[6] = ((tx_ptr - 4)>>8)&0xFF; // length
tx_buf[7] = (tx_ptr - 4)&0xFF;
}else if (result&1) { // NAK
tx_buf[4]=NAK;
tx_buf[6]=0;
tx_buf[7]=8;
tx_buf[8]=3;
tx_buf[9]=4;
tx_buf[10]=0xC0;
tx_buf[11]=0x23;
}else { // ACK
tx_buf[4]=ACKW;
rx_ptr = 8;
tx_ptr = 8;
while(rx_ptr < size) {
for(i=rx_ptr;i<(rx_ptr+rx_buf[rx_ptr+1]); i++) {
tx_buf[tx_ptr++] = rx_buf[i];
}
rx_ptr += rx_buf[rx_ptr+1];
}
tx_buf[6] = ((tx_ptr - 4)>>8)&0xFF; // length
tx_buf[7] = (tx_ptr - 4)&0xFF;
ppp_state |= LCP_ACK_SENT;
}
tx_buf[5]=rx_buf[5]; // id must match request
ppp_send(LCP_PROTOCOL, ((tx_buf[6]<<8) + tx_buf[7]));
if (ppp_state == LCP_OK)
printf("\nLCP OK\n");
}
void lcp_process(void) {
switch(CTRL->type){
case REQ:
lcp_req_scan();
break;
case ACKW:
if (ppp_state == LCP_OK)
printf("LCP OK\n");
ppp_state |= LCP_ACK_RCVD;
break;
case NAK:
break;
case REJ:
break;
case TERM_REQ:
tx_buf[4]=TERM_ACK;
tx_buf[5]=rx_buf[5]; // id must match request
tx_buf[6]=0;
tx_buf[7]=4;
ppp_send(LCP_PROTOCOL, ((tx_buf[6]<<8) + tx_buf[7]));
printf("PPP Closed (requested by Server)\n");
ppp_start_stop = PPP_STOP;
modem_status = MODEM_NO_STATUS;
if (ppp_status == PPP_WAIT) { // if it does not reach the PPP_OK
if (ppp_state == PAP_REQ_SENT)
ppp_status = PPP_ERROR_AUTH; // an error in ppp Authentication
else
ppp_status = PPP_ERROR_NEGOTIATION; // an error in ppp negotiation
}else {
ppp_status = PPP_ERROR_SERVER_CLOSE; // the server terminates the connection
}
ppp_state = PPP_INITIAL_STATE;
break;
case TERM_ACK:
break;
default:
printf("\nLCP Unkown Type: %d\n", CTRL->type);
break;
}
}
void ipcp_process(void) {
switch(CTRL->type) {
case REQ:
if (rx_buf[8]==2) { // IP Compression-Protocol option (Not Allowed)
memcpy(&tx_buf[4], &rx_buf[4], 10);
tx_buf[4] = REJ;
tx_buf[7] = 0x0A;
}else { // only IP-Address option (Allowed)
memcpy(&tx_buf[4], &rx_buf[4], HTONS(CTRL->length));
tx_buf[4] = ACKW;
memcpy(&server[0], &rx_buf[10], 4);
printf("\nServer Address: %d.%d.%d.%d \n", server[0],server[1],server[2],server[3]);
}
ppp_send(IPCP_PROTOCOL, HTONS(CTRL->length));
break;
case ACKW:
ppp_state = PPP_OK;
memcpy(&MyIP[0], &rx_buf[10], 4);
printf("PPP Ok - Address: %d.%d.%d.%d\n", MyIP[0],MyIP[1],MyIP[2],MyIP[3]);
ppp_status = PPP_OPENED;
break;
case NAK:
ppp_state = IPCP_NAK_RCVD;
break;
}
}
#if debug_ppp
void ppp_debug(void) {
if (HTONS(PPP->protocol)==IP_PROTOCOL)
return;
printf("\nReceived: ");
switch(HTONS(PPP->protocol)) {
case LCP_PROTOCOL:
printf("LCP ");
break;
case PAP_PROTOCOL:
printf("PAP ");
break;
case IPCP_PROTOCOL:
printf("IPCP ");
break;
case CCP_PROTOCOL:
printf("CCP ");
break;
default:
printf("Unknown Protocol ");
break;
}
switch(CTRL->type) {
case REQ:
printf("REQ ID: %d\n", CTRL->id);
break;
case ACKW:
printf("ACK ID: %d\n", CTRL->id);
break;
case NAK:
printf("NAK ID: %d\n", CTRL->id);
break;
case REJ:
printf("REJ ID: %d\n", CTRL->id);
break;
case TERM_REQ:
printf("TERM-REQ ID: %d\n", CTRL->id);
break;
case TERM_ACK:
printf("TERM-ACK ID: %d\n", CTRL->id);
break;
default:
printf("Unknown Type: %d ID: %d\n", CTRL->type,CTRL->id);
break;
}
ppp_display(&rx_buf[0]);
}
#endif //debug_ppp
void packet_process(void) {
#if debug_ppp
ppp_debug();
#endif //debug_ppp
switch(HTONS(PPP->protocol)) {
case LCP_PROTOCOL:
lcp_process();
break;
case PAP_PROTOCOL:
if (CTRL->type == ACKW) {
ppp_state = PAP_ACK_RCVD;
printf("PAP OK\n");
}
if (CTRL->type == NAK) {
printf("PAP: Incorrect User or Password!\n");
}
break;
case IPCP_PROTOCOL:
ipcp_process();
break;
case CCP_PROTOCOL:
memcpy(&tx_buf[4], &rx_buf[4], HTONS(CTRL->length));
if (rx_buf[4] == TERM_REQ)
tx_buf[4] = TERM_ACK;
else
tx_buf[4] = REJ;
ppp_send(CCP_PROTOCOL, HTONS(CTRL->length));
break;
case IP_PROTOCOL:
//ip_process(); // IP layer not yet implemented!
break;
default:
printf("Unknown Protocol %04x\n", HTONS(PPP->protocol));
break;
}
}
unsigned int calc(unsigned int ch) {
char i;
ch &= 0xFF;
for (i=0; i<8; i++)
{
if (ch&1)
{
ch /= 2;
ch ^= 0x8408;
}else ch /= 2;
}
return ch;
}
unsigned short tx_chksum(unsigned short len) {
short i;
unsigned short chksum16=0xFFFF;
for (i=0;i<len;i++) {
chksum16 = calc(tx_buf[i] ^ chksum16) ^ (chksum16/256);
}
return ~ chksum16;
}
void char_process(void) {
static char extended=0;
static unsigned int chksum;
static unsigned short index = 0;
if (c == 0x7E) { // Start or End of packet
if (index && (chksum == 0xF0B8)) {
packet_process();
}
extended=0; // Prepare for next packet
index = 0;
chksum = 0xFFFF;
}else if (c == 0x7D) {
extended = 1;
}else {
if (extended) {
c ^= 0x20;
extended = 0;
}
if (index==0 && c!=0xFF) // if Address compressed, include it
rx_buf[index++] = 0xFF;
if (index==1 && c!=0x03) // if Control compressed, include it
rx_buf[index++] = 0x03;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -