]> git.proxmox.com Git - mirror_frr.git/blame - isisd/iso_checksum.c
[isisd] Fix packet filtering with DLPI
[mirror_frr.git] / isisd / iso_checksum.c
CommitLineData
eb5d44eb 1/*
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
eb5d44eb 45 */
46
47int
f390d2c7 48iso_csum_verify (u_char * buffer, int len, uint16_t * csum)
49{
eb5d44eb 50 u_int8_t *p;
51 u_int32_t c0;
52 u_int32_t c1;
53 u_int16_t checksum;
53c997c9 54 int i, partial_len;
eb5d44eb 55
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;
f390d2c7 72
eb5d44eb 73 /*
74 * Otherwise initialize to zero and calculate...
75 */
76 c0 = 0;
77 c1 = 0;
78
53c997c9 79 while (len)
f390d2c7 80 {
53c997c9 81 partial_len = MIN(len, 5803);
82
83 for (i = 0; i < partial_len; i++)
84 {
85 c0 = c0 + *(p++);
86 c1 += c0;
87 }
eb5d44eb 88
53c997c9 89 c0 = c0 % 255;
90 c1 = c1 % 255;
91
92 len -= partial_len;
93 }
f390d2c7 94
95 if (c0 == 0 && c1 == 0)
eb5d44eb 96 return 0;
97
98 return 1;
99}
100
eb5d44eb 101/*
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
eb5d44eb 105 */
106#define FIXED_CODE
107u_int16_t
f390d2c7 108iso_csum_create (u_char * buffer, int len, u_int16_t n)
eb5d44eb 109{
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;
f390d2c7 118 u_int16_t *csum;
53c997c9 119 int i, init_len, partial_len;
eb5d44eb 120
121 checksum = 0;
122
123 /*
124 * Zero the csum in the packet.
125 */
f390d2c7 126 csum = (u_int16_t *) (buffer + n);
eb5d44eb 127 *(csum) = checksum;
128
eb5d44eb 129 p = buffer;
130 c0 = 0;
131 c1 = 0;
53c997c9 132 init_len = len;
eb5d44eb 133
53c997c9 134 while (len != 0)
f390d2c7 135 {
53c997c9 136 partial_len = MIN(len, 5803);
137
138 for (i = 0; i < partial_len; i++)
139 {
140 c0 = c0 + *(p++);
141 c1 += c0;
142 }
eb5d44eb 143
53c997c9 144 c0 = c0 % 255;
145 c1 = c1 % 255;
146
147 len -= partial_len;
148 }
eb5d44eb 149
53c997c9 150 mul = (init_len - n)*(c0);
f390d2c7 151
eb5d44eb 152#ifdef FIXED_CODE
153 x = mul - c0 - c1;
154 y = c1 - mul - 1;
155
53c997c9 156 if (y > 0)
f390d2c7 157 y++;
158 if (x < 0)
159 x--;
eb5d44eb 160
161 x %= 255;
162 y %= 255;
163
f390d2c7 164 if (x == 0)
165 x = 255;
166 if (y == 0)
53c997c9 167 y = 1;
eb5d44eb 168
53c997c9 169 checksum = (y << 8) | (x & 0xFF);
eb5d44eb 170
171#else
172 x = mul - c0 - c1;
173 x %= 255;
174
175 y = c1 - mul - 1;
176 y %= 255;
177
f390d2c7 178 if (x == 0)
179 x = 255;
180 if (y == 0)
181 y = 255;
eb5d44eb 182
183 checksum = ((y << 8) | x);
184#endif
f390d2c7 185
eb5d44eb 186 /*
187 * Now we write this to the packet
188 */
189 *(csum) = checksum;
190
191 /* return the checksum for user usage */
192 return checksum;
193}