Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 1 | /* |
Brian O'Connor | a09fe5b | 2017-08-03 21:12:30 -0700 | [diff] [blame] | 2 | * Copyright 2015-present Open Networking Foundation |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 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 | */ |
| 16 | |
| 17 | package org.onosproject.bgpio.util; |
| 18 | |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 19 | import java.net.InetAddress; |
| 20 | import java.net.UnknownHostException; |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 21 | import java.util.Arrays; |
| 22 | |
| 23 | import org.jboss.netty.buffer.ChannelBuffer; |
| 24 | import org.jboss.netty.buffer.ChannelBuffers; |
| 25 | import org.onlab.packet.IpAddress; |
| 26 | import org.onlab.packet.IpPrefix; |
Mohammad Shahid | 30fedc5 | 2017-08-09 11:49:40 +0530 | [diff] [blame^] | 27 | import org.onlab.packet.MacAddress; |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 28 | import org.onosproject.bgpio.exceptions.BgpParseException; |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 29 | import org.slf4j.Logger; |
| 30 | import org.slf4j.LoggerFactory; |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 31 | |
| 32 | import com.google.common.primitives.Ints; |
| 33 | |
| 34 | /** |
| 35 | * Provides methods to parse attribute header, validate length and type. |
| 36 | */ |
| 37 | public class Validation { |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 38 | private static final Logger log = LoggerFactory.getLogger(Validation.class); |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 39 | public static final byte FIRST_BIT = (byte) 0x80; |
| 40 | public static final byte SECOND_BIT = 0x40; |
| 41 | public static final byte THIRD_BIT = 0x20; |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 42 | public static final byte FOURTH_BIT = (byte) 0x10; |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 43 | public static final byte IPV4_SIZE = 4; |
| 44 | private boolean firstBit; |
| 45 | private boolean secondBit; |
| 46 | private boolean thirdBit; |
| 47 | private boolean fourthBit; |
| 48 | private int len; |
| 49 | private boolean isShort; |
| 50 | |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 51 | /** |
| 52 | * Constructor to initialize parameter. |
| 53 | * |
| 54 | * @param firstBit in AttributeFlags |
| 55 | * @param secondBit in AttributeFlags |
| 56 | * @param thirdBit in AttributeFlags |
| 57 | * @param fourthBit in AttributeFlags |
| 58 | * @param len length |
| 59 | * @param isShort true if length is read as short otherwise false |
| 60 | */ |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 61 | Validation(boolean firstBit, boolean secondBit, boolean thirdBit, boolean fourthBit, int len, boolean isShort) { |
| 62 | this.firstBit = firstBit; |
| 63 | this.secondBit = secondBit; |
| 64 | this.thirdBit = thirdBit; |
| 65 | this.fourthBit = fourthBit; |
| 66 | this.len = len; |
| 67 | this.isShort = isShort; |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Parses attribute Header. |
| 72 | * |
| 73 | * @param cb ChannelBuffer |
| 74 | * @return object of Validation |
| 75 | */ |
| 76 | public static Validation parseAttributeHeader(ChannelBuffer cb) { |
| 77 | |
| 78 | boolean firstBit; |
| 79 | boolean secondBit; |
| 80 | boolean thirdBit; |
| 81 | boolean fourthBit; |
| 82 | boolean isShort; |
| 83 | byte flags = cb.readByte(); |
| 84 | byte typeCode = cb.readByte(); |
| 85 | byte temp = flags; |
| 86 | //first Bit : Optional (1) or well-known (0) |
| 87 | firstBit = ((temp & FIRST_BIT) == FIRST_BIT); |
| 88 | //second Bit : Transitive (1) or non-Transitive (0) |
| 89 | secondBit = ((temp & SECOND_BIT) == SECOND_BIT); |
| 90 | //third Bit : partial (1) or complete (0) |
| 91 | thirdBit = ((temp & THIRD_BIT) == THIRD_BIT); |
| 92 | //forth Bit(Extended Length bit) : Attribute Length is 1 octects (0) or 2 octects (1) |
| 93 | fourthBit = ((temp & FOURTH_BIT) == FOURTH_BIT); |
| 94 | int len; |
| 95 | if (fourthBit) { |
| 96 | isShort = true; |
| 97 | short length = cb.readShort(); |
| 98 | len = length; |
| 99 | } else { |
| 100 | isShort = false; |
| 101 | byte length = cb.readByte(); |
| 102 | len = length; |
| 103 | } |
| 104 | return new Validation(firstBit, secondBit, thirdBit, fourthBit, len, isShort); |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Throws exception if length is not correct. |
| 109 | * |
| 110 | * @param errorCode Error code |
| 111 | * @param subErrCode Sub Error Code |
| 112 | * @param length erroneous length |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 113 | * @throws BgpParseException for erroneous length |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 114 | */ |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 115 | public static void validateLen(byte errorCode, byte subErrCode, int length) throws BgpParseException { |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 116 | byte[] errLen = Ints.toByteArray(length); |
| 117 | ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); |
| 118 | buffer.writeBytes(errLen); |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 119 | throw new BgpParseException(errorCode, subErrCode, buffer); |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Throws exception if type is not correct. |
| 124 | * |
| 125 | * @param errorCode Error code |
| 126 | * @param subErrCode Sub Error Code |
| 127 | * @param type erroneous type |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 128 | * @throws BgpParseException for erroneous type |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 129 | */ |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 130 | public static void validateType(byte errorCode, byte subErrCode, int type) throws BgpParseException { |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 131 | byte[] errType = Ints.toByteArray(type); |
| 132 | ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); |
| 133 | buffer.writeBytes(errType); |
Shashikanth VH | 5dd8dbe | 2015-11-26 13:22:18 +0530 | [diff] [blame] | 134 | throw new BgpParseException(errorCode, subErrCode, buffer); |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | /** |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 138 | * Convert byte array to InetAddress. |
| 139 | * |
| 140 | * @param length of IpAddress |
| 141 | * @param cb channelBuffer |
| 142 | * @return InetAddress |
| 143 | */ |
| 144 | public static InetAddress toInetAddress(int length, ChannelBuffer cb) { |
| 145 | byte[] address = new byte[length]; |
| 146 | cb.readBytes(address, 0, length); |
| 147 | InetAddress ipAddress = null; |
| 148 | try { |
| 149 | ipAddress = InetAddress.getByAddress(address); |
| 150 | } catch (UnknownHostException e) { |
| 151 | log.info("InetAddress convertion failed"); |
| 152 | } |
| 153 | return ipAddress; |
| 154 | } |
Mohammad Shahid | 30fedc5 | 2017-08-09 11:49:40 +0530 | [diff] [blame^] | 155 | /** |
| 156 | * Convert byte array to MacAddress. |
| 157 | * |
| 158 | * @param length of MacAddress |
| 159 | * @param cb channelBuffer |
| 160 | * @return macAddress |
| 161 | */ |
| 162 | public static MacAddress toMacAddress(int length, ChannelBuffer cb) { |
| 163 | byte[] address = new byte[length]; |
| 164 | cb.readBytes(address, 0, length); |
| 165 | MacAddress macAddress = MacAddress.valueOf(address); |
| 166 | return macAddress; |
| 167 | } |
Priyanka B | 03fa5e5 | 2015-10-30 12:46:40 +0530 | [diff] [blame] | 168 | /** |
Priyanka B | b2988fa | 2015-10-09 12:45:36 +0530 | [diff] [blame] | 169 | * Returns first bit in type flags. |
| 170 | * |
| 171 | * @return first bit in type flags |
| 172 | */ |
| 173 | public boolean getFirstBit() { |
| 174 | return this.firstBit; |
| 175 | } |
| 176 | |
| 177 | /** |
| 178 | * Returns second bit in type flags. |
| 179 | * |
| 180 | * @return second bit in type flags |
| 181 | */ |
| 182 | public boolean getSecondBit() { |
| 183 | return this.secondBit; |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Returns third bit in type flags. |
| 188 | * |
| 189 | * @return third bit in type flags |
| 190 | */ |
| 191 | public boolean getThirdBit() { |
| 192 | return this.thirdBit; |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * Returns fourth bit in type flags. |
| 197 | * |
| 198 | * @return fourth bit in type flags |
| 199 | */ |
| 200 | public boolean getFourthBit() { |
| 201 | return this.fourthBit; |
| 202 | } |
| 203 | |
| 204 | /** |
| 205 | * Returns attribute length. |
| 206 | * |
| 207 | * @return attribute length |
| 208 | */ |
| 209 | public int getLength() { |
| 210 | return this.len; |
| 211 | } |
| 212 | |
| 213 | /** |
| 214 | * Returns whether attribute length read in short or byte. |
| 215 | * |
| 216 | * @return whether attribute length read in short or byte |
| 217 | */ |
| 218 | public boolean isShort() { |
| 219 | return this.isShort; |
| 220 | } |
| 221 | |
| 222 | /** |
| 223 | * Converts byte array of prefix value to IpPrefix object. |
| 224 | * |
| 225 | * @param value byte array of prefix value |
| 226 | * @param length prefix length in bits |
| 227 | * @return object of IpPrefix |
| 228 | */ |
| 229 | public static IpPrefix bytesToPrefix(byte[] value, int length) { |
| 230 | if (value.length != IPV4_SIZE) { |
| 231 | value = Arrays.copyOf(value, IPV4_SIZE); |
| 232 | } |
| 233 | IpPrefix ipPrefix = IpPrefix.valueOf(IpAddress.Version.INET, value, length); |
| 234 | return ipPrefix; |
| 235 | } |
| 236 | } |