www.pudn.com > uCOSII上实现的tcpip.rar > zicmp.c


#include "include/zicmp.h"


int icmp_input(znetif_t *pnetif, zbuffer_t *pbuffer)
{
	ip_header_t	*pipheader;
	icmp_echo_header_t *picmp_echo_header;
	eth_header_t *pethheader;

	ipaddr_t tmpipaddr;
	u8_t	i;
	u16_t	hlen;
	u8_t	type;

	
	pipheader =(ip_header_t *) (( u8_t*)pbuffer->pdata + ETH_HEAD_LEN);	/*remenber buffer is whole PACKET*/
	pethheader = (eth_header_t *) (( u8_t*)pbuffer->pdata );
	
	hlen = IPH_HL(pipheader) * 4 + ETH_HEAD_LEN;			/*must jump ETH and IP */
	
	type = *(u8_t *)((u8_t *)pbuffer->pdata + hlen );		/*move to the ICMP header*/
	
	switch(type)
	{
	case ICMP_ECHO:
			if ( pbuffer->tot_len <  ( sizeof(ip_header_t) + sizeof( icmp_echo_header_t) ) )
				return -1;
			picmp_echo_header = (icmp_echo_header_t *)((u8_t *)pbuffer->pdata + hlen );

			/*change src and dest ip*/
			tmpipaddr = pipheader->src_ipaddr;
		    pipheader->src_ipaddr = pipheader->dest_ipaddr;
		    pipheader->dest_ipaddr = tmpipaddr;

			/*change ICMP type*/
			ICMPH_TYPE_SET(picmp_echo_header, ICMP_ER);

			/*change ICMP checksum*/
			if( picmp_echo_header->chksum >= htons(0xffff - (ICMP_ECHO << 8))) 
			{
				picmp_echo_header->chksum += htons(ICMP_ECHO << 8) + 1;
			}
			else
			{
				picmp_echo_header->chksum += htons(ICMP_ECHO << 8);
			}
			/*setup ETH addr */
			for ( i=0 ; i < 6 ; i++)
			{
				pethheader->dest_hwaddr.addr[i] = pethheader->src_hwaddr.addr[i];
				pethheader->src_hwaddr.addr[i] = pnetif->hwaddr.addr[i];
			}
		
			pnetif->netif_tx(pnetif, pbuffer);			
			zbuffer_delete(pbuffer);
			return 0;
			break;
	}
	zbuffer_delete(pbuffer);
	return -1;
}

void icmp_dest_unreach(znetif_t *pnetif, zbuffer_t * pbuffer, enum icmp_dur_type t)
{
	ip_header_t	* pipheader;
	u16_t	offset;
	u8_t	i;
	icmp_dur_header_t	*pdur;
	eth_header_t		*pethheader;
	ipaddr_t		tmpipaddr;

					
	pethheader = (eth_header_t *)(pbuffer->pdata);
	pipheader =(ip_header_t *) (( u8_t*)pbuffer->pdata + ETH_HEAD_LEN);	/*remenber buffer is whole PACKET*/
	offset = IPH_HL(pipheader) * 4 + ETH_HEAD_LEN;
	pdur = (icmp_dur_header_t *)((u8_t *)pbuffer->pdata + offset);


	pbuffer = zbuffer_adjust(pbuffer, 0, (offset + 8 + IP_HEAD_LEN + 8 - pbuffer->tot_len) );
	
	if (pbuffer == NULL )
		return;

	for ( i = 0; i < 8 + IP_HEAD_LEN; i++)
	{
		*(u8_t *)((u8_t *)pbuffer->pdata + offset + i + 8) = *(u8_t *)((u8_t *)pbuffer->pdata + ETH_HEAD_LEN  + i);
	}
	
	for ( i = 0; i < 4; i++)
	{
		*(u8_t *)((u8_t *)pbuffer->pdata + offset + i + 4) = 0x00;
	}
	ICMPH_TYPE_SET(pdur, ICMP_DUR);
	ICMPH_CODE_SET(pdur, t);
	pdur->chksum = 0;
	pdur->chksum = inet_chksum(pdur, 8 + IP_HEAD_LEN + 8);

	/*change src and dest ip and proto and checksum*/
	tmpipaddr = pipheader->src_ipaddr;
	pipheader->src_ipaddr = pipheader->dest_ipaddr;
	pipheader->dest_ipaddr = tmpipaddr;
	pipheader->_len = offset + 8 + IP_HEAD_LEN + 8 - ETH_HEAD_LEN;	/*updata length*/
	pipheader->_ttl_proto &= (0xff00 &  IP_PROTO_ICMP);
	pipheader->_chksum = 0;
	pipheader->_chksum = inet_chksum(pipheader, IPH_HL(pipheader) * 4);

	for ( i=0 ; i < 6 ; i++)
	{
		pethheader->dest_hwaddr.addr[i] = pethheader->src_hwaddr.addr[i];
		pethheader->src_hwaddr.addr[i] = pnetif->hwaddr.addr[i];
	}
	
	pnetif->netif_tx(pnetif, pbuffer);
	zbuffer_delete(pbuffer);

}