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