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

📄 icmp.c

📁 AVR单片机系统开发经典实例部分源程序
💻 C
字号:

/*
 * Copyright (C) 2003-2004 by Clive Moss All rights reserved.
 *
 * Help & Contributions from D.J.Armstrong

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CLIVE MOSS 'AS IS' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.
 * IN NO EVENT SHALL CLIVE MOSS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

//#ifdef CPU_eZ8
//	#pragma stkck									// enable stack checking
//#endif

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "common.h"
#include "ppp.h"
#include "ip.h"
#include "icmp.h"

#ifdef Debug
flash char	icmp_str1[]	=	"    ICMPHdr: type:";
flash char	icmp_str2[]	=	" Code:";
flash char	icmp_str3[]	=	" Chksum:";
flash char	icmp_str4[]	=	" ID:";
flash char	icmp_str5[]	=	" SeqNum:";
flash char	icmp_str6[]	=	" DataBytes:";
flash char	icmp_str7[]	=	" - BLOCKED\n";
flash char	icmp_str8[]	=	"*** ICMP chksum err\n";
#endif

#ifdef CPU_eZ8
volatile near u16		ICMP_Timer;
volatile near u16		ICMP_SeqNum;
volatile near T_IP_Addr	ICMP_IP;
#endif
#ifdef CPU_ATmega128
volatile u16			ICMP_Timer;
volatile u16			ICMP_SeqNum;
volatile T_IP_Addr		ICMP_IP;
#endif

T_ICMP_Header	*ICMP_Header = NULL;

// **************************************************************************

#ifdef Debug

void ICMP_DisplayHeader(int HeaderIdx, int TotalBytes)
{

/*
	 0                   1                   2                   3
	 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|    Type       |    Code       |         Checksum              |
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	|             ID                |      Sequence Number          |
	+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/

	// show the header

	if (!SendDebugRStr(icmp_str1)) return;
	sprintf((char*)ScratchPad, "%u", ICMP_Header->Type);
	if (!SendDebugStr((char*)ScratchPad)) return;

	if (!SendDebugRStr(icmp_str2)) return;
	sprintf((char*)ScratchPad, "%u", ICMP_Header->Code);
	if (!SendDebugStr((char*)ScratchPad)) return;

	if (!SendDebugRStr(icmp_str3)) return;
	sprintf((char*)ScratchPad, "%04X", ntohs(ICMP_Header->Checksum));
	if (!SendDebugStr((char*)ScratchPad)) return;

	if (!SendDebugRStr(icmp_str4)) return;
	sprintf((char*)ScratchPad, "%u", ntohs(ICMP_Header->ID));
	if (!SendDebugStr((char*)ScratchPad)) return;

	if (!SendDebugRStr(icmp_str5)) return;
	sprintf((char*)ScratchPad, "%u", ntohs(ICMP_Header->SeqNum));
	if (!SendDebugStr((char*)ScratchPad)) return;

	// done

	if (!SendDebugRStr(icmp_str6)) return;
	sprintf((char*)ScratchPad, "%u\n", TotalBytes - (HeaderIdx + sizeof(T_ICMP_Header)));
	if (!SendDebugStr((char*)ScratchPad)) return;
}

#endif

// **************************************************************************

void ICMP_In(void)
{
	u16 len;
	u32	dw;

	// **********************

	len = MainBufferWr_Rx - MainBufferRd_Rx;							// length of data left
																		//
	ICMP_Header = (T_ICMP_Header*)(MainBuffer + MainBufferRd_Rx);		// point to the ICMP header
																		//
	if (!ICMP_Header->Checksum) return;									// invalid checksum
	if (IP_Checksum1((char*)ICMP_Header, len))							//
	{																	// invalid checksum
		#ifdef Debug
			SendDebugRStr(icmp_str8);									//
		#endif
		return;															//
	}

	#ifdef Debug
		ICMP_DisplayHeader(MainBufferRd_Rx, MainBufferWr_Rx);			//
	#endif

	MainBufferRd_Rx += sizeof(T_ICMP_Header);							//

	// **********************

	if (ICMP_Header->Type == ICMP_ECHO_REQUEST)
	{	// PING
		if (IP_FireWalled())
		{
			#ifdef Debug
				SendDebugRStr(icmp_str7);
			#endif
			return;									// firewalled
		}

		// send a PONG - eeeewwwww

		IP_Header->ID = htons(IP_ID++);

		// first swap the ip addresses
		dw = IP_Header->SourceIP.ip32;
		IP_Header->SourceIP.ip32 = IP_Header->DestIP.ip32;
		IP_Header->DestIP.ip32 = dw;

		// now the packet type
		ICMP_Header->Type = ICMP_ECHO_REPLY;

		// update checksums
		ICMP_Header->Checksum = 0;
		ICMP_Header->Checksum = htons(IP_Checksum1((char*)ICMP_Header, len));
		IP_Header->Checksum = 0;
		IP_Header->Checksum = htons(IP_Checksum1((char*)IP_Header, (IP_Header->VerLen & 0x0f) << 2));
																	//
		MainBufferWr_Tx = MainBufferWr_Rx;							// number of bytes to the packet we are sending back

		len = MainBufferWr_Tx;										//

		if (!PPP_SendPacket(false)) return;							// send it

		#ifdef Debug
			IP_DisplayProtocol(true, len);							//
			IP_DisplayHeader(4, len);								//
			ICMP_DisplayHeader(4 + sizeof(T_IP_Header), len);		//
		#endif

		return;
	}

	// **********************

	if (ICMP_Header->Type == ICMP_ECHO_REPLY)
	{	// PONG
		#ifdef Debug
			SendDebugStr("\n");
		#endif

		if ((ICMP_SeqNum) && (ntohs(ICMP_Header->SeqNum) == ICMP_SeqNum) && (IP_Header->SourceIP.ip32 == ICMP_IP.ip32))
		{																	//
			ICMP_SeqNum = 0;												//
			ICMP_IP.ip32 = 0;												//
																			//
			sprintf((char*)ScratchPad, "   pong: %ums\n", ICMP_Timer);		//
			SendConsoleStr((char*)ScratchPad);								//
		}																	//

		return;
	}

	// **********************
}

// **************************************************************************
// send a ping out

bool ICMP_Out(u32 IP)
{
	u16	w, w2, RandNum, len;

	if (!IP) return false;															// no IP supplied
	if (MainBufferWr_Rx > 0) return false;											// buffer is not yet free
	if (MainBufferWr_Tx) return false;												// buffer is not yet free

	for (RandNum = 0; !RandNum; ) RandNum = (u16)rand();							//

	// start the packet off (IP header etc)
	IP_StartPacket(IP_PROTO_ICMP, IP);												// start the IP packet off

	len = MainBufferWr_Tx;															//

	// add the ICMP header
	ICMP_Header = (T_ICMP_Header*)(MainBuffer + MainBufferWr_Tx);					// point to the ICMP header
	memset(ICMP_Header, 0, sizeof(T_ICMP_Header));									// clear it
	ICMP_Header->Type = ICMP_ECHO_REQUEST;											//
	ICMP_Header->Code = 0;															//
	ICMP_Header->ID = htons(IP_ID++);												// use the IP ID - for now
	ICMP_Header->SeqNum = htons(RandNum);											// sequence number
	MainBufferWr_Tx += sizeof(T_ICMP_Header);										// update index
																					//
	// add the ICMP data															//
	for (w = 0; w < 47; w++) MainBuffer[MainBufferWr_Tx++] = (u8)w;					// add some data - any data
																					//
	len = MainBufferWr_Tx - len;													//
																					//
	w2 = MainBufferWr_Tx;															//
																					//
	w = IP_Checksum1((char*)ICMP_Header, len);										// update the ICMP header checksum
//	if (!w) w = 0xffff;																//
	ICMP_Header->Checksum = htons(w);												//
																					//
	IP_Header->TotalLength += len;													// update the IP header
																					//
	IP_EndPacket();																	//
																					//
	if (!PPP_SendPacket(false)) return false;										// send it
																					//
	ICMP_Timer = 0;																	// reset the timer
	ICMP_SeqNum = RandNum;															// remember the sequence number
	ICMP_IP.ip32 = IP;																// and the ip

	#ifdef Debug
		IP_DisplayProtocol(true, (int)w2);											//
		IP_DisplayHeader(4, (int)w2);												//
		ICMP_DisplayHeader(4 + sizeof(T_IP_Header), (int)w2);						//
	#endif

	return true;
}

// **************************************************************************
// this is called from the ip module - every 10ms

void ICMP_10ms_Timer(void)
{
	if (ICMP_Timer < 5000)										//
		ICMP_Timer += 10;										// update the timer
	else														//
	{															//
		ICMP_SeqNum = 0;										// 5 seconds have gone by - ignore any ICMP echo's
		ICMP_IP.ip32 = 0;										//
	}															//
}

// **************************************************************************

⌨️ 快捷键说明

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