blob: 8c2a7b7b702d821c1318aa7c55b913a85aa89fd6 [file] [log] [blame]
Jian Li451cea32016-10-04 15:27:50 +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.ctl;
17
Jian Li6ef1b3f2016-11-12 18:16:06 +090018import org.onlab.packet.IpAddress;
Jian Li712ec052016-11-22 03:23:54 +090019import org.onosproject.lisp.msg.authentication.LispAuthenticationConfig;
Jian Li6ef1b3f2016-11-12 18:16:06 +090020import org.onosproject.lisp.msg.protocols.DefaultLispInfoReply;
Jian Li24f6cc02016-11-01 16:38:40 +090021import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
22import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
23import org.onosproject.lisp.msg.protocols.LispEidRecord;
Jian Li6ef1b3f2016-11-12 18:16:06 +090024import org.onosproject.lisp.msg.protocols.LispInfoReply;
25import org.onosproject.lisp.msg.protocols.LispInfoReply.InfoReplyBuilder;
26import org.onosproject.lisp.msg.protocols.LispInfoRequest;
27import org.onosproject.lisp.msg.protocols.LispInfoRequest.InfoRequestBuilder;
Jian Liafe2d3f2016-11-01 02:49:07 +090028import org.onosproject.lisp.msg.protocols.LispMapNotify;
Jian Li24f6cc02016-11-01 16:38:40 +090029import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
30import org.onosproject.lisp.msg.protocols.LispMapRegister;
31import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
Jian Li451cea32016-10-04 15:27:50 +090032import org.onosproject.lisp.msg.protocols.LispMessage;
Jian Li6ef1b3f2016-11-12 18:16:06 +090033import org.onosproject.lisp.msg.types.LispAfiAddress;
34import org.onosproject.lisp.msg.types.LispIpv4Address;
35import org.onosproject.lisp.msg.types.LispIpv6Address;
36import org.onosproject.lisp.msg.types.LispNoAddress;
Jian Li24f6cc02016-11-01 16:38:40 +090037import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
Jian Li6ef1b3f2016-11-12 18:16:06 +090040import java.net.InetAddress;
Jian Li24f6cc02016-11-01 16:38:40 +090041import java.net.InetSocketAddress;
Jian Li6ef1b3f2016-11-12 18:16:06 +090042import java.net.UnknownHostException;
Jian Li24f6cc02016-11-01 16:38:40 +090043import java.util.Arrays;
44
45import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
Jian Li6ef1b3f2016-11-12 18:16:06 +090046import static org.onosproject.lisp.msg.protocols.DefaultLispInfoRequest.DefaultInfoRequestBuilder;
47import static org.onosproject.lisp.msg.types.LispNatLcafAddress.NatAddressBuilder;
Jian Li451cea32016-10-04 15:27:50 +090048
49/**
50 * LISP map server class.
51 * Handles map-register message and acknowledges with map-notify message.
52 */
Jian Li712ec052016-11-22 03:23:54 +090053public final class LispMapServer {
Jian Li6322a362016-10-31 00:57:19 +090054
Jian Lid1a109e2016-11-12 09:00:42 +090055 private static final int MAP_NOTIFY_PORT = 4342;
Jian Li6ef1b3f2016-11-12 18:16:06 +090056 private static final int INFO_REPLY_PORT = 4342;
Jian Li24f6cc02016-11-01 16:38:40 +090057
Jian Li24f6cc02016-11-01 16:38:40 +090058 private static final Logger log = LoggerFactory.getLogger(LispMapServer.class);
59
Jian Li712ec052016-11-22 03:23:54 +090060 private LispEidRlocMap eidRlocMap = LispEidRlocMap.getInstance();
61 private LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
Jian Li24f6cc02016-11-01 16:38:40 +090062
Jian Li712ec052016-11-22 03:23:54 +090063 public static LispMapServer getInstance() {
64 return SingletonHelper.INSTANCE;
65 }
66
67 // non-instantiable (except for our Singleton)
68 private LispMapServer() {
Jian Li24f6cc02016-11-01 16:38:40 +090069 }
70
71 /**
72 * Handles map-register message and replies with map-notify message.
73 *
74 * @param message map-register message
75 * @return map-notify message
76 */
Jian Liafe2d3f2016-11-01 02:49:07 +090077 public LispMapNotify processMapRegister(LispMessage message) {
Jian Li24f6cc02016-11-01 16:38:40 +090078
79 LispMapRegister register = (LispMapRegister) message;
80
Jian Lid1a109e2016-11-12 09:00:42 +090081 if (!checkMapRegisterAuthData(register)) {
Jian Li24f6cc02016-11-01 16:38:40 +090082 log.warn("Unmatched authentication data of Map-Register");
83 return null;
84 }
85
Jian Li2c8a2a42016-11-24 02:51:03 +090086 // we only acknowledge back to ETR when want-map-notify bit is set to true
87 // otherwise, we do not acknowledge back to ETR
88 if (register.isWantMapNotify()) {
89 NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
90 notifyBuilder.withKeyId(authConfig.lispAuthKeyId());
91 notifyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
92 notifyBuilder.withAuthKey(authConfig.lispAuthKey());
93 notifyBuilder.withNonce(register.getNonce());
94 notifyBuilder.withMapRecords(register.getMapRecords());
Jian Li24f6cc02016-11-01 16:38:40 +090095
Jian Li2c8a2a42016-11-24 02:51:03 +090096 LispMapNotify notify = notifyBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +090097
Jian Li2c8a2a42016-11-24 02:51:03 +090098 InetSocketAddress address =
99 new InetSocketAddress(register.getSender().getAddress(), MAP_NOTIFY_PORT);
100 notify.configSender(address);
Jian Li24f6cc02016-11-01 16:38:40 +0900101
Jian Li2c8a2a42016-11-24 02:51:03 +0900102 register.getMapRecords().forEach(record -> {
103 LispEidRecord eidRecord =
104 new LispEidRecord(record.getMaskLength(), record.getEidPrefixAfi());
105 eidRlocMap.insertMapRecord(eidRecord, record);
106 });
Jian Li24f6cc02016-11-01 16:38:40 +0900107
Jian Li2c8a2a42016-11-24 02:51:03 +0900108 return notify;
109 }
110
111 return null;
Jian Li24f6cc02016-11-01 16:38:40 +0900112 }
113
114 /**
Jian Li6ef1b3f2016-11-12 18:16:06 +0900115 * Handles info-request message and replies with info-reply message.
116 *
117 * @param message info-request message
118 * @return info-reply message
119 */
120 public LispInfoReply processInfoRequest(LispMessage message) {
121 LispInfoRequest request = (LispInfoRequest) message;
122
123 if (!checkInfoRequestAuthData(request)) {
124 log.warn("Unmatched authentication data of Info-Request");
125 return null;
126 }
127
128 NatAddressBuilder natBuilder = new NatAddressBuilder();
129 try {
130 LispAfiAddress msAddress =
131 new LispIpv4Address(IpAddress.valueOf(InetAddress.getLocalHost()));
132 natBuilder.withMsRlocAddress(msAddress);
133 natBuilder.withMsUdpPortNumber((short) INFO_REPLY_PORT);
134
135 // try to extract global ETR RLOC address from info-request
136 IpAddress globalRlocIp = IpAddress.valueOf(request.getSender().getAddress());
137 LispAfiAddress globalRlocAddress;
138 if (globalRlocIp.isIp4()) {
139 globalRlocAddress = new LispIpv4Address(globalRlocIp);
140 } else {
141 globalRlocAddress = new LispIpv6Address(globalRlocIp);
142 }
143 natBuilder.withGlobalEtrRlocAddress(globalRlocAddress);
144 natBuilder.withEtrUdpPortNumber((short) request.getSender().getPort());
145 natBuilder.withPrivateEtrRlocAddress(new LispNoAddress());
146
147 // TODO: need to specify RTR addresses
148
149 } catch (UnknownHostException e) {
150 log.warn("Fails during formulate NAT address", e);
151 }
152
153 InfoReplyBuilder replyBuilder = new DefaultLispInfoReply.DefaultInfoReplyBuilder();
154 replyBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900155 replyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
156 replyBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900157 replyBuilder.withNonce(request.getNonce());
158 replyBuilder.withEidPrefix(request.getPrefix());
159 replyBuilder.withMaskLength(request.getMaskLength());
160 replyBuilder.withTtl(request.getTtl());
161 replyBuilder.withNatLcafAddress(natBuilder.build());
162 replyBuilder.withIsInfoReply(true);
163
164 LispInfoReply reply = replyBuilder.build();
165 reply.configSender(request.getSender());
166
167 return reply;
168 }
169
170 /**
Jian Li51aaca12016-11-11 01:56:15 +0900171 * Checks the integrity of the received map-register message by calculating
172 * authentication data from received map-register message.
Jian Li24f6cc02016-11-01 16:38:40 +0900173 *
Jian Li51aaca12016-11-11 01:56:15 +0900174 * @param register map-register message
Jian Li24f6cc02016-11-01 16:38:40 +0900175 * @return evaluation result
176 */
Jian Lid1a109e2016-11-12 09:00:42 +0900177 private boolean checkMapRegisterAuthData(LispMapRegister register) {
Jian Li24f6cc02016-11-01 16:38:40 +0900178 RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
179 registerBuilder.withKeyId(register.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900180 registerBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li24f6cc02016-11-01 16:38:40 +0900181 registerBuilder.withNonce(register.getNonce());
182 registerBuilder.withIsProxyMapReply(register.isProxyMapReply());
183 registerBuilder.withIsWantMapNotify(register.isWantMapNotify());
184 registerBuilder.withMapRecords(register.getMapRecords());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900185
Jian Lid1a109e2016-11-12 09:00:42 +0900186 LispMapRegister authRegister = registerBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +0900187
Jian Lid1a109e2016-11-12 09:00:42 +0900188 return Arrays.equals(authRegister.getAuthData(), register.getAuthData());
Jian Li451cea32016-10-04 15:27:50 +0900189 }
Jian Li6ef1b3f2016-11-12 18:16:06 +0900190
191 /**
192 * Checks the integrity of the received info-request message by calculating
193 * authentication data from received info-request message.
194 *
195 * @param request info-request message
196 * @return evaluation result
197 */
198 private boolean checkInfoRequestAuthData(LispInfoRequest request) {
199 InfoRequestBuilder requestBuilder = new DefaultInfoRequestBuilder();
200 requestBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900201 requestBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900202 requestBuilder.withNonce(request.getNonce());
203 requestBuilder.withTtl(request.getTtl());
204 requestBuilder.withEidPrefix(request.getPrefix());
205 requestBuilder.withIsInfoReply(request.isInfoReply());
206 requestBuilder.withMaskLength(request.getMaskLength());
207
yoonseon980cd7c2016-11-18 14:18:46 -0800208 LispInfoRequest authRequest = requestBuilder.build();
Jian Li6ef1b3f2016-11-12 18:16:06 +0900209
210 return Arrays.equals(authRequest.getAuthData(), request.getAuthData());
211 }
Jian Li712ec052016-11-22 03:23:54 +0900212
213 /**
214 * Prevents object instantiation from external.
215 */
216 private static class SingletonHelper {
217 private static final LispMapServer INSTANCE = new LispMapServer();
218 }
Jian Li451cea32016-10-04 15:27:50 +0900219}