📄 icmp.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 + -