/* * 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 com.google.common.base.Objects; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.onosproject.lisp.msg.authentication.LispAuthenticationFactory; 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.LispNoAddress; import org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; import static com.google.common.base.MoreObjects.toStringHelper; import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf; /** * Default LISP info request message class. */ public class DefaultLispInfoRequest extends DefaultLispInfo implements LispInfoRequest { private static final Logger log = LoggerFactory.getLogger(DefaultLispInfoRequest.class); static final InfoRequestWriter WRITER; static { WRITER = new InfoRequestWriter(); } /** * 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 DefaultLispInfoRequest(boolean infoReply, long nonce, short keyId, short authDataLength, byte[] authData, int ttl, byte maskLength, LispAfiAddress eidPrefix) { super(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix); } @Override public String toString() { return toStringHelper(this) .add("type", getType()) .add("nonce", nonce) .add("keyId", keyId) .add("authentication data length", authDataLength) .add("authentication data", authData) .add("TTL", ttl) .add("EID mask length", maskLength) .add("EID prefix", eidPrefix).toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } DefaultLispInfoRequest that = (DefaultLispInfoRequest) o; return Objects.equal(nonce, that.nonce) && Objects.equal(keyId, that.keyId) && Objects.equal(authDataLength, that.authDataLength) && Arrays.equals(authData, that.authData) && Objects.equal(ttl, that.ttl) && Objects.equal(maskLength, that.maskLength) && Objects.equal(eidPrefix, that.eidPrefix); } @Override public int hashCode() { return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength, eidPrefix) + Arrays.hashCode(authData); } @Override public void writeTo(ByteBuf byteBuf) throws LispWriterException { WRITER.writeTo(byteBuf, this); } public static final class DefaultInfoRequestBuilder implements InfoRequestBuilder { private boolean infoReply; private long nonce; private short keyId; private short authDataLength; private byte[] authData; private String authKey; private int ttl; private byte maskLength; private LispAfiAddress eidPrefix; @Override public LispType getType() { return LispType.LISP_INFO; } @Override public InfoRequestBuilder withIsInfoReply(boolean infoReply) { this.infoReply = infoReply; return this; } @Override public InfoRequestBuilder withNonce(long nonce) { this.nonce = nonce; return this; } @Override public InfoRequestBuilder withAuthDataLength(short authDataLength) { this.authDataLength = authDataLength; return this; } @Override public InfoRequestBuilder withKeyId(short keyId) { this.keyId = keyId; return this; } @Override public InfoRequestBuilder withAuthData(byte[] authenticationData) { if (authenticationData != null) { this.authData = authenticationData; } return this; } @Override public InfoRequestBuilder withAuthKey(String key) { this.authKey = key; return this; } @Override public InfoRequestBuilder withTtl(int ttl) { this.ttl = ttl; return this; } @Override public InfoRequestBuilder withMaskLength(byte maskLength) { this.maskLength = maskLength; return this; } @Override public InfoRequestBuilder withEidPrefix(LispAfiAddress eidPrefix) { this.eidPrefix = eidPrefix; return this; } @Override public LispInfoRequest build() { // if authentication data is not specified, we will calculate it if (authData == null) { LispAuthenticationFactory factory = LispAuthenticationFactory.getInstance(); authDataLength = LispAuthenticationKeyEnum.valueOf(keyId).getHashLength(); byte[] tmpAuthData = new byte[authDataLength]; Arrays.fill(tmpAuthData, (byte) 0); authData = tmpAuthData; ByteBuf byteBuf = Unpooled.buffer(); try { new DefaultLispInfoRequest(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix) .writeTo(byteBuf); } catch (LispWriterException e) { log.warn("Failed to serialize info request", e); } byte[] bytes = new byte[byteBuf.readableBytes()]; byteBuf.readBytes(bytes); if (authKey == null) { log.warn("Must specify authentication key"); } authData = factory .createAuthenticationData(valueOf(keyId), authKey, bytes); } return new DefaultLispInfoRequest(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix); } } /** * A LISP message reader for InfoRequest message. */ public static class InfoRequestReader implements LispMessageReader<LispInfoRequest> { @Override public LispInfoRequest readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException { LispInfo lispInfo = deserialize(byteBuf); return new DefaultInfoRequestBuilder() .withIsInfoReply(lispInfo.isInfoReply()) .withNonce(lispInfo.getNonce()) .withKeyId(lispInfo.getKeyId()) .withAuthDataLength(lispInfo.getAuthDataLength()) .withAuthData(lispInfo.getAuthData()) .withTtl(lispInfo.getTtl()) .withMaskLength(lispInfo.getMaskLength()) .withEidPrefix(lispInfo.getPrefix()).build(); } } /** * A LISP message writer for InfoRequest message. */ public static final class InfoRequestWriter implements LispMessageWriter<LispInfoRequest> { @Override public void writeTo(ByteBuf byteBuf, LispInfoRequest message) throws LispWriterException { serialize(byteBuf, message); //Fill AFI=0, no address new LispAfiAddress.AfiAddressWriter() .writeTo(byteBuf, new LispNoAddress()); } } }