blob: faac48de31a615a6529ddf6df5eb8db0b20778fd [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 */
Jian Li5e505c62016-12-05 02:44:24 +090016package org.onosproject.lisp.ctl.impl;
Jian Li451cea32016-10-04 15:27:50 +090017
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 Li5e505c62016-12-05 02:44:24 +090020import org.onosproject.lisp.msg.protocols.DefaultLispInfoReply.DefaultInfoReplyBuilder;
21import org.onosproject.lisp.msg.protocols.DefaultLispInfoRequest.DefaultInfoRequestBuilder;
Jian Li24f6cc02016-11-01 16:38:40 +090022import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
23import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
24import org.onosproject.lisp.msg.protocols.LispEidRecord;
Jian Li6ef1b3f2016-11-12 18:16:06 +090025import org.onosproject.lisp.msg.protocols.LispInfoReply;
26import org.onosproject.lisp.msg.protocols.LispInfoReply.InfoReplyBuilder;
27import org.onosproject.lisp.msg.protocols.LispInfoRequest;
28import org.onosproject.lisp.msg.protocols.LispInfoRequest.InfoRequestBuilder;
Jian Liafe2d3f2016-11-01 02:49:07 +090029import org.onosproject.lisp.msg.protocols.LispMapNotify;
Jian Li24f6cc02016-11-01 16:38:40 +090030import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
31import org.onosproject.lisp.msg.protocols.LispMapRegister;
32import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
Jian Li451cea32016-10-04 15:27:50 +090033import org.onosproject.lisp.msg.protocols.LispMessage;
Jian Li6ef1b3f2016-11-12 18:16:06 +090034import org.onosproject.lisp.msg.types.LispAfiAddress;
35import org.onosproject.lisp.msg.types.LispIpv4Address;
36import org.onosproject.lisp.msg.types.LispIpv6Address;
Jian Li5e505c62016-12-05 02:44:24 +090037import org.onosproject.lisp.msg.types.LispNatLcafAddress.NatAddressBuilder;
Jian Li6ef1b3f2016-11-12 18:16:06 +090038import org.onosproject.lisp.msg.types.LispNoAddress;
Jian Li24f6cc02016-11-01 16:38:40 +090039import org.slf4j.Logger;
40import org.slf4j.LoggerFactory;
41
Jian Li6ef1b3f2016-11-12 18:16:06 +090042import java.net.InetAddress;
Jian Li24f6cc02016-11-01 16:38:40 +090043import java.net.InetSocketAddress;
Jian Li6ef1b3f2016-11-12 18:16:06 +090044import java.net.UnknownHostException;
Jian Li24f6cc02016-11-01 16:38:40 +090045import java.util.Arrays;
46
Jian Licdbc0872016-12-05 17:23:53 +090047import static org.onlab.packet.IpAddress.valueOf;
Jian Li24f6cc02016-11-01 16:38:40 +090048import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
Jian Li451cea32016-10-04 15:27:50 +090049
50/**
51 * LISP map server class.
52 * Handles map-register message and acknowledges with map-notify message.
53 */
Jian Li712ec052016-11-22 03:23:54 +090054public final class LispMapServer {
Jian Li6322a362016-10-31 00:57:19 +090055
Jian Licdbc0872016-12-05 17:23:53 +090056 private static final Logger log = LoggerFactory.getLogger(LispMapServer.class);
57
Jian Lid1a109e2016-11-12 09:00:42 +090058 private static final int MAP_NOTIFY_PORT = 4342;
Jian Li6ef1b3f2016-11-12 18:16:06 +090059 private static final int INFO_REPLY_PORT = 4342;
Jian Li24f6cc02016-11-01 16:38:40 +090060
Jian Licdbc0872016-12-05 17:23:53 +090061 private static final String INVALID_AUTHENTICATION_DATA_MSG =
62 "Unmatched authentication data of {}.";
63 private static final String FAILED_TO_FORMULATE_NAT_MSG =
64 "Fails during formulate NAT address.";
65
Jian Li24f6cc02016-11-01 16:38:40 +090066
Jian Li29986d82016-12-01 03:25:12 +090067 private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
Jian Li712ec052016-11-22 03:23:54 +090068 private LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
Jian Li24f6cc02016-11-01 16:38:40 +090069
Jian Li712ec052016-11-22 03:23:54 +090070 // non-instantiable (except for our Singleton)
71 private LispMapServer() {
Jian Li24f6cc02016-11-01 16:38:40 +090072 }
73
Jian Licdbc0872016-12-05 17:23:53 +090074 static LispMapServer getInstance() {
Jian Li29986d82016-12-01 03:25:12 +090075 return SingletonHelper.INSTANCE;
76 }
77
Jian Li24f6cc02016-11-01 16:38:40 +090078 /**
79 * Handles map-register message and replies with map-notify message.
80 *
81 * @param message map-register message
82 * @return map-notify message
83 */
Jian Licdbc0872016-12-05 17:23:53 +090084 LispMapNotify processMapRegister(LispMessage message) {
Jian Li24f6cc02016-11-01 16:38:40 +090085
86 LispMapRegister register = (LispMapRegister) message;
87
Jian Lid1a109e2016-11-12 09:00:42 +090088 if (!checkMapRegisterAuthData(register)) {
Jian Licdbc0872016-12-05 17:23:53 +090089 log.warn(INVALID_AUTHENTICATION_DATA_MSG, "Map-Register");
Jian Li24f6cc02016-11-01 16:38:40 +090090 return null;
91 }
92
Jian Li29986d82016-12-01 03:25:12 +090093 register.getMapRecords().forEach(mapRecord -> {
94 LispEidRecord eidRecord =
Jian Licdbc0872016-12-05 17:23:53 +090095 new LispEidRecord(mapRecord.getMaskLength(),
96 mapRecord.getEidPrefixAfi());
Jian Li29986d82016-12-01 03:25:12 +090097
Jian Licdbc0872016-12-05 17:23:53 +090098 mapDb.putMapRecord(eidRecord, mapRecord, register.isProxyMapReply());
Jian Li29986d82016-12-01 03:25:12 +090099 });
100
Jian Li2c8a2a42016-11-24 02:51:03 +0900101 // we only acknowledge back to ETR when want-map-notify bit is set to true
102 // otherwise, we do not acknowledge back to ETR
103 if (register.isWantMapNotify()) {
104 NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
105 notifyBuilder.withKeyId(authConfig.lispAuthKeyId());
106 notifyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
107 notifyBuilder.withAuthKey(authConfig.lispAuthKey());
108 notifyBuilder.withNonce(register.getNonce());
109 notifyBuilder.withMapRecords(register.getMapRecords());
Jian Li24f6cc02016-11-01 16:38:40 +0900110
Jian Li2c8a2a42016-11-24 02:51:03 +0900111 LispMapNotify notify = notifyBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +0900112
Jian Li2c8a2a42016-11-24 02:51:03 +0900113 InetSocketAddress address =
114 new InetSocketAddress(register.getSender().getAddress(), MAP_NOTIFY_PORT);
115 notify.configSender(address);
Jian Li24f6cc02016-11-01 16:38:40 +0900116
Jian Li2c8a2a42016-11-24 02:51:03 +0900117 return notify;
118 }
119
120 return null;
Jian Li24f6cc02016-11-01 16:38:40 +0900121 }
122
123 /**
Jian Li6ef1b3f2016-11-12 18:16:06 +0900124 * Handles info-request message and replies with info-reply message.
125 *
126 * @param message info-request message
127 * @return info-reply message
128 */
Jian Licdbc0872016-12-05 17:23:53 +0900129 LispInfoReply processInfoRequest(LispMessage message) {
Jian Li6ef1b3f2016-11-12 18:16:06 +0900130 LispInfoRequest request = (LispInfoRequest) message;
131
132 if (!checkInfoRequestAuthData(request)) {
Jian Licdbc0872016-12-05 17:23:53 +0900133 log.warn(INVALID_AUTHENTICATION_DATA_MSG, "Info-Request");
Jian Li6ef1b3f2016-11-12 18:16:06 +0900134 return null;
135 }
136
137 NatAddressBuilder natBuilder = new NatAddressBuilder();
138 try {
139 LispAfiAddress msAddress =
Jian Licdbc0872016-12-05 17:23:53 +0900140 new LispIpv4Address(valueOf(InetAddress.getLocalHost()));
Jian Li6ef1b3f2016-11-12 18:16:06 +0900141 natBuilder.withMsRlocAddress(msAddress);
142 natBuilder.withMsUdpPortNumber((short) INFO_REPLY_PORT);
143
144 // try to extract global ETR RLOC address from info-request
Jian Licdbc0872016-12-05 17:23:53 +0900145 IpAddress globalRlocIp = valueOf(request.getSender().getAddress());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900146 LispAfiAddress globalRlocAddress;
147 if (globalRlocIp.isIp4()) {
148 globalRlocAddress = new LispIpv4Address(globalRlocIp);
149 } else {
150 globalRlocAddress = new LispIpv6Address(globalRlocIp);
151 }
152 natBuilder.withGlobalEtrRlocAddress(globalRlocAddress);
153 natBuilder.withEtrUdpPortNumber((short) request.getSender().getPort());
154 natBuilder.withPrivateEtrRlocAddress(new LispNoAddress());
155
156 // TODO: need to specify RTR addresses
157
158 } catch (UnknownHostException e) {
Jian Licdbc0872016-12-05 17:23:53 +0900159 log.warn(FAILED_TO_FORMULATE_NAT_MSG, e);
Jian Li6ef1b3f2016-11-12 18:16:06 +0900160 }
161
Jian Li5e505c62016-12-05 02:44:24 +0900162 InfoReplyBuilder replyBuilder = new DefaultInfoReplyBuilder();
Jian Li6ef1b3f2016-11-12 18:16:06 +0900163 replyBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900164 replyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
165 replyBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900166 replyBuilder.withNonce(request.getNonce());
167 replyBuilder.withEidPrefix(request.getPrefix());
168 replyBuilder.withMaskLength(request.getMaskLength());
169 replyBuilder.withTtl(request.getTtl());
170 replyBuilder.withNatLcafAddress(natBuilder.build());
171 replyBuilder.withIsInfoReply(true);
172
173 LispInfoReply reply = replyBuilder.build();
174 reply.configSender(request.getSender());
175
176 return reply;
177 }
178
179 /**
Jian Li51aaca12016-11-11 01:56:15 +0900180 * Checks the integrity of the received map-register message by calculating
181 * authentication data from received map-register message.
Jian Li24f6cc02016-11-01 16:38:40 +0900182 *
Jian Li51aaca12016-11-11 01:56:15 +0900183 * @param register map-register message
Jian Li24f6cc02016-11-01 16:38:40 +0900184 * @return evaluation result
185 */
Jian Lid1a109e2016-11-12 09:00:42 +0900186 private boolean checkMapRegisterAuthData(LispMapRegister register) {
Jian Li24f6cc02016-11-01 16:38:40 +0900187 RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
188 registerBuilder.withKeyId(register.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900189 registerBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li24f6cc02016-11-01 16:38:40 +0900190 registerBuilder.withNonce(register.getNonce());
191 registerBuilder.withIsProxyMapReply(register.isProxyMapReply());
192 registerBuilder.withIsWantMapNotify(register.isWantMapNotify());
193 registerBuilder.withMapRecords(register.getMapRecords());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900194
Jian Lid1a109e2016-11-12 09:00:42 +0900195 LispMapRegister authRegister = registerBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +0900196
Jian Lid1a109e2016-11-12 09:00:42 +0900197 return Arrays.equals(authRegister.getAuthData(), register.getAuthData());
Jian Li451cea32016-10-04 15:27:50 +0900198 }
Jian Li6ef1b3f2016-11-12 18:16:06 +0900199
200 /**
201 * Checks the integrity of the received info-request message by calculating
202 * authentication data from received info-request message.
203 *
204 * @param request info-request message
205 * @return evaluation result
206 */
207 private boolean checkInfoRequestAuthData(LispInfoRequest request) {
208 InfoRequestBuilder requestBuilder = new DefaultInfoRequestBuilder();
209 requestBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900210 requestBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900211 requestBuilder.withNonce(request.getNonce());
212 requestBuilder.withTtl(request.getTtl());
213 requestBuilder.withEidPrefix(request.getPrefix());
214 requestBuilder.withIsInfoReply(request.isInfoReply());
215 requestBuilder.withMaskLength(request.getMaskLength());
216
yoonseon980cd7c2016-11-18 14:18:46 -0800217 LispInfoRequest authRequest = requestBuilder.build();
Jian Li6ef1b3f2016-11-12 18:16:06 +0900218
219 return Arrays.equals(authRequest.getAuthData(), request.getAuthData());
220 }
Jian Li712ec052016-11-22 03:23:54 +0900221
222 /**
223 * Prevents object instantiation from external.
224 */
Jian Li29986d82016-12-01 03:25:12 +0900225 private static final class SingletonHelper {
226 private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class.";
Jian Li712ec052016-11-22 03:23:54 +0900227 private static final LispMapServer INSTANCE = new LispMapServer();
Jian Li29986d82016-12-01 03:25:12 +0900228
229 private SingletonHelper() {
230 throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
231 }
Jian Li712ec052016-11-22 03:23:54 +0900232 }
Jian Li451cea32016-10-04 15:27:50 +0900233}