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

📄 ppp.c

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


	WriteComm (0x7E);

	while (len--) {
        //if ((signed char)*Buffer < (signed char)0x20) {
        if (*Buffer < 0x20) {
			WriteComm (0x7D);
			WriteComm (*Buffer ^ 0x20);
		} else {
			switch (*Buffer) {
				case 0x7E:
					WriteComm (0x7D);
					WriteComm (0x5E);
				break;

				case 0x7D:
					WriteComm (0x7D);
					WriteComm (0x5D);
				break;

				default:
					WriteComm (*Buffer);
				break;
			}
		}
		Buffer++;
	}
	WriteComm (0x7E);

	FlushPPPBuf();      // data send out
}

/************************************************************
 * 将形成的IP包打成真正的ppp数据包,准备发出去
 * 这里输入的将是一个完整的IP数据包
 ************************************************************/
void PPPSendIPPacket (BYTE *Buffer, WORD len) {
    WORD Checksum = 0;

	Checksum = PPPGetChecksum (Buffer, len);
	Buffer [len++] = Checksum & 0xFF;
	Buffer [len++] = (Checksum >> 8) & 0xFF;

#ifdef  PPP_PACKET_ANYSIS
    if (BufAnysisIndex<MAX_PPP_BUF_ANYSIS_NUM) {
        memcpy((UB *)BufAnysis[BufAnysisIndex],Buffer,len); // packet save 
        BufAnysisFlag[BufAnysisIndex++]=0;  // send packet 
    }
#endif

    WriteComm(' ');
	WriteComm(0x7E);

	while (len--) {
        
        if (*Buffer < 0x20) {
			WriteComm (0x7D);
			WriteComm (*Buffer ^ 0x20);
		} else {
        
			switch (*Buffer) {
				case 0x7E:
					WriteComm (0x7D);
					WriteComm (0x5E);
				break;

				case 0x7D:
					WriteComm (0x7D);
					WriteComm (0x5D);
				break;

				default:
					WriteComm (*Buffer);
				break;
			}
		}
		Buffer++;
	}
	WriteComm (0x7E);
    
    FlushPPPBuf();      // data send out
}

/***********************************************************************
Function : 	public PPPFrameSize

Parameters : 	None

Date : 		August 2000

Desc : 		Returns the size of the current available PPP packet
		stored in InBuffer. Caller should call this function
		if needed only when the IsFram flag has been signaled. 
		
***********************************************************************/

BYTE PPPFrameSize (void) {
	return FrameSize;
}




/***********************************************************************
Function : 	protected HandleLCPOptions

Parameters : 	None

Date : 		August 2000

Desc : 		State Machine that implements LCP packet negotiation 
		
***********************************************************************/

static void HandleLCPOptions (void) {
    BYTE *dest = OutBuffer;					// A pointer to the options of output buffer
    BYTE *ptr = (BYTE *)&InBuffer[8];			// A pointer to the options of input buffer

	switch (InBuffer[4] ) {

		case LCP_REQ:
            // 下面将分情况讨论各种 option
            if ((InBuffer[8] != 0x03) && (InBuffer[7] > 9)) {
                // 如果option选项有很多项,并且第一项不是3,那么将Reject除3选项外的所有选项
                // 通常都会有1、2、3、7、11、13等选项
                BYTE OptionsSize;
	            BYTE Option;
		        BYTE Size;

                Move(InBuffer, OutBuffer, 8);   // Move LCP header to output buffer
                OutBuffer[4] = LCP_REJ;         // Output will be a reject packet
                dest += 8;                      // Offset output pointer to LCP options
                OptionsSize = InBuffer[7] - 4;  // Get size of LCP options in bytes
                while (OptionsSize > 0) {       // Is there options to process?
                    Option = *ptr;              // Get option number
                    Size = *(ptr + 1);          // Get size of this option

                    OptionsSize -= Size;        // Reduce the amount of OptionsSize 

                    if (Option == 3) {          // Is this option 3? (authentication protocol)
                        ptr += Size;            // Remove this option in output packet
                        OutBuffer[7] = OutBuffer[7] - Size;	// Set New Packet size
                    }
                    else {
                        while (Size-- ) {       // Copy this option to the output buffer
                            *dest++ = *ptr++;
                        }
                    }
                }
            } else if ((InBuffer[8] == 0x02) && (InBuffer[7] <= 0x0A))  {
                // 第一个option是2且仅有一个option项? yes, 去应答
                if ((InBuffer[10] == 0xFF) &&
                    (InBuffer[11] == 0xFF) &&
                    (InBuffer[12] == 0xFF) &&
                    (InBuffer[13] == 0xFF)) {
					
                    InBuffer[4] = LCP_ACK;
                    ProcPPPSend (InBuffer, InBuffer[7] + 6);
                    return;
                }
            } else if ((InBuffer[8] == 0x03) && (InBuffer[10] == 0xC2)) {
                // Server Request CHAP protocol, We reply with
                // a suggestion of the PAP protocol instead
				InBuffer[4] = LCP_NAK;                  // NAK CHAP protocol
				InBuffer[10] = 0xC0;                    // We suggest PAP instead
				ProcPPPSend (InBuffer, InBuffer[7]+6);  // Send the NAK reply
				return;
			} else if ((InBuffer[8] == 0x03) && (InBuffer[10] == 0xC0)) {
                // Server Request PAP protocol //////////
                // We Acknowledge this reply and then we start negotiating
                // the Async-Control-Char..., Here we send both packets!!!
                Move (InBuffer, OutBuffer, InBuffer[7]+6);
                OutBuffer[4] = LCP_ACK;

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

                OutBuffer[4] = LCP_REQ;
                OutBuffer[5] = PPP_PacketID++;        //OutBuffer [5] + 1;
                OutBuffer[7] = 0x0A;
                OutBuffer[8] = 0x02;
                OutBuffer[9] = 0x06;
                OutBuffer[10] = 0xFF;
                OutBuffer[11] = 0xFF;
                OutBuffer[12] = 0xFF;
                OutBuffer[13] = 0xFF;

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

       case LCP_ACK:
            // Server Acknowledge Async Control //////////
            // 本软件只在协调好认证协议方式为PAP后,才发了一个REQ "option 2"的包
            // 这里收到ISP的应答,那么肯定是应答上面的REQ "Option 2"
            // 此时可以开始向ISP发用户名和密码进行认证了
            if (InBuffer[8] == 0x02) {
                SendPAPPacket (LCP_REQ, InBuffer[5] + 1, User, Password);
                PPPStatus |= LCP_FIN;   // LCP协商完成
            }
            break;

        case LCP_NAK:
            break;

        case LCP_REJ:
            break;

		case LCP_TERMINATE:			
            //"ISP Terminate-Request received"
			Move (InBuffer, OutBuffer, InBuffer[7]+6);
			OutBuffer[4] = LCP_TERMINATE_ACK;
			ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);					
			PPPStatus &= ~(LinkOn | LCP_FIN |PAP_FIN);  // 设置ppp断开标志
            EXT_IP_BYTE1=0;     // extern IP Address Reset
            EXT_IP_BYTE2=0;
            EXT_IP_BYTE3=0;
            EXT_IP_BYTE4=0;
            break;
		
        case LCP_TERMINATE_ACK: 
            // 本机发出Terminate REQ后,收到对方Terminate LCP_ACK!
            
            PPPStatus &= ~(LinkOn | LCP_FIN |PAP_FIN);  // 设置ppp断开标志
            EXT_IP_BYTE1=0;     // extern IP Address Reset
            EXT_IP_BYTE2=0;
            EXT_IP_BYTE3=0;
            EXT_IP_BYTE4=0;
            
            break;
            
        case LCP_ECHO_REQ:
			Move (InBuffer, OutBuffer, InBuffer[7]+6);
			OutBuffer[4] = LCP_ECHO_ACK;
			ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);					
            break;
        default:        
            break;            
    }
    return;
}

