blob: eabe281fb30ae61f69f8e91205cfdd3e69730c5c [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
jardineb5d44e2003-12-23 08:09:43 +000045 */
46
47int
hassof390d2c2004-09-10 20:48:21 +000048iso_csum_verify (u_char * buffer, int len, uint16_t * csum)
49{
jardineb5d44e2003-12-23 08:09:43 +000050 u_int8_t *p;
51 u_int32_t c0;
52 u_int32_t c1;
53 u_int16_t checksum;
hasso53c997c2004-09-15 16:21:59 +000054 int i, partial_len;
jardineb5d44e2003-12-23 08:09:43 +000055
56 p = buffer;
57 checksum = 0;
58 c0 = *csum & 0xff00;
59 c1 = *csum & 0x00ff;
60
61 /*
62 * If both are zero return correct
63 */
64 if (c0 == 0 && c1 == 0)
65 return 0;
66
67 /*
68 * If either, but not both are zero return incorrect
69 */
70 if (c0 == 0 || c1 == 0)
71 return 1;
hassof390d2c2004-09-10 20:48:21 +000072
jardineb5d44e2003-12-23 08:09:43 +000073 /*
74 * Otherwise initialize to zero and calculate...
75 */
76 c0 = 0;
77 c1 = 0;
78
hasso53c997c2004-09-15 16:21:59 +000079 while (len)
hassof390d2c2004-09-10 20:48:21 +000080 {
hasso53c997c2004-09-15 16:21:59 +000081 partial_len = MIN(len, 5803);
jardineb5d44e2003-12-23 08:09:43 +000082
hasso53c997c2004-09-15 16:21:59 +000083 for (i = 0; i < partial_len; i++)
84 {
85 c0 = c0 + *(p++);
86 c1 += c0;
87 }
88
89 c0 = c0 % 255;
90 c1 = c1 % 255;
91
92 len -= partial_len;
93 }
hassof390d2c2004-09-10 20:48:21 +000094
95 if (c0 == 0 && c1 == 0)
jardineb5d44e2003-12-23 08:09:43 +000096 return 0;
97
98 return 1;
99}
100
jardineb5d44e2003-12-23 08:09:43 +0000101/*
102 * Creates the checksum. *csum points to the position of the checksum in the
103 * PDU.
104 * Based on Annex C.4 of ISO/IEC 8473
jardineb5d44e2003-12-23 08:09:43 +0000105 */
106#define FIXED_CODE
107u_int16_t
hassof390d2c2004-09-10 20:48:21 +0000108iso_csum_create (u_char * buffer, int len, u_int16_t n)
jardineb5d44e2003-12-23 08:09:43 +0000109{
110
111 u_int8_t *p;
112 int x;
113 int y;
114 u_int32_t mul;
115 u_int32_t c0;
116 u_int32_t c1;
117 u_int16_t checksum;
hassof390d2c2004-09-10 20:48:21 +0000118 u_int16_t *csum;
hasso53c997c2004-09-15 16:21:59 +0000119 int i, init_len, partial_len;
jardineb5d44e2003-12-23 08:09:43 +0000120
121 checksum = 0;
122
123 /*
124 * Zero the csum in the packet.
125 */
hassof390d2c2004-09-10 20:48:21 +0000126 csum = (u_int16_t *) (buffer + n);
jardineb5d44e2003-12-23 08:09:43 +0000127 *(csum) = checksum;
128
jardineb5d44e2003-12-23 08:09:43 +0000129 p = buffer;
130 c0 = 0;
131 c1 = 0;
hasso53c997c2004-09-15 16:21:59 +0000132 init_len = len;
jardineb5d44e2003-12-23 08:09:43 +0000133
hasso53c997c2004-09-15 16:21:59 +0000134 while (len != 0)
hassof390d2c2004-09-10 20:48:21 +0000135 {
hasso53c997c2004-09-15 16:21:59 +0000136 partial_len = MIN(len, 5803);
137
138 for (i = 0; i < partial_len; i++)
139 {
140 c0 = c0 + *(p++);
141 c1 += c0;
142 }
143
144 c0 = c0 % 255;
145 c1 = c1 % 255;
146
147 len -= partial_len;
hassof390d2c2004-09-10 20:48:21 +0000148 }
jardineb5d44e2003-12-23 08:09:43 +0000149
hasso53c997c2004-09-15 16:21:59 +0000150 mul = (init_len - n)*(c0);
hassof390d2c2004-09-10 20:48:21 +0000151
jardineb5d44e2003-12-23 08:09:43 +0000152#ifdef FIXED_CODE
153 x = mul - c0 - c1;
154 y = c1 - mul - 1;
155
hasso53c997c2004-09-15 16:21:59 +0000156 if (y > 0)
hassof390d2c2004-09-10 20:48:21 +0000157 y++;
158 if (x < 0)
159 x--;
jardineb5d44e2003-12-23 08:09:43 +0000160
161 x %= 255;
162 y %= 255;
163
hassof390d2c2004-09-10 20:48:21 +0000164 if (x == 0)
165 x = 255;
166 if (y == 0)
hasso53c997c2004-09-15 16:21:59 +0000167 y = 1;
jardineb5d44e2003-12-23 08:09:43 +0000168
hasso53c997c2004-09-15 16:21:59 +0000169 checksum = (y << 8) | (x & 0xFF);
jardineb5d44e2003-12-23 08:09:43 +0000170
171#else
172 x = mul - c0 - c1;
173 x %= 255;
174
175 y = c1 - mul - 1;
176 y %= 255;
177
hassof390d2c2004-09-10 20:48:21 +0000178 if (x == 0)
179 x = 255;
180 if (y == 0)
181 y = 255;
jardineb5d44e2003-12-23 08:09:43 +0000182
183 checksum = ((y << 8) | x);
184#endif
hassof390d2c2004-09-10 20:48:21 +0000185
jardineb5d44e2003-12-23 08:09:43 +0000186 /*
187 * Now we write this to the packet
188 */
189 *(csum) = checksum;
190
191 /* return the checksum for user usage */
192 return checksum;
193}
194
jardineb5d44e2003-12-23 08:09:43 +0000195int
hassof390d2c2004-09-10 20:48:21 +0000196iso_csum_modify (u_char * buffer, int len, uint16_t * csum)
jardineb5d44e2003-12-23 08:09:43 +0000197{
jardineb5d44e2003-12-23 08:09:43 +0000198 return 0;
199}