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

📄 ppp.c

📁 本人亲手实现且用在一商用产品上的一个简单的ppp协议
💻 C
📖 第 1 页 / 共 3 页
字号:

}


/***********************************************************************
Function : 	public PPPSendPAPPacket 

Parameters : 	Action: 	LCP_REQ, LCP_REJ, LCP_NAK
		ID:		Sequence number of PPP packet
		user:		User name for login
		password:	Password in plain text

Date : 		September 2000

Desc : 		Formats a PAP packet on Output Buffer. This function
		supports the type field for future implementation of
		the PPP module in server mode.
***********************************************************************/
void SendPAPPacket (BYTE Action, BYTE id, char* user, char* password) {
	OutBuffer [0] = 0xFF;
	OutBuffer [1] = 0x03;
	OutBuffer [2] = 0xC0;
	OutBuffer [3] = 0x23;
	OutBuffer [4] = Action;
	OutBuffer [5] = InBuffer [5] + 1;
	OutBuffer [6] = 0;
	OutBuffer [7] = strlen (user) + strlen (password) + 6;
	OutBuffer [8] = strlen (user);
	Move ((BYTE *)user, &OutBuffer [9], strlen (user));
	OutBuffer [9 + strlen (user)] = strlen (password);
	Move ((BYTE *)password, &OutBuffer [10 + strlen (user)], strlen (password));
	ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);
}
/***********************************************************************
 * 如果ISP发出了分配给本机IP地址的NAK协商包后,DTE端将此IP地址来请求,但却再也没收到
 * ISP的IP地址ACK包,这时候将无法确定是哪个包丢掉,只有重新向ISP申请IP地址
 ***********************************************************************/
void SendIPCPReqIPAddr() {
    static TMO tm=0;
    
    if (tm==0) {
        // 此函数第一次运行时,需要设好一个timer初始值
        mstimeout(&tm,0);
        return;
    }
    else {
        if ( !mstimeout(&tm,2000) )
            return;
    }
    // 这里如果需要申请IP地址,那么需要每隔一段时间周期性地去
    // 请求,直到申请IP地址成功.这里设为2秒钟
    
    // 我们自己的IP地址还没取到,所以要继续Request                        
    OutBuffer[0] = 0xFF;
    OutBuffer[1] = 0x03;
    OutBuffer[2] = 0x80;
    OutBuffer[3] = 0x21;
    OutBuffer[4] = LCP_REQ;         // Request command
    OutBuffer[5] = PPP_PacketID++;  // OutBuffer [5] + 1;  // Packet ID = ID + 1
    OutBuffer[6] = 0x00;            // 长度字段,len=10
    OutBuffer[7] = 0x0A;        
    OutBuffer[8] = 0x03;            // Option 3
    OutBuffer[9] = 0x06;
    OutBuffer[10] = 0;              // IP address is set to 0 so ISP server 
    OutBuffer[11] = 0;              // can assign one to us
    OutBuffer[12] = 0;
    OutBuffer[13] = 0;
    OutBuffer[14] = 0;              // CRC 字段,暂设为零
    OutBuffer[15] = 0;
    ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);
}
/***********************************************************************
Function : 	Move

Parameters : 	src:	 	A pointer to the data to copy 
		dest:		A pointer to the destination location 
		numBYTEs:	Number of bytes to copy

Date : 		September 2000

Desc : 		Copies a block of numBYTEs bytes from src pointer 
		to dest pointer
***********************************************************************/
void Move (BYTE *src, BYTE *dest, int numBYTEs) {
    if ( numBYTEs <= 0 ) return;
    
    if ( src < dest ) {
        src += numBYTEs;
        dest += numBYTEs;
        do {
            *--dest = *--src;
        } while ( --numBYTEs > 0 );
    } else {
        do {
            *dest++ = *src++;
        } while ( --numBYTEs > 0 );
    }		
}

