File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / coova-chilli / src / chksum.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:48:25 2012 UTC (13 years, 1 month ago) by misho
Branches: coova-chilli, MAIN
CVS tags: v1_0_12, HEAD
coova-chilli

    1: /*
    2:  * Chksum library functions
    3:  * Copyright (c) 2006-2008 David Bird <david@coova.com>
    4:  *
    5:  * The contents of this file may be used under the terms of the GNU
    6:  * General Public License Version 2, provided that the above copyright
    7:  * notice and this permission notice is included in all copies or
    8:  * substantial portions of the software.
    9:  *
   10:  */
   11: 
   12: #include "system.h"
   13: #include "pkt.h"
   14: #include "options.h"
   15: #include "syserr.h"
   16: 
   17: #define cksum_wrap(c) (c=(c>>16)+(c&0xffff),(~(c+(c>>16))&0xffff))
   18: 
   19: int
   20: in_cksum(uint16_t *addr, size_t len)
   21: {
   22:   size_t      nleft = len;
   23:   uint32_t    sum = 0;
   24:   uint16_t  * w = addr;
   25:   
   26:   while (nleft > 1)  {
   27:     sum += *w++;
   28:     nleft -= 2;
   29:   }
   30:   
   31:   if (nleft == 1) {
   32:     uint16_t ans = 0;
   33:     *(unsigned char *)(&ans) = *(unsigned char *)w ;
   34:     sum += ans;
   35:   }
   36:   
   37:   return(sum);
   38: }
   39: 
   40: int chksum(struct pkt_iphdr_t *iph) {
   41:   size_t hlen = (iph->version_ihl & 0x0f) << 2;
   42:   int sum;
   43: 
   44:   switch(iph->protocol) {
   45:   case PKT_IP_PROTO_TCP:
   46:     {
   47:       struct pkt_tcphdr_t *tcph = (struct pkt_tcphdr_t *)(((void *)iph) + hlen);
   48:       size_t len = (size_t)ntohs(iph->tot_len);
   49:       
   50:       if (len > 2000) return -1; /* too long? */
   51:       
   52:       len -= (iph->version_ihl & 0x0f) << 2;
   53:       
   54:       if (len < 20) return -1;  /* too short? */
   55:       
   56:       tcph->check = 0;
   57:       sum = in_cksum(((uint16_t *)iph)+6/*saddr*/, 8);
   58:       sum += ntohs(IPPROTO_TCP + len);
   59:       sum += in_cksum((uint16_t *)tcph, len);
   60:       tcph->check = cksum_wrap(sum);
   61:     }
   62:     break;
   63:     
   64:   case PKT_IP_PROTO_UDP:
   65:     {
   66:       struct pkt_udphdr_t *udph = (struct pkt_udphdr_t *)(((void *)iph) + hlen);
   67:       size_t len = (size_t)ntohs(udph->len);
   68:       
   69:       udph->check = 0;
   70:       sum = in_cksum(((uint16_t *)iph)+6/*saddr*/, 8);
   71:       sum += ntohs(IPPROTO_UDP + len);
   72:       sum += in_cksum((uint16_t *)udph, len);
   73:       udph->check = cksum_wrap(sum);
   74:     }
   75:     break;
   76:   }
   77:   
   78:   iph->check = 0;
   79:   sum = in_cksum((uint16_t *)iph, hlen);
   80:   iph->check = cksum_wrap(sum);
   81:   
   82:   return 0;
   83: }
   84: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>