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;
}