Home | History | Annotate | Line # | Download | only in dist
checksum.c revision 1.1
      1  1.1  christos /*
      2  1.1  christos  * Copyright (c) 1998-2006 The TCPDUMP project
      3  1.1  christos  *
      4  1.1  christos  * Redistribution and use in source and binary forms, with or without
      5  1.1  christos  * modification, are permitted provided that: (1) source code
      6  1.1  christos  * distributions retain the above copyright notice and this paragraph
      7  1.1  christos  * in its entirety, and (2) distributions including binary code include
      8  1.1  christos  * the above copyright notice and this paragraph in its entirety in
      9  1.1  christos  * the documentation or other materials provided with the distribution.
     10  1.1  christos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
     11  1.1  christos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
     12  1.1  christos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     13  1.1  christos  * FOR A PARTICULAR PURPOSE.
     14  1.1  christos  *
     15  1.1  christos  * miscellaneous checksumming routines
     16  1.1  christos  *
     17  1.1  christos  * Original code by Hannes Gredler (hannes (at) juniper.net)
     18  1.1  christos  */
     19  1.1  christos 
     20  1.1  christos #ifndef lint
     21  1.1  christos static const char rcsid[] _U_ =
     22  1.1  christos     "@(#) Header: /tcpdump/master/tcpdump/checksum.c,v 1.4 2006-09-25 09:23:32 hannes Exp";
     23  1.1  christos #endif
     24  1.1  christos 
     25  1.1  christos #ifdef HAVE_CONFIG_H
     26  1.1  christos #include "config.h"
     27  1.1  christos #endif
     28  1.1  christos 
     29  1.1  christos #include <tcpdump-stdinc.h>
     30  1.1  christos 
     31  1.1  christos #include <stdio.h>
     32  1.1  christos #include <stdlib.h>
     33  1.1  christos #include <string.h>
     34  1.1  christos #include <assert.h>
     35  1.1  christos 
     36  1.1  christos #include "interface.h"
     37  1.1  christos 
     38  1.1  christos /*
     39  1.1  christos  * CRC-10 table generated using the following Python snippet:
     40  1.1  christos 
     41  1.1  christos import sys
     42  1.1  christos 
     43  1.1  christos crc_table = []
     44  1.1  christos for i in range(256):
     45  1.1  christos 	accum = i << 2
     46  1.1  christos 	for j in range(8):
     47  1.1  christos 		accum <<= 1
     48  1.1  christos 		if accum & 0x400:
     49  1.1  christos 			accum ^= 0x633
     50  1.1  christos 	crc_table.append(accum)
     51  1.1  christos 
     52  1.1  christos for i in range(len(crc_table)/8):
     53  1.1  christos 	for j in range(8):
     54  1.1  christos 		sys.stdout.write("0x%04x, " % crc_table[i*8+j])
     55  1.1  christos 	sys.stdout.write("\n")
     56  1.1  christos 
     57  1.1  christos  */
     58  1.1  christos static const u_int16_t crc10_table[256] =
     59  1.1  christos {
     60  1.1  christos 	0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
     61  1.1  christos 	0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
     62  1.1  christos 	0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
     63  1.1  christos 	0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
     64  1.1  christos 	0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
     65  1.1  christos 	0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
     66  1.1  christos 	0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
     67  1.1  christos 	0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
     68  1.1  christos 	0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
     69  1.1  christos 	0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
     70  1.1  christos 	0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
     71  1.1  christos 	0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
     72  1.1  christos 	0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
     73  1.1  christos 	0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
     74  1.1  christos 	0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
     75  1.1  christos 	0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
     76  1.1  christos 	0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
     77  1.1  christos 	0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
     78  1.1  christos 	0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
     79  1.1  christos 	0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
     80  1.1  christos 	0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
     81  1.1  christos 	0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
     82  1.1  christos 	0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
     83  1.1  christos 	0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
     84  1.1  christos 	0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
     85  1.1  christos 	0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
     86  1.1  christos 	0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
     87  1.1  christos 	0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
     88  1.1  christos 	0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
     89  1.1  christos 	0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
     90  1.1  christos 	0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
     91  1.1  christos 	0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1
     92  1.1  christos };
     93  1.1  christos 
     94  1.1  christos static void
     95  1.1  christos init_crc10_table(void)
     96  1.1  christos {
     97  1.1  christos #define CRC10_POLYNOMIAL 0x633
     98  1.1  christos     register int i, j;
     99  1.1  christos     register u_int16_t accum;
    100  1.1  christos     u_int16_t verify_crc10_table[256];
    101  1.1  christos 
    102  1.1  christos     for ( i = 0;  i < 256;  i++ )
    103  1.1  christos     {
    104  1.1  christos         accum = ((unsigned short) i << 2);
    105  1.1  christos         for ( j = 0;  j < 8;  j++ )
    106  1.1  christos         {
    107  1.1  christos             if ((accum <<= 1) & 0x400) accum ^= CRC10_POLYNOMIAL;
    108  1.1  christos         }
    109  1.1  christos         verify_crc10_table[i] = accum;
    110  1.1  christos     }
    111  1.1  christos     assert(memcmp(verify_crc10_table,
    112  1.1  christos 				  crc10_table,
    113  1.1  christos 				  sizeof(verify_crc10_table)) == 0);
    114  1.1  christos #undef CRC10_POLYNOMIAL
    115  1.1  christos }
    116  1.1  christos 
    117  1.1  christos u_int16_t
    118  1.1  christos verify_crc10_cksum(u_int16_t accum, const u_char *p, int length)
    119  1.1  christos {
    120  1.1  christos     register int i;
    121  1.1  christos 
    122  1.1  christos     for ( i = 0;  i < length;  i++ )
    123  1.1  christos     {
    124  1.1  christos         accum = ((accum << 8) & 0x3ff)
    125  1.1  christos             ^ crc10_table[( accum >> 2) & 0xff]
    126  1.1  christos             ^ *p++;
    127  1.1  christos     }
    128  1.1  christos     return accum;
    129  1.1  christos }
    130  1.1  christos 
    131  1.1  christos /* precompute checksum tables */
    132  1.1  christos void
    133  1.1  christos init_checksum(void) {
    134  1.1  christos 
    135  1.1  christos     init_crc10_table();
    136  1.1  christos 
    137  1.1  christos }
    138  1.1  christos 
    139  1.1  christos /*
    140  1.1  christos  * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
    141  1.1  christos  * The checksum field of the passed PDU does not need to be reset to zero.
    142  1.1  christos  */
    143  1.1  christos u_int16_t
    144  1.1  christos create_osi_cksum (const u_int8_t *pptr, int checksum_offset, int length)
    145  1.1  christos {
    146  1.1  christos 
    147  1.1  christos     int x;
    148  1.1  christos     int y;
    149  1.1  christos     u_int32_t mul;
    150  1.1  christos     u_int32_t c0;
    151  1.1  christos     u_int32_t c1;
    152  1.1  christos     u_int16_t checksum;
    153  1.1  christos     int index;
    154  1.1  christos 
    155  1.1  christos     checksum = 0;
    156  1.1  christos 
    157  1.1  christos     c0 = 0;
    158  1.1  christos     c1 = 0;
    159  1.1  christos 
    160  1.1  christos     for (index = 0; index < length; index++) {
    161  1.1  christos         /*
    162  1.1  christos          * Ignore the contents of the checksum field.
    163  1.1  christos          */
    164  1.1  christos         if (index == checksum_offset ||
    165  1.1  christos             index == checksum_offset+1) {
    166  1.1  christos             c1 += c0;
    167  1.1  christos             pptr++;
    168  1.1  christos         } else {
    169  1.1  christos             c0 = c0 + *(pptr++);
    170  1.1  christos             c1 += c0;
    171  1.1  christos         }
    172  1.1  christos     }
    173  1.1  christos 
    174  1.1  christos     c0 = c0 % 255;
    175  1.1  christos     c1 = c1 % 255;
    176  1.1  christos 
    177  1.1  christos     mul = (length - checksum_offset)*(c0);
    178  1.1  christos 
    179  1.1  christos     x = mul - c0 - c1;
    180  1.1  christos     y = c1 - mul - 1;
    181  1.1  christos 
    182  1.1  christos     if ( y >= 0 ) y++;
    183  1.1  christos     if ( x < 0 ) x--;
    184  1.1  christos 
    185  1.1  christos     x %= 255;
    186  1.1  christos     y %= 255;
    187  1.1  christos 
    188  1.1  christos 
    189  1.1  christos     if (x == 0) x = 255;
    190  1.1  christos     if (y == 0) y = 255;
    191  1.1  christos 
    192  1.1  christos     y &= 0x00FF;
    193  1.1  christos     checksum = ((x << 8) | y);
    194  1.1  christos 
    195  1.1  christos     return checksum;
    196  1.1  christos }
    197