blob: 25827a00614e2996d60d3e480bd748a5d13e8f1d [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;
Jian Li5e505c62016-12-05 02:44:24 +090021import org.onosproject.lisp.msg.types.LispAfiAddress;
Jian Lid1a109e2016-11-12 09:00:42 +090022import org.onosproject.lisp.msg.authentication.LispAuthenticationFactory;
23import org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum;
Jian Li27759352016-10-04 20:14:42 +090024import org.onosproject.lisp.msg.exceptions.LispParseError;
25import org.onosproject.lisp.msg.exceptions.LispReaderException;
26import org.onosproject.lisp.msg.exceptions.LispWriterException;
Jian Li55ddcdb2016-11-21 17:04:01 +090027import org.onosproject.lisp.msg.types.LispLcafAddress.LcafAddressReader;
28import org.onosproject.lisp.msg.types.LispLcafAddress.LcafAddressWriter;
Jian Li27759352016-10-04 20:14:42 +090029import org.onosproject.lisp.msg.types.LispNatLcafAddress;
Jian Lid1a109e2016-11-12 09:00:42 +090030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
Jian Li27759352016-10-04 20:14:42 +090032
33import java.util.Arrays;
34
35import static com.google.common.base.MoreObjects.toStringHelper;
Jian Lid1a109e2016-11-12 09:00:42 +090036import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
Jian Li27759352016-10-04 20:14:42 +090037
38/**
39 * Default LISP info reply message class.
40 */
41public final class DefaultLispInfoReply extends DefaultLispInfo implements LispInfoReply {
42
Jian Lid1a109e2016-11-12 09:00:42 +090043 private static final Logger log = LoggerFactory.getLogger(DefaultLispInfoReply.class);
44
Jian Li27759352016-10-04 20:14:42 +090045 private final LispNatLcafAddress natLcafAddress;
46
yoonseon980cd7c2016-11-18 14:18:46 -080047 static final InfoReplyWriter WRITER;
48
49 static {
50 WRITER = new InfoReplyWriter();
51 }
52
Jian Li27759352016-10-04 20:14:42 +090053 /**
54 * A private constructor that protects object instantiation from external.
55 *
Jian Lid1a109e2016-11-12 09:00:42 +090056 * @param infoReply info reply flag
57 * @param nonce nonce
58 * @param keyId key identifier
59 * @param authDataLength authentication data length
60 * @param authData authentication data
61 * @param ttl Time-To-Live value
62 * @param maskLength EID prefix mask length
63 * @param eidPrefix EID prefix
64 * @param natLcafAddress NAT LCAF address
Jian Li27759352016-10-04 20:14:42 +090065 */
66 protected DefaultLispInfoReply(boolean infoReply, long nonce, short keyId, short authDataLength,
Jian Lid1a109e2016-11-12 09:00:42 +090067 byte[] authData, int ttl, byte maskLength,
68 LispAfiAddress eidPrefix, LispNatLcafAddress natLcafAddress) {
69 super(infoReply, nonce, keyId, authDataLength, authData, ttl, maskLength, eidPrefix);
Jian Li27759352016-10-04 20:14:42 +090070 this.natLcafAddress = natLcafAddress;
71 }
72
73 @Override
74 public LispNatLcafAddress getNatLcafAddress() {
75 return natLcafAddress;
76 }
77
78 @Override
yoonseon980cd7c2016-11-18 14:18:46 -080079 public void writeTo(ByteBuf byteBuf) throws LispWriterException {
80 WRITER.writeTo(byteBuf, this);
81 }
82
83 @Override
Jian Li27759352016-10-04 20:14:42 +090084 public String toString() {
85 return toStringHelper(this)
86 .add("type", getType())
87 .add("nonce", nonce)
88 .add("keyId", keyId)
89 .add("authentication data length", authDataLength)
Jian Lid1a109e2016-11-12 09:00:42 +090090 .add("authentication data", authData)
Jian Li27759352016-10-04 20:14:42 +090091 .add("TTL", ttl)
92 .add("EID mask length", maskLength)
93 .add("EID prefix", eidPrefix)
94 .add("NAT LCAF address", natLcafAddress).toString();
95 }
96
97 @Override
98 public boolean equals(Object o) {
99 if (this == o) {
100 return true;
101 }
102 if (o == null || getClass() != o.getClass()) {
103 return false;
104 }
105
106 DefaultLispInfoReply that = (DefaultLispInfoReply) o;
107 return Objects.equal(nonce, that.nonce) &&
108 Objects.equal(keyId, that.keyId) &&
109 Objects.equal(authDataLength, that.authDataLength) &&
Jian Lid1a109e2016-11-12 09:00:42 +0900110 Arrays.equals(authData, that.authData) &&
Jian Li27759352016-10-04 20:14:42 +0900111 Objects.equal(ttl, that.ttl) &&
112 Objects.equal(maskLength, that.maskLength) &&
113 Objects.equal(eidPrefix, that.eidPrefix) &&
114 Objects.equal(natLcafAddress, that.natLcafAddress);
115 }
116
117 @Override
118 public int hashCode() {
119 return Objects.hashCode(nonce, keyId, authDataLength, ttl, maskLength,
Jian Lid1a109e2016-11-12 09:00:42 +0900120 eidPrefix, natLcafAddress) + Arrays.hashCode(authData);
Jian Li27759352016-10-04 20:14:42 +0900121 }
122
123 public static final class DefaultInfoReplyBuilder implements InfoReplyBuilder {
124
125 private boolean infoReply;
126 private long nonce;
127 private short keyId;
128 private short authDataLength;
Jian Lid1a109e2016-11-12 09:00:42 +0900129 private byte[] authData;
130 private String authKey;
Jian Li27759352016-10-04 20:14:42 +0900131 private int ttl;
132 private byte maskLength;
133 private LispAfiAddress eidPrefix;
134 private LispNatLcafAddress natLcafAddress;
135
136 @Override
137 public LispType getType() {
138 return LispType.LISP_INFO;
139 }
140
141
142 @Override
Jian Li6ef1b3f2016-11-12 18:16:06 +0900143 public InfoReplyBuilder withIsInfoReply(boolean infoReply) {
Jian Li27759352016-10-04 20:14:42 +0900144 this.infoReply = infoReply;
145 return this;
146 }
147
148 @Override
149 public InfoReplyBuilder withNonce(long nonce) {
150 this.nonce = nonce;
151 return this;
152 }
153
154 @Override
155 public InfoReplyBuilder withAuthDataLength(short authDataLength) {
156 this.authDataLength = authDataLength;
157 return this;
158 }
159
160 @Override
161 public InfoReplyBuilder withKeyId(short keyId) {
162 this.keyId = keyId;
163 return this;
164 }
165
166 @Override
Jian Lid1a109e2016-11-12 09:00:42 +0900167 public InfoReplyBuilder withAuthData(byte[] authenticationData) {
Jian Li27759352016-10-04 20:14:42 +0900168 if (authenticationData != null) {
Jian Lid1a109e2016-11-12 09:00:42 +0900169 this.authData = authenticationData;
Jian Li27759352016-10-04 20:14:42 +0900170 }
171 return this;
172 }
173
174 @Override
Jian Lid1a109e2016-11-12 09:00:42 +0900175 public InfoReplyBuilder withAuthKey(String key) {
176 this.authKey = key;
177 return this;
178 }
179
180 @Override
Jian Li27759352016-10-04 20:14:42 +0900181 public InfoReplyBuilder withTtl(int ttl) {
182 this.ttl = ttl;
183 return this;
184 }
185
186 @Override
187 public InfoReplyBuilder withMaskLength(byte maskLength) {
188 this.maskLength = maskLength;
189 return this;
190 }
191
192 @Override
193 public InfoReplyBuilder withEidPrefix(LispAfiAddress eidPrefix) {
194 this.eidPrefix = eidPrefix;
195 return this;
196 }
197
198
199 @Override
200 public InfoReplyBuilder withNatLcafAddress(LispNatLcafAddress natLcafAddress) {
201 this.natLcafAddress = natLcafAddress;
202 return this;
203 }
204
205 @Override
206 public LispInfoReply build() {
Jian Lid1a109e2016-11-12 09:00:42 +0900207
208 // if authentication data is not specified, we will calculate it
209 if (authData == null) {
210 LispAuthenticationFactory factory = LispAuthenticationFactory.getInstance();
211
212 authDataLength = LispAuthenticationKeyEnum.valueOf(keyId).getHashLength();
213 byte[] tmpAuthData = new byte[authDataLength];
214 Arrays.fill(tmpAuthData, (byte) 0);
215 authData = tmpAuthData;
216
217 ByteBuf byteBuf = Unpooled.buffer();
218 try {
219 new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
220 authData, ttl, maskLength, eidPrefix, natLcafAddress).writeTo(byteBuf);
221 } catch (LispWriterException e) {
222 log.warn("Failed to serialize info reply", e);
223 }
224
225 byte[] bytes = new byte[byteBuf.readableBytes()];
226 byteBuf.readBytes(bytes);
227
228 if (authKey == null) {
229 log.warn("Must specify authentication key");
230 }
231
232 authData = factory.createAuthenticationData(valueOf(keyId), authKey, bytes);
233 }
234
Jian Li27759352016-10-04 20:14:42 +0900235 return new DefaultLispInfoReply(infoReply, nonce, keyId, authDataLength,
Jian Lid1a109e2016-11-12 09:00:42 +0900236 authData, ttl, maskLength, eidPrefix, natLcafAddress);
Jian Li27759352016-10-04 20:14:42 +0900237 }
238 }
239
240 /**
241 * A LISP message reader for InfoReply message.
242 */
243 public static final class InfoReplyReader implements LispMessageReader<LispInfoReply> {
244
245 @Override
246 public LispInfoReply readFrom(ByteBuf byteBuf) throws LispParseError, LispReaderException {
Jian Li5e505c62016-12-05 02:44:24 +0900247 LispInfo lispInfo = deserialize(byteBuf);
Jian Li55ddcdb2016-11-21 17:04:01 +0900248
249 LispNatLcafAddress natLcafAddress = (LispNatLcafAddress)
250 new LcafAddressReader().readFrom(byteBuf);
Jian Li27759352016-10-04 20:14:42 +0900251
252 return new DefaultInfoReplyBuilder()
Jian Li6ef1b3f2016-11-12 18:16:06 +0900253 .withIsInfoReply(lispInfo.isInfoReply())
Jian Li27759352016-10-04 20:14:42 +0900254 .withNonce(lispInfo.getNonce())
255 .withKeyId(lispInfo.getKeyId())
256 .withAuthDataLength(lispInfo.getAuthDataLength())
Jian Lid1a109e2016-11-12 09:00:42 +0900257 .withAuthData(lispInfo.getAuthData())
Jian Li27759352016-10-04 20:14:42 +0900258 .withTtl(lispInfo.getTtl())
259 .withMaskLength(lispInfo.getMaskLength())
260 .withEidPrefix(lispInfo.getPrefix())
261 .withNatLcafAddress(natLcafAddress).build();
262 }
263 }
264
265 public static final class InfoReplyWriter implements LispMessageWriter<LispInfoReply> {
266
267 @Override
268 public void writeTo(ByteBuf byteBuf, LispInfoReply message) throws LispWriterException {
Jian Li5e505c62016-12-05 02:44:24 +0900269 serialize(byteBuf, message);
Jian Li27759352016-10-04 20:14:42 +0900270
Jian Li55ddcdb2016-11-21 17:04:01 +0900271 new LcafAddressWriter().writeTo(byteBuf, message.getNatLcafAddress());
Jian Li27759352016-10-04 20:14:42 +0900272 }
273 }
274}