blob: 5ab4f964d3f530d57b69d727ea4e63d74d82e830 [file] [log] [blame]
Jian Li27759352016-10-04 20:14:42 +09001/*
2 * Copyright 2016-present 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.lisp.msg.protocols;
17
18import com.google.common.base.Objects;
19import io.netty.buffer.ByteBuf;
Jian Lid1a109e2016-11-12 09:00:42 +090020import io.netty.buffer.Unpooled;
21import org.onosproject.lisp.msg.authentication.LispAuthenticationFactory;
22import org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum;
Jian Li27759352016-10-04 20:14:42 +090023import org.onosproject.lisp.msg.exceptions.LispParseError;
24import org.onosproject.lisp.msg.exceptions.LispReaderException;
25import org.onosproject.lisp.msg.exceptions.LispWriterException;
26import org.onosproject.lisp.msg.types.LispAfiAddress;
27import org.onosproject.lisp.msg.types.LispNatLcafAddress;
28import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatLcafAddressWriter;
Jian Lid1a109e2016-11-12 09:00:42 +090029import org.slf4j.Logger;
30import org.slf4j.LoggerFactory;
Jian Li27759352016-10-04 20:14:42 +090031
32import java.util.Arrays;
33
34import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lid1a109e2016-11-12 09:00:42 +090035import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
Jian Li27759352016-10-04 20:14:42 +090036
37/**
38 * Default LISP info reply message class.
39 */
40public final class DefaultLispInfoReply extends DefaultLispInfo implements LispInfoReply {
41
Jian Lid1a109e2016-11-12 09:00:42 +090042 private static final Logger log = LoggerFactory.getLogger(DefaultLispInfoReply.class);
43
Jian Li27759352016-10-04 20:14:42 +090044 private final LispNatLcafAddress natLcafAddress;
45
46 /**
47 * A private constructor that protects object instantiation from external.
48 *
Jian Lid1a109e2016-11-12 09:00:42 +090049 * @param infoReply info reply flag
50 * @param nonce nonce
51 * @param keyId key identifier
52 * @param authDataLength authentication data length
53 * @param authData authentication data
54 * @param ttl Time-To-Live value
55 * @param maskLength EID prefix mask length
56 * @param eidPrefix EID prefix
57 * @param natLcafAddress NAT LCAF address
Jian Li27759352016-10-04 20:14:42 +090058 */
59 protected DefaultLispInfoReply(boolean infoReply, long nonce, short keyId, short authDataLength,
Jian Lid1a109e2016-11-12 09:00:42 +090060 byte[] authData, int ttl, byte maskLength,
61 LispAfiAddress eidPrefix, LispNatLcafAddress natLcafAddress) {
62 super(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix);
Jian Li27759352016-10-04 20:14:42 +090063 this.natLcafAddress = natLcafAddress;
64 }
65
66 @Override
67 public LispNatLcafAddress getNatLcafAddress() {
68 return natLcafAddress;
69 }
70
71 @Override
72 public String toString() {
73 return toStringHelper(this)
74 .add("type", getType())
75 .add("nonce", nonce)
76 .add("keyId", keyId)
77 .add("authentication data length", authDataLength)
Jian Lid1a109e2016-11-12 09:00:42 +090078 .add("authentication data", authData)
Jian Li27759352016-10-04 20:14:42 +090079 .add("TTL", ttl)
80 .add("EID mask length", maskLength)
81 .add("EID prefix", eidPrefix)
82 .add("NAT LCAF address", natLcafAddress).toString();
83 }
84
85 @Override
86 public boolean equals(Object o) {
87 if (this == o) {
88 return true;
89 }
90 if (o == null || getClass() != o.getClass()) {
91 return false;
92 }
93
94 DefaultLispInfoReply that = (DefaultLispInfoReply) o;
95 return Objects.equal(nonce, that.nonce) &&
96 Objects.equal(keyId, that.keyId) &&
97 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lid1a109e2016-11-12 09:00:42 +090098 Arrays.equals(authData, that.authData) &&
Jian Li27759352016-10-04 20:14:42 +090099 Objects.equal(ttl, that.ttl) &&
100 Objects.equal(maskLength, that.maskLength) &&
101 Objects.equal(eidPrefix, that.eidPrefix) &&
102 Objects.equal(natLcafAddress, that.natLcafAddress);
103 }
104
105 @Override
106 public int hashCode() {
107 return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength,
Jian Lid1a109e2016-11-12 09:00:42 +0900108 eidPrefix, natLcafAddress) + Arrays.hashCode(authData);
Jian Li27759352016-10-04 20:14:42 +0900109 }
110
111 public static final class DefaultInfoReplyBuilder implements InfoReplyBuilder {
112
113 private boolean infoReply;
114 private long nonce;
115 private short keyId;
116 private short authDataLength;
Jian Lid1a109e2016-11-12 09:00:42 +0900117 private byte[] authData;
118 private String authKey;
Jian Li27759352016-10-04 20:14:42 +0900119 private int ttl;
120 private byte maskLength;
121 private LispAfiAddress eidPrefix;
122 private LispNatLcafAddress natLcafAddress;
123
124 @Override
125 public LispType getType() {
126 return LispType.LISP_INFO;
127 }
128
129
130 @Override
Jian Li6ef1b3f2016-11-12 18:16:06 +0900131 public InfoReplyBuilder withIsInfoReply(boolean infoReply) {
Jian Li27759352016-10-04 20:14:42 +0900132 this.infoReply = infoReply;
133 return this;
134 }
135
136 @Override
137 public InfoReplyBuilder withNonce(long nonce) {
138 this.nonce = nonce;
139 return this;
140 }
141
142 @Override
143 public InfoReplyBuilder withAuthDataLength(short authDataLength) {
144 this.authDataLength = authDataLength;
145 return this;
146 }
147
148 @Override
149 public InfoReplyBuilder withKeyId(short keyId) {
150 this.keyId = keyId;
151 return this;
152 }
153
154 @Override
Jian Lid1a109e2016-11-12 09:00:42 +0900155 public InfoReplyBuilder withAuthData(byte[] authenticationData) {
Jian Li27759352016-10-04 20:14:42 +0900156 if (authenticationData != null) {
Jian Lid1a109e2016-11-12 09:00:42 +0900157 this.authData = authenticationData;
Jian Li27759352016-10-04 20:14:42 +0900158 }
159 return this;
160 }
161
162 @Override
Jian Lid1a109e2016-11-12 09:00:42 +0900163 public InfoReplyBuilder withAuthKey(String key) {
164 this.authKey = key;
165 return this;
166 }
167
168 @Override
Jian Li27759352016-10-04 20:14:42 +0900169 public InfoReplyBuilder withTtl(int ttl) {
170 this.ttl = ttl;
171 return this;
172 }
173
174 @Override
175 public InfoReplyBuilder withMaskLength(byte maskLength) {
176 this.maskLength = maskLength;
177 return this;
178 }
179
180 @Override
181 public InfoReplyBuilder withEidPrefix(LispAfiAddress eidPrefix) {
182 this.eidPrefix = eidPrefix;
183 return this;
184 }
185
186
187 @Override
188 public InfoReplyBuilder withNatLcafAddress(LispNatLcafAddress natLcafAddress) {
189 this.natLcafAddress = natLcafAddress;
190 return this;
191 }
192
193 @Override
194 public LispInfoReply build() {
Jian Lid1a109e2016-11-12 09:00:42 +0900195
196 // if authentication data is not specified, we will calculate it
197 if (authData == null) {
198 LispAuthenticationFactory factory = LispAuthenticationFactory.getInstance();
199
200 authDataLength = LispAuthenticationKeyEnum.valueOf(keyId).getHashLength();
201 byte[] tmpAuthData = new byte[authDataLength];
202 Arrays.fill(tmpAuthData, (byte) 0);
203 authData = tmpAuthData;
204
205 ByteBuf byteBuf = Unpooled.buffer();
206 try {
207 new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
208 authData, ttl, maskLength, eidPrefix, natLcafAddress).writeTo(byteBuf);
209 } catch (LispWriterException e) {
210 log.warn("Failed to serialize info reply", e);
211 }
212
213 byte[] bytes = new byte[byteBuf.readableBytes()];
214 byteBuf.readBytes(bytes);
215
216 if (authKey == null) {
217 log.warn("Must specify authentication key");
218 }
219
220 authData = factory.createAuthenticationData(valueOf(keyId), authKey, bytes);
221 }
222
Jian Li27759352016-10-04 20:14:42 +0900223 return new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
Jian Lid1a109e2016-11-12 09:00:42 +0900224 authData, ttl, maskLength, eidPrefix, natLcafAddress);
Jian Li27759352016-10-04 20:14:42 +0900225 }
226 }
227
228 /**
229 * A LISP message reader for InfoReply message.
230 */
231 public static final class InfoReplyReader implements LispMessageReader<LispInfoReply> {
232
233 @Override
234 public LispInfoReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
235 LispInfo lispInfo = DefaultLispInfo.deserialize(byteBuf);
236 LispNatLcafAddress natLcafAddress = new LispNatLcafAddress.NatLcafAddressReader().readFrom(byteBuf);
237
238 return new DefaultInfoReplyBuilder()
Jian Li6ef1b3f2016-11-12 18:16:06 +0900239 .withIsInfoReply(lispInfo.isInfoReply())
Jian Li27759352016-10-04 20:14:42 +0900240 .withNonce(lispInfo.getNonce())
241 .withKeyId(lispInfo.getKeyId())
242 .withAuthDataLength(lispInfo.getAuthDataLength())
Jian Lid1a109e2016-11-12 09:00:42 +0900243 .withAuthData(lispInfo.getAuthData())
Jian Li27759352016-10-04 20:14:42 +0900244 .withTtl(lispInfo.getTtl())
245 .withMaskLength(lispInfo.getMaskLength())
246 .withEidPrefix(lispInfo.getPrefix())
247 .withNatLcafAddress(natLcafAddress).build();
248 }
249 }
250
251 public static final class InfoReplyWriter implements LispMessageWriter<LispInfoReply> {
252
253 @Override
254 public void writeTo(ByteBuf byteBuf, LispInfoReply message) throws LispWriterException {
255 DefaultLispInfo.serialize(byteBuf, message);
256
257 // NAT LCAF address
258 NatLcafAddressWriter writer = new NatLcafAddressWriter();
259 writer.writeTo(byteBuf, message.getNatLcafAddress());
260 }
261 }
262}