checksum.c revision 1.9 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.9 christos __RCSID("$NetBSD: checksum.c,v 1.9 2024/09/02 16:15:29 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.5 christos uint32_t mul;
115 1.5 christos uint32_t c0;
116 1.5 christos uint32_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.1 christos x = mul - c0 - c1;
143 1.1 christos y = c1 - mul - 1;
144 1.1 christos
145 1.1 christos if ( y >= 0 ) y++;
146 1.1 christos if ( x < 0 ) x--;
147 1.1 christos
148 1.1 christos x %= 255;
149 1.1 christos y %= 255;
150 1.1 christos
151 1.1 christos
152 1.1 christos if (x == 0) x = 255;
153 1.1 christos if (y == 0) y = 255;
154 1.1 christos
155 1.1 christos y &= 0x00FF;
156 1.1 christos checksum = ((x << 8) | y);
157 1.5 christos
158 1.1 christos return checksum;
159 1.1 christos }
160