blob: 306ad1b51358676c065837ba44dee98c29212003 [file] [log] [blame]
Dhruv Dhody43f3ce62016-02-16 22:44:21 +05301/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ospf.protocol.util;
17
18import org.onosproject.ospf.controller.OspfLsa;
19import org.onosproject.ospf.controller.OspfLsaType;
20import org.onosproject.ospf.protocol.lsa.types.AsbrSummaryLsa;
21import org.onosproject.ospf.protocol.lsa.types.ExternalLsa;
22import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
23import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10;
24import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa11;
25import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa9;
26import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
27import org.onosproject.ospf.protocol.lsa.types.SummaryLsa;
28import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
29import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
30import org.onosproject.ospf.protocol.ospfpacket.types.HelloPacket;
31import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
32import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
33import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
34
35import java.util.Arrays;
36
37/**
38 * Calculates checksum for different types of OSPF packets.
39 */
40public class ChecksumCalculator {
41
42 /**
43 * Converts given string to sixteen bits integer.
44 * If hexasum is more than 16 bit value, needs to be reduced to 16 bit value.
45 *
46 * @param strToConvert hexasum value to convert
47 * @return 16 bit integer value
48 */
49 public static int convertToSixteenBits(String strToConvert) {
50 StringBuilder sb = new StringBuilder(strToConvert);
51 sb = sb.reverse();
52 StringBuilder s1 = new StringBuilder(sb.substring(0, 4));
53 s1 = s1.reverse();
54 StringBuilder s2 = new StringBuilder(sb.substring(4, sb.length()));
55 s2 = s2.reverse();
56 int num = Integer.parseInt(s1.toString(), 16) + Integer.parseInt(s2.toString(), 16);
57 return num;
58 }
59
60 /**
61 * Checks whether checksum is valid or not in the given OSPF message.
62 *
63 * @param ospfMessage ospf message instance
64 * @param checksumPos1 position of checksum bit in packet
65 * @param checksumPos2 position of checksum bit in packet
66 * @return true if valid else false
67 */
68 public boolean isValidOspfCheckSum(OspfMessage ospfMessage, int checksumPos1, int checksumPos2) {
69
70 switch (ospfMessage.ospfMessageType().value()) {
71 case OspfParameters.HELLO:
72 ospfMessage = (HelloPacket) ospfMessage;
73 break;
74 case OspfParameters.DD:
75 ospfMessage = (DdPacket) ospfMessage;
76 break;
77 case OspfParameters.LSREQUEST:
78 ospfMessage = (LsRequest) ospfMessage;
79 break;
80 case OspfParameters.LSUPDATE:
81 ospfMessage = (LsUpdate) ospfMessage;
82 break;
83 case OspfParameters.LSACK:
84 ospfMessage = (LsAcknowledge) ospfMessage;
85 break;
86 default:
87 break;
88 }
89
90 byte[] messageAsBytes = ospfMessage.asBytes();
91 return validateOspfCheckSum(messageAsBytes, checksumPos1, checksumPos2);
92 }
93
94 /**
95 * Checks whether checksum is valid or not in the given OSPF LSA.
96 *
97 * @param ospfLsa lsa instance
98 * @param lsType lsa type
99 * @param lsaChecksumPos1 lsa checksum position in packet
100 * @param lsaChecksumPos2 lsa checksum position in packet
101 * @return true if valid else false
102 * @throws Exception might throw exception while processing
103 */
104 public boolean isValidLsaCheckSum(OspfLsa ospfLsa, int lsType, int lsaChecksumPos1,
105 int lsaChecksumPos2) throws Exception {
106 if (lsType == OspfLsaType.ROUTER.value()) {
107 RouterLsa lsa = (RouterLsa) ospfLsa;
108 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
109 } else if (lsType == OspfLsaType.NETWORK.value()) {
110 NetworkLsa lsa = (NetworkLsa) ospfLsa;
111 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
112 } else if (lsType == OspfLsaType.SUMMARY.value()) {
113 SummaryLsa lsa = (SummaryLsa) ospfLsa;
114 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
115 } else if (lsType == OspfLsaType.ASBR_SUMMARY.value()) {
116 AsbrSummaryLsa lsa = (AsbrSummaryLsa) ospfLsa;
117 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
118 } else if (lsType == OspfLsaType.EXTERNAL_LSA.value()) {
119 ExternalLsa lsa = (ExternalLsa) ospfLsa;
120 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
121 } else if (lsType == OspfLsaType.LINK_LOCAL_OPAQUE_LSA.value()) {
122 OpaqueLsa9 lsa = (OpaqueLsa9) ospfLsa;
123 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
124 } else if (lsType == OspfLsaType.AREA_LOCAL_OPAQUE_LSA.value()) {
125 OpaqueLsa10 lsa = (OpaqueLsa10) ospfLsa;
126 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
127 } else if (lsType == OspfLsaType.AS_OPAQUE_LSA.value()) {
128 OpaqueLsa11 lsa = (OpaqueLsa11) ospfLsa;
129 return validateLsaCheckSum(lsa.asBytes(), lsaChecksumPos1, lsaChecksumPos2);
130 }
131
132 return false;
133 }
134
135 /**
136 * Verifies the checksum is valid in given LSA packet bytes.
137 *
138 * @param lsaPacket lsa as byte array
139 * @param lsaChecksumPos1 position of checksum bit in packet
140 * @param lsaChecksumPos2 position of checksum bit in packet
141 * @return true if valid else false
142 */
143 public boolean validateLsaCheckSum(byte[] lsaPacket, int lsaChecksumPos1, int lsaChecksumPos2) {
144
145 byte[] checksum = calculateLsaChecksum(lsaPacket, lsaChecksumPos1, lsaChecksumPos2);
146
147 if (lsaPacket[lsaChecksumPos1] == checksum[0] && lsaPacket[lsaChecksumPos2] == checksum[1]) {
148 return true;
149 }
150
151 return false;
152 }
153
154 /**
155 * Verifies the checksum is valid in given OSPF packet bytes.
156 *
157 * @param ospfPacket as byte array
158 * @param checksumPos1 position of checksum bit in packet
159 * @param checksumPos2 position of checksum bit in packet
160 * @return true if valid else false
161 */
162 public boolean validateOspfCheckSum(byte[] ospfPacket, int checksumPos1, int checksumPos2) {
163
164 byte[] checkSum = calculateOspfCheckSum(ospfPacket, checksumPos1, checksumPos2);
165
166 if (ospfPacket[checksumPos1] == checkSum[0] && ospfPacket[checksumPos2] == checkSum[1]) {
167 return true;
168 }
169
170 return false;
171 }
172
173 /**
174 * Calculates the LSA checksum.
175 *
176 * @param lsaBytes as byte array
177 * @param lsaChecksumPos1 position of checksum bit in packet
178 * @param lsaChecksumPos2 position of checksum bit in packet
179 * @return checksum bytes
180 */
181 public byte[] calculateLsaChecksum(byte[] lsaBytes, int lsaChecksumPos1, int lsaChecksumPos2) {
182
183 byte[] tempLsaByte = Arrays.copyOf(lsaBytes, lsaBytes.length);
184
185 int[] checksumOut = {0, 0};
186 tempLsaByte[lsaChecksumPos1] = 0;
187 tempLsaByte[lsaChecksumPos2] = 0;
188 byte[] byteCheckSum = {0, 0};
189 if (lsaBytes != null) {
190 for (int i = 2; i < tempLsaByte.length; i++) {
191 checksumOut[0] = checksumOut[0] + ((int) tempLsaByte[i] & 0xFF);
192 checksumOut[1] = checksumOut[1] + checksumOut[0];
193 }
194 checksumOut[0] = checksumOut[0] % 255;
195 checksumOut[1] = checksumOut[1] % 255;
196 }
197 int byte1 = (int) ((tempLsaByte.length - lsaChecksumPos1 - 1) * checksumOut[0] - checksumOut[1]) % 255;
198 if (byte1 <= 0) {
199 byte1 += 255;
200 }
201 int byte2 = 510 - checksumOut[0] - byte1;
202 if (byte2 > 255) {
203 byte2 -= 255;
204 }
205
206 byteCheckSum[0] = (byte) byte1;
207 byteCheckSum[1] = (byte) byte2;
208
209 return byteCheckSum;
210 }
211
212 /**
213 * Calculate checksum from hexasum.
214 *
215 * @param hexasum total of 16 bits hexadecimal values
216 * @return checksum value
217 */
218 private int calculateChecksum(int hexasum) {
219
220 char[] tempZeros = {'0', '0', '0', '0'};
221 StringBuffer hexaAsBinaryStr = new StringBuffer(Integer.toBinaryString(hexasum));
222 int length = hexaAsBinaryStr.length();
223 while (length > 16) {
224 if (hexaAsBinaryStr.length() % 4 != 0) {
225 int offset = hexaAsBinaryStr.length() % 4;
226 hexaAsBinaryStr.insert(0, tempZeros, 0, 4 - offset);
227 }
228 StringBuffer hexaStr1 = new StringBuffer(hexaAsBinaryStr.reverse().substring(0, 16));
229 String revHexaStr1 = hexaStr1.reverse().toString();
230 StringBuffer hexaStr2 = new StringBuffer(hexaAsBinaryStr.reverse());
231 StringBuffer hexaStr3 = new StringBuffer(hexaStr2.reverse().substring(16, hexaStr2.length()));
232 String revHexaStr3 = hexaStr3.reverse().toString();
233 int lastSixteenHexaBits = Integer.parseInt(revHexaStr1, 2);
234 int remainingHexaBits = Integer.parseInt(revHexaStr3, 2);
235 int totalCheckSum = lastSixteenHexaBits + remainingHexaBits;
236 hexaAsBinaryStr = new StringBuffer(Integer.toBinaryString(totalCheckSum));
237 length = hexaAsBinaryStr.length();
238 }
239 if (hexaAsBinaryStr.length() < 16) {
240 int count = 16 - hexaAsBinaryStr.length();
241 String s = hexaAsBinaryStr.toString();
242 for (int i = 0; i < count; i++) {
243 s = "0" + s;
244 }
245
246 hexaAsBinaryStr = new StringBuffer(s);
247
248 }
249 StringBuffer checksum = negate(hexaAsBinaryStr);
250 return Integer.parseInt(checksum.toString(), 2);
251 }
252
253 /**
254 * Negates given hexasum.
255 *
256 * @param binaryString binary form of hexasum
257 * @return binary from of calculateChecksum
258 */
259 private StringBuffer negate(StringBuffer binaryString) {
260 for (int i = 0; i < binaryString.length(); i++) {
261 if (binaryString.charAt(i) == '1') {
262 binaryString.replace(i, i + 1, "0");
263 } else {
264 binaryString.replace(i, i + 1, "1");
265 }
266 }
267
268 return binaryString;
269 }
270
271 /**
272 * Calculates the OSPF checksum for the given packet.
273 *
274 * @param packet as byte array
275 * @param checksumPos1 position of checksum bit in packet
276 * @param checksumPos2 position of checksum bit in packet
277 * @return checksum bytes
278 */
279 public byte[] calculateOspfCheckSum(byte[] packet, int checksumPos1, int checksumPos2) {
280
281 int hexasum = 0;
282 for (int i = 0; i < packet.length; i = i + 2) {
283 if (i != 12) {
284 byte b1 = packet[i];
285 String s1 = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
286 b1 = packet[i + 1];
287 String s2 = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
288 String hexa = s1 + s2;
289 int num1 = Integer.parseInt(hexa, 2);
290 hexasum = hexasum + num1;
291 String convertTo16 = Integer.toHexString(hexasum);
292 if (convertTo16.length() > 4) {
293 hexasum = convertToSixteenBits(convertTo16);
294 }
295 }
296 }
297 StringBuilder sb = new StringBuilder(Integer.toHexString(hexasum));
298 if (sb.length() > 4) {
299 sb = sb.reverse();
300 StringBuilder s1 = new StringBuilder(sb.substring(0, 4));
301 s1 = s1.reverse();
302 StringBuilder s2 = new StringBuilder(sb.substring(4, sb.length()));
303 s2 = s2.reverse();
304 hexasum = Integer.parseInt(s1.toString(), 16) + Integer.parseInt(s2.toString(), 16);
305 }
306 int finalChecksum = calculateChecksum(hexasum);
307 return OspfUtil.convertToTwoBytes(finalChecksum);
308 }
309}