/***********************************************************************
Function : 	protected HandleIPCPOptions

Parameters : 	None

Date : 		August 2000

Desc : 		State Machine that implement IPCP packet negotiation 
		
***********************************************************************/

static void HandleIPCPOptions (void) {
    BYTE *dest = (BYTE *)&OutBuffer[8];
    BYTE *ptr = (BYTE *)&InBuffer[8];
    BYTE FrameSize;
    BYTE Option;
    BYTE Size;

    switch (InBuffer [4] ) {
        case LCP_REQ:
            if ((InBuffer [8] != 0x03) && (InBuffer [7] > 0x0A)) {
                // 除了"option-3"外,拒绝所有的option选项
                OutBuffer [0] = 0xFF;       // Build a IPCP header 
                OutBuffer [1] = 0x03;
                OutBuffer [2] = 0x80;       // Set IPCP protocol field
                OutBuffer [3] = 0x21;
                OutBuffer [4] = LCP_REJ;    // This will be REJ packet for now
                OutBuffer [5] = InBuffer [5];
                FrameSize = InBuffer[7] - 4;
                //Ignore all but option #3 //
                while (FrameSize > 0) {
                    Option = *ptr;
                    Size = *(ptr + 1);

                    FrameSize -= Size;

                    if (Option == 3) {
                        ptr += Size;
                        //Set New Packet size
                        OutBuffer [7] = InBuffer [7] - Size;	
                    }
                    else {
                        while (Size-- ) {
                        *dest++ = *ptr++;
                        }
                    }
                }
            }
            else {
                // ISP第一次的包实际上可能就返回了ISP自己的IP地址
                // 注意这里ISP用的是REQ命令
                Move (InBuffer, OutBuffer, InBuffer[7]+6);
                OutBuffer [4] = LCP_ACK;
                ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);
                
                // 我们自己的IP地址还没取到,所以要继续Request                        
                OutBuffer [4] = LCP_REQ;    // Request command
                OutBuffer [5] = PPP_PacketID++;   // OutBuffer [5] + 1;  // Packet ID = ID + 1
                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;
            }
            ProcPPPSend ((BYTE *)OutBuffer, OutBuffer[7] + 6);

            break;

        case LCP_ACK:
            if (InBuffer [8] == 0x03) {         // Reply of the only IPCP Request we can send
                // 获得IP地址
                EXT_IP_BYTE1 = InBuffer [10];   // ISP assigned IP address
                EXT_IP_BYTE2 = InBuffer [11];		
                EXT_IP_BYTE3 = InBuffer [12];
                EXT_IP_BYTE4 = InBuffer [13];
				
                //PORTC = 0xFF;

                PPPStatus |= LinkOn;			// PPP Link is now up
            }
            break;

        case LCP_NAK:
            //if ((InBuffer [8] == 0x03) && (InBuffer [7] <= 0x0A)) {
            if ( InBuffer [8] == 0x03 ) {
			    /// 用协商的IP地址向ISP请求一遍

			    // 这里只请求IP地址,如DNS等就不管了,所以将packet长度设"死"!
			    InBuffer[7]=0x0A;   
                Move (InBuffer, OutBuffer, InBuffer[7]+6);
                OutBuffer [4] = LCP_REQ;

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

        case LCP_REJ:
            break;
        default:
            break;            
    }

⌨️ 快捷键说明

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