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