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