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

📄 ppp.c

📁 阿根廷教授编写的嵌入式internet的实验教程的高质量代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************************
   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 + -