Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

checksum.h

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 2000,2001 Christopher Cramer <cec@ee.duke.edu>
00004 ** Snort is Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00005 **
00006 ** Copyright (C) 2002 Sourcefire,Inc 
00007 ** Marc Norton <mnorton@sourcefire.com>
00008 **
00009 ** This program is free software; you can redistribute it and/or modify
00010 ** it under the terms of the GNU General Public License as published by
00011 ** the Free Software Foundation; either version 2 of the License, or
00012 ** (at your option) any later version.
00013 **
00014 ** This program is distributed in the hope that it will be useful,
00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 ** GNU General Public License for more details.
00018 **
00019 ** You should have received a copy of the GNU General Public License
00020 ** along with this program; if not, write to the Free Software
00021 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00022 **
00023 **
00024 ** 7/2002 Marc Norton - added inline/optimized checksum routines
00025 **                      these handle all hi/low endian issues
00026 ** 8/2002 Marc Norton - removed old checksum code and prototype
00027 **
00028 */
00029 
00030 #ifndef __CHECKSUM_H__
00031 #define __CHECKSUM_H__
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #include <sys/types.h>
00038 
00039 
00040 /* define checksum error flags */
00041 #define CSE_IP    0x01
00042 #define CSE_TCP   0x02
00043 #define CSE_UDP   0x04
00044 #define CSE_ICMP  0x08
00045 #define CSE_IGMP  0x10
00046 
00047 /*
00048 *  checksum IP  - header=20+ bytes
00049 *
00050 *  w - short words of data
00051 *  blen - byte length
00052 * 
00053 */
00054 static inline unsigned short in_chksum_ip(  unsigned short * w, int blen )
00055 {
00056    unsigned int cksum;
00057 
00058    /* IP must be >= 20 bytes */
00059    cksum  = w[0];
00060    cksum += w[1];
00061    cksum += w[2];
00062    cksum += w[3];
00063    cksum += w[4];
00064    cksum += w[5];
00065    cksum += w[6];
00066    cksum += w[7];
00067    cksum += w[8];
00068    cksum += w[9];
00069 
00070    blen  -= 20;
00071    w     += 10;
00072 
00073    while( blen ) /* IP-hdr must be an integral number of 4 byte words */
00074    {
00075      cksum += w[0];
00076      cksum += w[1];
00077      w     += 2;
00078      blen  -= 4;
00079    }
00080 
00081    cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
00082    cksum += (cksum >> 16);
00083  
00084    return (unsigned short) (~cksum);
00085 }
00086 
00087 
00088 /*
00089 *  checksum tcp
00090 *
00091 *  h    - pseudo header - 12 bytes
00092 *  d    - tcp hdr + payload
00093 *  dlen - length of tcp hdr + payload in bytes
00094 *
00095 */
00096 static inline unsigned short in_chksum_tcp(  unsigned short *h, unsigned short * d, int dlen )
00097 {
00098    unsigned int cksum;
00099    unsigned short answer=0;
00100 
00101    /* PseudoHeader must have 12 bytes */
00102    cksum  = h[0];
00103    cksum += h[1];
00104    cksum += h[2];
00105    cksum += h[3];
00106    cksum += h[4];
00107    cksum += h[5];
00108 
00109    /* TCP hdr must have 20 hdr bytes */
00110    cksum += d[0];
00111    cksum += d[1];
00112    cksum += d[2];
00113    cksum += d[3];
00114    cksum += d[4];
00115    cksum += d[5];
00116    cksum += d[6];
00117    cksum += d[7];
00118    cksum += d[8];
00119    cksum += d[9];
00120 
00121    dlen  -= 20; /* bytes   */
00122    d     += 10; /* short's */ 
00123 
00124    while(dlen >=32)
00125    {
00126      cksum += d[0];
00127      cksum += d[1];
00128      cksum += d[2];
00129      cksum += d[3];
00130      cksum += d[4];
00131      cksum += d[5];
00132      cksum += d[6];
00133      cksum += d[7];
00134      cksum += d[8];
00135      cksum += d[9];
00136      cksum += d[10];
00137      cksum += d[11];
00138      cksum += d[12];
00139      cksum += d[13];
00140      cksum += d[14];
00141      cksum += d[15];
00142      d     += 16;
00143      dlen  -= 32;
00144    }
00145 
00146    while(dlen >=8)  
00147    {
00148      cksum += d[0];
00149      cksum += d[1];
00150      cksum += d[2];
00151      cksum += d[3];
00152      d     += 4;   
00153      dlen  -= 8;
00154    }
00155 
00156    while(dlen > 1)
00157    {
00158      cksum += *d++;
00159      dlen  -= 2;
00160    }
00161 
00162    if( dlen == 1 ) 
00163    { 
00164     /* printf("new checksum odd byte-packet\n"); */
00165     *(unsigned char*)(&answer) = (*(unsigned char*)d);
00166 
00167     /* cksum += (u_int16_t) (*(u_int8_t*)d); */
00168      
00169      cksum += answer;
00170    }
00171    
00172    cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
00173    cksum += (cksum >> 16);
00174  
00175    return (unsigned short)(~cksum);
00176 }
00177 
00178 /*
00179 *  checksum udp
00180 *
00181 *  h    - pseudo header - 12 bytes
00182 *  d    - udp hdr + payload
00183 *  dlen - length of payload in bytes
00184 *
00185 */
00186 static inline unsigned short in_chksum_udp(  unsigned short *h, unsigned short * d, int dlen )
00187 {
00188    unsigned int cksum;
00189    unsigned short answer=0;
00190 
00191    /* PseudoHeader must have  12 bytes */
00192    cksum  = h[0];
00193    cksum += h[1];
00194    cksum += h[2];
00195    cksum += h[3];
00196    cksum += h[4];
00197    cksum += h[5];
00198 
00199    /* UDP must have 8 hdr bytes */
00200    cksum += d[0];
00201    cksum += d[1];
00202    cksum += d[2];
00203    cksum += d[3];
00204 
00205    dlen  -= 8; /* bytes   */
00206    d     += 4; /* short's */ 
00207 
00208    while(dlen >=32) 
00209    {
00210      cksum += d[0];
00211      cksum += d[1];
00212      cksum += d[2];
00213      cksum += d[3];
00214      cksum += d[4];
00215      cksum += d[5];
00216      cksum += d[6];
00217      cksum += d[7];
00218      cksum += d[8];
00219      cksum += d[9];
00220      cksum += d[10];
00221      cksum += d[11];
00222      cksum += d[12];
00223      cksum += d[13];
00224      cksum += d[14];
00225      cksum += d[15];
00226      d     += 16;
00227      dlen  -= 32;
00228    }
00229 
00230    while(dlen >=8)
00231    {
00232      cksum += d[0];
00233      cksum += d[1];
00234      cksum += d[2];
00235      cksum += d[3];
00236      d     += 4;   
00237      dlen  -= 8;
00238    }
00239 
00240    while(dlen > 1) 
00241    {
00242      cksum += *d++;
00243      dlen  -= 2;
00244    }
00245 
00246    if( dlen == 1 ) 
00247    { 
00248      *(unsigned char*)(&answer) = (*(unsigned char*)d);
00249      cksum += answer;
00250    }
00251    
00252    cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
00253    cksum += (cksum >> 16);
00254  
00255    return (unsigned short)(~cksum);
00256 }
00257 
00258 /*
00259 *  checksum icmp
00260 */
00261 static inline unsigned short in_chksum_icmp( unsigned short * w, int blen )
00262 {
00263   unsigned  short answer=0;
00264   unsigned int cksum = 0;
00265 
00266   while(blen >=32) 
00267   {
00268      cksum += w[0];
00269      cksum += w[1];
00270      cksum += w[2];
00271      cksum += w[3];
00272      cksum += w[4];
00273      cksum += w[5];
00274      cksum += w[6];
00275      cksum += w[7];
00276      cksum += w[8];
00277      cksum += w[9];
00278      cksum += w[10];
00279      cksum += w[11];
00280      cksum += w[12];
00281      cksum += w[13];
00282      cksum += w[14];
00283      cksum += w[15];
00284      w     += 16;
00285      blen  -= 32;
00286   }
00287 
00288   while(blen >=8) 
00289   {
00290      cksum += w[0];
00291      cksum += w[1];
00292      cksum += w[2];
00293      cksum += w[3];
00294      w     += 4;
00295      blen  -= 8;
00296   }
00297 
00298   while(blen > 1) 
00299   {
00300      cksum += *w++;
00301      blen  -= 2;
00302   }
00303 
00304   if( blen == 1 ) 
00305   {
00306     *(unsigned char*)(&answer) = (*(unsigned char*)w);
00307     cksum += answer;
00308   }
00309 
00310   cksum  = (cksum >> 16) + (cksum & 0x0000ffff);
00311   cksum += (cksum >> 16);
00312 
00313 
00314   return (unsigned short)(~cksum);
00315 }
00316 
00317 #endif /* __CHECKSUM_H__ */

Generated on Sun May 14 14:51:12 2006 by  doxygen 1.4.2