/* * Copyright 2016-present Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.lisp.msg.protocols; import io.netty.buffer.ByteBuf; import org.onlab.util.ByteOperator; import org.onlab.util.ImmutableByteSequence; import org.onosproject.lisp.msg.exceptions.LispParseError; import org.onosproject.lisp.msg.exceptions.LispReaderException; import org.onosproject.lisp.msg.exceptions.LispWriterException; import org.onosproject.lisp.msg.types.LispAfiAddress; import org.onosproject.lisp.msg.types.LispAfiAddress.AfiAddressWriter; import java.util.Arrays; /** * A class that contains a set of helper methods for LISP info request and reply. */ public class DefaultLispInfo extends AbstractLispMessage implements LispInfo { protected final boolean infoReply; protected final long nonce; protected final short keyId; protected final short authDataLength; protected final byte[] authData; protected final int ttl; protected final byte maskLength; protected final LispAfiAddress eidPrefix; private static final int INFO_REPLY_INDEX = 3; private static final int RESERVED_SKIP_LENGTH_1 = 3; private static final int RESERVED_SKIP_LENGTH_2 = 1; private static final int INFO_REQUEST_SHIFT_BIT = 4; private static final int ENABLE_BIT = 1; private static final int DISABLE_BIT = 0; private static final int UNUSED_ZERO = 0; /** * A private constructor that protects object instantiation from external. * * @param infoReply info reply flag * @param nonce nonce * @param keyId key identifier * @param authDataLength authentication data length * @param authData authentication data * @param ttl Time-To-Live value * @param maskLength EID prefix mask length * @param eidPrefix EID prefix */ protected DefaultLispInfo(boolean infoReply, long nonce, short keyId, short authDataLength, byte[] authData, int ttl, byte maskLength, LispAfiAddress eidPrefix) { this.infoReply = infoReply; this.nonce = nonce; this.keyId = keyId; this.authDataLength = authDataLength; this.authData = authData; this.ttl = ttl; this.maskLength = maskLength; this.eidPrefix = eidPrefix; } @Override public LispType getType() { return LispType.LISP_INFO; } @Override public void writeTo(ByteBuf byteBuf) throws LispWriterException { serialize(byteBuf, this); } @Override public Builder createBuilder() { return new DefaultLispInfoRequest.DefaultInfoRequestBuilder(); } @Override public boolean isInfoReply() { return infoReply; } @Override public long getNonce() { return nonce; } @Override public short getKeyId() { return keyId; } @Override public short getAuthDataLength() { return authDataLength; } @Override public byte[] getAuthData() { if (authData != null && authData.length != 0) { return ImmutableByteSequence.copyFrom(authData).asArray(); } else { return new byte[0]; } } @Override public int getTtl() { return ttl; } @Override public byte getMaskLength() { return maskLength; } @Override public LispAfiAddress getPrefix() { return eidPrefix; } public static LispInfo deserialize(ByteBuf byteBuf) throws LispParseError, LispReaderException { if (byteBuf.readerIndex() != 0) { return null; } // infoReply -> 1 bit boolean infoReplyFlag = ByteOperator.getBit(byteBuf.readByte(), INFO_REPLY_INDEX); // let's skip the reserved field byteBuf.skipBytes(RESERVED_SKIP_LENGTH_1); // nonce -> 64 bits long nonce = byteBuf.readLong(); // keyId -> 16 bits short keyId = byteBuf.readShort(); // authenticationDataLength -> 16 bits short authLength = byteBuf.readShort(); // authData -> depends on the authenticationDataLength byte[] authData = new byte[authLength]; byteBuf.readBytes(authData); // ttl -> 32 bits int ttl = byteBuf.readInt(); // let's skip the reserved field byteBuf.skipBytes(RESERVED_SKIP_LENGTH_2); // mask length -> 8 bits short maskLength = byteBuf.readUnsignedByte(); LispAfiAddress prefix = new LispAfiAddress.AfiAddressReader().readFrom(byteBuf); return new DefaultLispInfo(infoReplyFlag, nonce, keyId, authLength, authData, ttl, (byte) maskLength, prefix); } public static void serialize(ByteBuf byteBuf, LispInfo message) throws LispWriterException { // specify LISP message type byte msgType = (byte) (LispType.LISP_INFO.getTypeCode() << INFO_REQUEST_SHIFT_BIT); // info reply flag byte infoReply = DISABLE_BIT; if (message.isInfoReply()) { infoReply = (byte) (ENABLE_BIT << INFO_REPLY_INDEX); } byteBuf.writeByte(msgType + infoReply); // fill zero into reserved filed byteBuf.writeByte((short) UNUSED_ZERO); byteBuf.writeByte((short) UNUSED_ZERO); byteBuf.writeByte((short) UNUSED_ZERO); // nonce byteBuf.writeLong(message.getNonce()); // keyId byteBuf.writeShort(message.getKeyId()); // authentication data length in octet byteBuf.writeShort(message.getAuthDataLength()); // authentication data byte[] data = message.getAuthData(); byte[] clone; if (data != null) { clone = data.clone(); Arrays.fill(clone, (byte) UNUSED_ZERO); } byteBuf.writeBytes(data); /// TTL byteBuf.writeInt(message.getTtl()); // fill zero into reserved filed byteBuf.writeByte((short) UNUSED_ZERO); // mask length byteBuf.writeByte(message.getMaskLength()); // EID prefix AFI with EID prefix AfiAddressWriter afiAddressWriter = new AfiAddressWriter(); afiAddressWriter.writeTo(byteBuf, message.getPrefix()); } }