/***********************************************************************
Function : 	protected RejectProtocol  

Parameters : 	InBuffer -> A pointer to the buffer that has the PPP
		Packet to reject

Date : 		August 2000

Desc : 		Rejects the a PPP packet based on its Protocol field
		Stored on InBuffer
		
***********************************************************************/
static void RejectProtocol (BYTE *InBuffer) {

	OutBuffer [0] = 0xFF;
	OutBuffer [1] = 0x03;
	OutBuffer [2] = 0xC0;
	OutBuffer [3] = 0x21;
	OutBuffer [4] = 0x08;
	OutBuffer [5] = 20;
	OutBuffer [6] = 0;
	OutBuffer [7] = InBuffer[7] + 6;
	Move (&InBuffer[2], &OutBuffer[8], InBuffer [7] + 2);
	ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);
}

/***********************************************************************
Function : 	protected PPPSendVoidLcp 

Parameters : 	None

Date : 		September 2000

Desc : 		Sends a void LCP packet with no options to the PPP Server.
		This will force the server to reply with his options to 
		negotiate. Some ISPs require scripts to stablish a connection thus
		a void LCP packet will try to force the server to negotiate PPP.  
***********************************************************************/

void PPPSendVoidLCP (void) {
    //WORD Checksum;

	Move ((BYTE *)PPPData, OutBuffer, PPPData[7] + 6);
	ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);
}


/***********************************************************************
Function : 	PPPTerminate

Parameters : 	None

Date : 		September 2000

Desc : 		Terminates a PPP link by sending a terminate LCP packet
***********************************************************************/
void PPPTerminate (void) {
   Move ((BYTE *)LCPTerminate, OutBuffer, 10);
   ProcPPPSend (OutBuffer, 10);
}


/***********************************************************************
Function : 	IPCompare

Parameters : 	Ip: A pointer to a IP address to compare

Date : 		November 2000

Desc : 		Compares an IP address to the default IP address defined
		in this module

***********************************************************************/
BYTE IPCompare (BYTE *IPOne) {
	if (IPOne [0] != EXT_IP_BYTE1) return (BYTE)0x00;
	if (IPOne [1] != EXT_IP_BYTE2) return (BYTE)0x00;
	if (IPOne [2] != EXT_IP_BYTE3) return (BYTE)0x00;
	if (IPOne [3] != EXT_IP_BYTE4) return (BYTE)0x00;

	return (BYTE) 0x01;
}

BOOL PPPLinkStatus() {
    if ( (PPPStatus & LinkOn) )
        return TRUE;
    else
        return FALSE;        
}
/***********************************************************************
Function : 	PPPEntry  

Parameters : 	None

Date : 		August 2000

Desc : 		PPP Module Entry, Applications should call PPPEntry 
		frequently in the main loop or in portions of the app 
		code.
***********************************************************************/
#define PK_TCP      0x06
#define PK_UDP      0x11
#define PK_ICMP     0x01

