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


#include "include/zipv4.h"
#include "include/zicmp.h"
#include "include/zudp.h"
#include "include/ztcp.h"


u16_t ip_id = 0;

static u32_t chksum(void *dataptr, u16_t len)
{
	u32_t acc;

	for(acc = 0; len > 1; len -= 2) 
	{
		acc += *((u16_t *)dataptr)++;
	}

	/* add up any odd byte */
	if(len == 1) 
	{
		acc += (u16_t)((*(u8_t *)dataptr) & 0xff) << 8;
	}

	return acc;
}

u16_t inet_chksum(void *dataptr, u16_t len)
{
	u32_t acc;

	acc = chksum(dataptr, len);
	while(acc >> 16) 
	{
		acc = (acc & 0xffff) + (acc >> 16);
	}
	
	return ~(acc & 0xffff);
}

u16_t inet_chksum_pseudo(zbuffer_t *pbuf_dat, ipaddr_t *src, ipaddr_t *dest, u8_t proto, u16_t proto_len)
{
	u32_t acc;
  	zbuffer_t *q;
  	u8_t swapped;

  	acc = 0;
  	swapped = 0;
 	for(q = pbuf_dat; q != NULL; q = q->next)
	{    
    	acc += chksum(q->pdata, q->len);
    	while(acc >> 16)
		{
      		acc = (acc & 0xffff) + (acc >> 16);
    	}
    	if(q->len % 2 != 0)
		{
      		swapped = 1 - swapped;
      		acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
    	}
  	}

  if(swapped)
  {
    acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
  }
  acc += (*src & 0xffff);
  acc += ((*src >> 16) & 0xffff);
  acc += (*dest & 0xffff);
  acc += ((*dest >> 16) & 0xffff);
  acc += (u32_t)((u16_t)proto);
  acc += (u32_t)(proto_len);  
  
  while(acc >> 16) 
  {
    acc = (acc & 0xffff) + (acc >> 16);
  }    
  return ~(acc & 0xffff);

}	


u8_t ip_input(znetif_t *pnetif, zbuffer_t *pbuffer)
{
	ip_header_t	*pheader;
	u8_t	hl;
			
	pheader = (ip_header_t *)((u8_t *)pbuffer->pdata + ETH_HEAD_LEN);
	
	/*step 1. check this is a ipv4 packet*/
	if(IPH_V(pheader) != 4) 
	{
		zbuffer_delete(pbuffer);
		return -1;
	}

	hl = IPH_HL(pheader);

	/*step 2. the header is too long for our buffer*/
	if(hl * 4 > pbuffer->len) 
	{
		zbuffer_delete(pbuffer);
		return -1;
	}
	
	/*setp 3. we check IPV4 header checksum*/
	if (inet_chksum(pheader, hl * 4) )
	{
		zbuffer_delete(pbuffer);
		return -1;	
	}
	
	/*setup 4. we only check DEST-ip is our ip's packet whithout brocast ip*/
#if 0	
	if ( !((pheader->dest_ipaddr == pnetif->ipaddr) || 
		   (ip_addr_isbroadcast(pheader->dest_ipaddr,pnetif->netmask) &&
			ip_addr_maskcmp(pheader->dest_ipaddr,pnetif->ipaddr,pnetif->netmask) )))
#else
	if ( !(pheader->dest_ipaddr == pnetif->ipaddr) )
#endif

	{
		zbuffer_delete(pbuffer);
		return -1;
	}

	/*step 5. we only check none-fragment ip packet now FIXME*/
	
	if(( IPH_OFFSET(pheader) & (IP_OFFMASK | IP_MF) ) != 0)
	{
		zbuffer_delete(pbuffer);	
		return -1;
	}		

	/*setup 6.we check if length < pbuffer->totlen ) */
	
	if ( pbuffer->tot_len > (IPH_LEN(pheader) + 14) )
	{
		pbuffer = zbuffer_adjust( pbuffer, 0, (-1)*(pbuffer->tot_len - (IPH_LEN(pheader) + 14)));
		if ( pbuffer == NULL)
			return -1;
	}
	
	/*step 7. we will check what type packet this is?*/
	switch(IPH_PROTO(pheader))
	{
		case IP_PROTO_UDP:
				udp_input(pnetif, pbuffer);
				break;
		case IP_PROTO_TCP:				
				tcp_input(pnetif, pbuffer);
				break;
		case IP_PROTO_ICMP:
				return icmp_input(pnetif, pbuffer);
				break;	
		default:
				if ( !ip_addr_isbroadcast((pheader->dest_ipaddr), (pnetif->netmask)) && !ip_addr_ismulticast((pheader->dest_ipaddr)))
				{
					icmp_dest_unreach(pnetif,pbuffer, ICMP_DUR_PROTO);
				}
				else
					zbuffer_delete(pbuffer);
				return -1;
				break;
				
	}
	return 0;
}