blob: e65f6ef67122b0619d5718bcf45b52ad1c52ce58 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - iso_checksum.c
3 * ISO checksum related routines
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <zebra.h>
25#include "iso_checksum.h"
26
27/*
28 * Calculations of the OSI checksum.
29 * ISO/IEC 8473 defines the sum as
30 *
31 * L
32 * sum a (mod 255) = 0
33 * 1 i
34 *
35 * L
36 * sum (L-i+1)a (mod 255) = 0
37 * 1 i
38 *
39 */
40
41/*
42 * Verifies that the checksum is correct.
43 * Return 0 on correct and 1 on invalid checksum.
44 * Based on Annex C.4 of ISO/IEC 8473
45 * FIXME: Check for overflow
46 */
47
48int
hassof390d2c2004-09-10 20:48:21 +000049iso_csum_verify (u_char * buffer, int len, uint16_t * csum)
50{
jardineb5d44e2003-12-23 08:09:43 +000051 u_int8_t *p;
52 u_int32_t c0;
53 u_int32_t c1;
54 u_int16_t checksum;
55 int i;
56
57 p = buffer;
58 checksum = 0;
59 c0 = *csum & 0xff00;
60 c1 = *csum & 0x00ff;
61
62 /*
63 * If both are zero return correct
64 */
65 if (c0 == 0 && c1 == 0)
66 return 0;
67
68 /*
69 * If either, but not both are zero return incorrect
70 */
71 if (c0 == 0 || c1 == 0)
72 return 1;
hassof390d2c2004-09-10 20:48:21 +000073
jardineb5d44e2003-12-23 08:09:43 +000074 /*
75 * Otherwise initialize to zero and calculate...
76 */
77 c0 = 0;
78 c1 = 0;
79
hassof390d2c2004-09-10 20:48:21 +000080 for (i = 0; i < len; i++)
81 {
82 c0 = c0 + *(p++);
83 c1 += c0;
84 }
jardineb5d44e2003-12-23 08:09:43 +000085
86 c0 = c0 % 255;
87 c1 = c1 % 255;
hassof390d2c2004-09-10 20:48:21 +000088
89 if (c0 == 0 && c1 == 0)
jardineb5d44e2003-12-23 08:09:43 +000090 return 0;
91
92 return 1;
93}
94
jardineb5d44e2003-12-23 08:09:43 +000095/*
96 * Creates the checksum. *csum points to the position of the checksum in the
97 * PDU.
98 * Based on Annex C.4 of ISO/IEC 8473
99 * we will not overflow until about length of 6000,
100 * which is the answer to (255+255n)*n/2 > 2^32
101 * so if we have a length of over 5000 we will return zero (for now)
102 */
103#define FIXED_CODE
104u_int16_t
hassof390d2c2004-09-10 20:48:21 +0000105iso_csum_create (u_char * buffer, int len, u_int16_t n)
jardineb5d44e2003-12-23 08:09:43 +0000106{
107
108 u_int8_t *p;
109 int x;
110 int y;
111 u_int32_t mul;
112 u_int32_t c0;
113 u_int32_t c1;
114 u_int16_t checksum;
hassof390d2c2004-09-10 20:48:21 +0000115 u_int16_t *csum;
jardineb5d44e2003-12-23 08:09:43 +0000116 int i;
117
118 checksum = 0;
119
120 /*
121 * Zero the csum in the packet.
122 */
hassof390d2c2004-09-10 20:48:21 +0000123 csum = (u_int16_t *) (buffer + n);
jardineb5d44e2003-12-23 08:09:43 +0000124 *(csum) = checksum;
125
126 /* for the limitation of our implementation */
hassof390d2c2004-09-10 20:48:21 +0000127 if (len > 5000)
128 {
129 return 0;
130 }
jardineb5d44e2003-12-23 08:09:43 +0000131
132 p = buffer;
133 c0 = 0;
134 c1 = 0;
135
hassof390d2c2004-09-10 20:48:21 +0000136 for (i = 0; i < len; i++)
137 {
138 c0 = c0 + *(p++);
139 c1 += c0;
140 }
jardineb5d44e2003-12-23 08:09:43 +0000141
142 c0 = c0 % 255;
143 c1 = c1 % 255;
144
hassof390d2c2004-09-10 20:48:21 +0000145 mul = (len - n) * (c0);
146
jardineb5d44e2003-12-23 08:09:43 +0000147#ifdef FIXED_CODE
148 x = mul - c0 - c1;
149 y = c1 - mul - 1;
150
hassof390d2c2004-09-10 20:48:21 +0000151 if (y >= 0)
152 y++;
153 if (x < 0)
154 x--;
jardineb5d44e2003-12-23 08:09:43 +0000155
156 x %= 255;
157 y %= 255;
158
hassof390d2c2004-09-10 20:48:21 +0000159 if (x == 0)
160 x = 255;
161 if (y == 0)
162 y = 255;
jardineb5d44e2003-12-23 08:09:43 +0000163
164 x &= 0x00FF;
165
166 checksum = ((y << 8) | x);
167
168#else
169 x = mul - c0 - c1;
170 x %= 255;
171
172 y = c1 - mul - 1;
173 y %= 255;
174
hassof390d2c2004-09-10 20:48:21 +0000175 if (x == 0)
176 x = 255;
177 if (y == 0)
178 y = 255;
jardineb5d44e2003-12-23 08:09:43 +0000179
180 checksum = ((y << 8) | x);
181#endif
hassof390d2c2004-09-10 20:48:21 +0000182
jardineb5d44e2003-12-23 08:09:43 +0000183 /*
184 * Now we write this to the packet
185 */
186 *(csum) = checksum;
187
188 /* return the checksum for user usage */
189 return checksum;
190}
191
jardineb5d44e2003-12-23 08:09:43 +0000192int
hassof390d2c2004-09-10 20:48:21 +0000193iso_csum_modify (u_char * buffer, int len, uint16_t * csum)
jardineb5d44e2003-12-23 08:09:43 +0000194{
jardineb5d44e2003-12-23 08:09:43 +0000195 return 0;
196}