/* ICMP vrstva komunikacniho modulu pro Ethernet */

#include "stdint.h"
#include "ICMP.h"
#include "IP.h"
#include "net_checksum.h"
#include "net.h"
#include "eth.h"
#include "ENC28J60.h"

extern unsigned char my_MAC[MAC_ADR_SIZE];					// MAC adresa HTTP serveru
extern unsigned char my_IP[IP_ADR_SIZE];					// IP adresa HTTP serveru

/* --------------------------------------------------------------
 Nastavi ICMP hlavicku
 ------------------------------------------------------------- */
void ICMP_Set_ICMP_Header(unsigned char *TX_buffer, unsigned int len, unsigned char type, unsigned char code)
{
	// len - delka Padding dat vcetne hlavicek - tedy celeho paketu!
	uint16_t i;
	TX_buffer[OFFSET_ICMP_Type] = type;
	TX_buffer[OFFSET_ICMP_Code] = code;
	TX_buffer[OFFSET_ICMP_Checksum+0] = 0x00;			// Vynulovani checksumu pred vypoctem
	TX_buffer[OFFSET_ICMP_Checksum+1] = 0x00;
	// Checksum pocitat az nakonec az budou vsechna data ulozena v hlavicce!!!
	i = NET_checksum(&TX_buffer[OFFSET_ICMP_Header], ICMP_Header_len+len, ICMP_TYPE);
	TX_buffer[OFFSET_ICMP_Checksum+0] = (0xFF00&i)>>8;
	TX_buffer[OFFSET_ICMP_Checksum+1] = (0x00FF&i);
}

/* ------------------------------------------------------------------
 Odesle Echo reply - odpoved na ping  (ICMP zprava)
 ----------------------------------------------------------------- */
void ICMP_Send_EchoReply(unsigned char *RX_buffer, unsigned char *TX_buffer, unsigned int len)
{
	unsigned char sourceMAC[MAC_ADR_SIZE];
	unsigned char destMAC[MAC_ADR_SIZE];
	unsigned char sourceIP[IP_ADR_SIZE];
	unsigned char destIP[IP_ADR_SIZE];
	unsigned int i;
	unsigned int Padding_len = 0;
	// Vytvoreni ETH a IP hlavicky
	for(i=0;i<MAC_ADR_SIZE;i++)
	{
		destMAC[i]= RX_buffer[OFFSET_ETH_SourceMAC+i];				// Nastavi zdrojovou MAC z prichoziho paketu
																	// ARP requestu do cilove MAC ARP reply
		sourceMAC[i] = my_MAC[i];									// Jako zdrojovou MAC adresu nastavi lokalni adresu
	}
	for(i=0;i<IP_ADR_SIZE;i++)
	{
		destIP[i] = RX_buffer[OFFSET_IP_SourceIP+i];				// Jako cilovou IP adresu nastavi Zdrojovou IP adresu prijatou v ARP paketu
		sourceIP[i] = my_IP[i];
	}
	ETH_Set_ETH_Header(TX_buffer, destMAC, sourceMAC, ETH_Type_IPv4);	// Nastaveni ETH hlavicky pro IP odpoved	
	// Zkopirovani ICMP Padding dat + Identifer a Seq. number z RX bufferu do TX bufferu
	for(i=OFFSET_ICMP_RestOfHeader;i<len+4;i++)
	{
		TX_buffer[i] = RX_buffer[i];
		Padding_len++;
	}	
	Padding_len = Padding_len - 8;												// Odecteni delky RestOfHeader
	IP_Set_IP_Header(TX_buffer, IP_Header_len+ICMP_Header_len+Padding_len,		// Nastaveni IP hlavicky 
					 (RX_buffer[OFFSET_IP_Identification+0]<<8)|
					 (RX_buffer[OFFSET_IP_Identification+1]),0x00, 250,
					 IP_Protokol_ICMP, sourceIP, destIP);
	ICMP_Set_ICMP_Header(TX_buffer, Padding_len, ICMP_Type_EchoReply,					// Nastaveni ICMP hlavicky
						 ICMP_Type_EchoReply_Code_EchoReply);
	enc28j60PacketSend(ETH_Header_len+IP_Header_len+ICMP_Header_len				// Odeslani odpovedi na Echo request
					   +Padding_len,TX_buffer,0);
}

/* ------------------------------------------------------------------
 Overeni jestli je prichozi paket pozadavkem na Ping reply
 ----------------------------------------------------------------- */
unsigned char ICMP_Check_PingRequest(unsigned char *buffer)
{
	if (buffer[OFFSET_IP_Protokol]==IP_Protokol_ICMP && buffer[OFFSET_ICMP_Type]==ICMP_Type_EchoRequest)
	{
		return(1);
	}
	return(0);
}

/* Konec souboru */