void PPPEntry (void) {
    WORD    PacketType;
    WORD    Checksum;
    BYTE    ck1,ck2;
            
    if (PPPStatus & IsFrame) {
        if ( !(PPPStatus & LinkOn) ) {
            // PPP建立后验证收到包的FCS是否正确

            // 在ppp链路没有建立以前,PPP包需要校验,PPP链路建立后,传送的包都是
            // IP数据了,数据的正确性通过后面的检测手段来保证
            
            // ppp链路建立以后,协议发生了变化,InBuffer[7]中不再存放的是长度值
            // 所以FCS校验不能混在一起
            
            // 协商阶段协议:
            // 0xFF 0x03 Proto(2) Code(1) ID(1) Len(2) OPTIONs(N) FCS(2)
            
            // PPP建立后协议:
            // 0xFF 0x03 Proto(2) Data... FCS(2) 
            
        	Checksum = PPPGetChecksum (InBuffer, InBuffer[7] + 4);
    	    ck1 = Checksum & 0xFF;
        	ck2 = (Checksum >> 8) & 0xFF;
        	if (InBuffer[InBuffer[7]+4]!=ck1 || InBuffer[InBuffer[7]+5]!=ck2) {
    	        // 验证不能通过
                PPPStatus &= ~IsFrame;
                PPPStatus |= ReSync;
                return;    
            }    	
        }    	    
        
#ifdef  PPP_PACKET_ANYSIS
    if (BufAnysisIndex<MAX_PPP_BUF_ANYSIS_NUM) {
        memcpy((UB *)BufAnysis[BufAnysisIndex],InBuffer,InBuffer[7] + 12); // packet save 
        BufAnysisFlag[BufAnysisIndex++]=1;  // receive packet 
    }
#endif

    	    
#ifdef  FOR_LITTLE_ENDIAN
        PacketType=((WORD)InBuffer[2] << 8) | InBuffer[3] ;
#endif
        switch (PacketType) {

            case LCP_PACKET:	
                HandleLCPOptions ();
                break;

            case PAP_PACKET:
                if (InBuffer [4] == 0x02) { 
                    PPPStatus |= PAP_FIN;   // Authentication OK
                }
                break;

            case IPCP_PACKET:               // IPCP Handler
                HandleIPCPOptions ();
                break;

            case IP_DATAGRAM:               // IP Data Handler 
                
                if (!IPCompare ((BYTE *)&InBuffer [20])) {
                    // Misrouted datagram or broadcast message received 
                    break;
                }
                else {		
                    /*
                    switch (InBuffer [13]) {
    
                        case PK_UDP:
                            //UDP_Handler ((UDPDatagram *)&InBuffer[16]);							
                            break;

                        case PK_TCP:
                            break;
	
                        case PK_ICMP:
                            //IcmpHandler ((IPDatagram *)&InBuffer[4]);
                            break;

                        default:
                            break;								
                    }
                    */

#ifdef  PPP_IP_ANYSIS
                    if (InBuffer[16]==61 &&
                        InBuffer[17]==141 &&
                        InBuffer[18]==237 &&
                        InBuffer[19]==100 ) 
                    {
                        if (BufIPAnysisIndex<MAX_PPP_IP_NUM)
                            memcpy(BufIpAnysis[BufIPAnysisIndex++],\
                                  (BYTE *)&InBuffer[4],sizeof(InBuffer)-4);
                    }
#endif

                    // 将收到的数据copy到公共接收区,准备集中处理
                    // 这里去掉ppp包头部数据,也就是说LinkRxBuf的起始值就是
                    // IP包头
                    memcpy(LinkRxBuf,(BYTE *)&InBuffer[4],sizeof(InBuffer)-4);
                    pLinkRxBuf=LinkRxBuf;
                    
                    //static BYTE pktcnt=0;
                    
                    //if (memchr((UB *)LinkRxBuf,'G',70)) {
                    //    pktcnt=0;
                    //}
                    
                    // 标识此包是通过PPP传过来
                    RxBufType=FROM_PPP;
                    bPPPRcvOneFrame=1;
                    break;
                }
            default:
                // Cannot handle this type of packet 
                RejectProtocol (InBuffer);	
                break;
        };
        PPPStatus &= ~IsFrame;
        PPPStatus |= ReSync;
    }
    else if ((PPPStatus & PAP_FIN) && !(PPPStatus & LinkOn)) {
        // 认证已经通过,此时ppp进入IPCP协议阶段,但IP地址还没有得到
        SendIPCPReqIPAddr();            
    }    

}
//***********************************************************************
extern UH   ModemStatus;

void PPPTask() {
    if (ModemStatus & MODEM_ONLINE) {   // 如果modem在线,才能处理ppp协议层
        pppRcv();
        PPPEntry();
    }
}
//***********************************************************************

⌨️ 快捷键说明

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