blob: e69cd41309887fa34ac80159a0792284c158fea7 [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 Li29986d82016-12-01 03:25:12 +090060 private LispMappingDatabase mapDb = LispMappingDatabase.getInstance();
Jian Li712ec052016-11-22 03:23:54 +090061 private LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
Jian Li24f6cc02016-11-01 16:38:40 +090062
Jian Li712ec052016-11-22 03:23:54 +090063 // non-instantiable (except for our Singleton)
64 private LispMapServer() {
Jian Li24f6cc02016-11-01 16:38:40 +090065 }
66
Jian Li29986d82016-12-01 03:25:12 +090067 public static LispMapServer getInstance() {
68 return SingletonHelper.INSTANCE;
69 }
70
Jian Li24f6cc02016-11-01 16:38:40 +090071 /**
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 Li29986d82016-12-01 03:25:12 +090086 register.getMapRecords().forEach(mapRecord -> {
87 LispEidRecord eidRecord =
88 new LispEidRecord(mapRecord.getMaskLength(),
89 mapRecord.getEidPrefixAfi());
90
91 mapDb.putMapRecord(eidRecord, mapRecord);
92 });
93
Jian Li2c8a2a42016-11-24 02:51:03 +090094 // we only acknowledge back to ETR when want-map-notify bit is set to true
95 // otherwise, we do not acknowledge back to ETR
96 if (register.isWantMapNotify()) {
97 NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
98 notifyBuilder.withKeyId(authConfig.lispAuthKeyId());
99 notifyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
100 notifyBuilder.withAuthKey(authConfig.lispAuthKey());
101 notifyBuilder.withNonce(register.getNonce());
102 notifyBuilder.withMapRecords(register.getMapRecords());
Jian Li24f6cc02016-11-01 16:38:40 +0900103
Jian Li2c8a2a42016-11-24 02:51:03 +0900104 LispMapNotify notify = notifyBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +0900105
Jian Li2c8a2a42016-11-24 02:51:03 +0900106 InetSocketAddress address =
107 new InetSocketAddress(register.getSender().getAddress(), MAP_NOTIFY_PORT);
108 notify.configSender(address);
Jian Li24f6cc02016-11-01 16:38:40 +0900109
Jian Li2c8a2a42016-11-24 02:51:03 +0900110 return notify;
111 }
112
113 return null;
Jian Li24f6cc02016-11-01 16:38:40 +0900114 }
115
116 /**
Jian Li6ef1b3f2016-11-12 18:16:06 +0900117 * Handles info-request message and replies with info-reply message.
118 *
119 * @param message info-request message
120 * @return info-reply message
121 */
122 public LispInfoReply processInfoRequest(LispMessage message) {
123 LispInfoRequest request = (LispInfoRequest) message;
124
125 if (!checkInfoRequestAuthData(request)) {
126 log.warn("Unmatched authentication data of Info-Request");
127 return null;
128 }
129
130 NatAddressBuilder natBuilder = new NatAddressBuilder();
131 try {
132 LispAfiAddress msAddress =
133 new LispIpv4Address(IpAddress.valueOf(InetAddress.getLocalHost()));
134 natBuilder.withMsRlocAddress(msAddress);
135 natBuilder.withMsUdpPortNumber((short) INFO_REPLY_PORT);
136
137 // try to extract global ETR RLOC address from info-request
138 IpAddress globalRlocIp = IpAddress.valueOf(request.getSender().getAddress());
139 LispAfiAddress globalRlocAddress;
140 if (globalRlocIp.isIp4()) {
141 globalRlocAddress = new LispIpv4Address(globalRlocIp);
142 } else {
143 globalRlocAddress = new LispIpv6Address(globalRlocIp);
144 }
145 natBuilder.withGlobalEtrRlocAddress(globalRlocAddress);
146 natBuilder.withEtrUdpPortNumber((short) request.getSender().getPort());
147 natBuilder.withPrivateEtrRlocAddress(new LispNoAddress());
148
149 // TODO: need to specify RTR addresses
150
151 } catch (UnknownHostException e) {
152 log.warn("Fails during formulate NAT address", e);
153 }
154
155 InfoReplyBuilder replyBuilder = new DefaultLispInfoReply.DefaultInfoReplyBuilder();
156 replyBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900157 replyBuilder.withAuthDataLength(valueOf(authConfig.lispAuthKeyId()).getHashLength());
158 replyBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900159 replyBuilder.withNonce(request.getNonce());
160 replyBuilder.withEidPrefix(request.getPrefix());
161 replyBuilder.withMaskLength(request.getMaskLength());
162 replyBuilder.withTtl(request.getTtl());
163 replyBuilder.withNatLcafAddress(natBuilder.build());
164 replyBuilder.withIsInfoReply(true);
165
166 LispInfoReply reply = replyBuilder.build();
167 reply.configSender(request.getSender());
168
169 return reply;
170 }
171
172 /**
Jian Li51aaca12016-11-11 01:56:15 +0900173 * Checks the integrity of the received map-register message by calculating
174 * authentication data from received map-register message.
Jian Li24f6cc02016-11-01 16:38:40 +0900175 *
Jian Li51aaca12016-11-11 01:56:15 +0900176 * @param register map-register message
Jian Li24f6cc02016-11-01 16:38:40 +0900177 * @return evaluation result
178 */
Jian Lid1a109e2016-11-12 09:00:42 +0900179 private boolean checkMapRegisterAuthData(LispMapRegister register) {
Jian Li24f6cc02016-11-01 16:38:40 +0900180 RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
181 registerBuilder.withKeyId(register.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900182 registerBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li24f6cc02016-11-01 16:38:40 +0900183 registerBuilder.withNonce(register.getNonce());
184 registerBuilder.withIsProxyMapReply(register.isProxyMapReply());
185 registerBuilder.withIsWantMapNotify(register.isWantMapNotify());
186 registerBuilder.withMapRecords(register.getMapRecords());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900187
Jian Lid1a109e2016-11-12 09:00:42 +0900188 LispMapRegister authRegister = registerBuilder.build();
Jian Li24f6cc02016-11-01 16:38:40 +0900189
Jian Lid1a109e2016-11-12 09:00:42 +0900190 return Arrays.equals(authRegister.getAuthData(), register.getAuthData());
Jian Li451cea32016-10-04 15:27:50 +0900191 }
Jian Li6ef1b3f2016-11-12 18:16:06 +0900192
193 /**
194 * Checks the integrity of the received info-request message by calculating
195 * authentication data from received info-request message.
196 *
197 * @param request info-request message
198 * @return evaluation result
199 */
200 private boolean checkInfoRequestAuthData(LispInfoRequest request) {
201 InfoRequestBuilder requestBuilder = new DefaultInfoRequestBuilder();
202 requestBuilder.withKeyId(request.getKeyId());
Jian Li712ec052016-11-22 03:23:54 +0900203 requestBuilder.withAuthKey(authConfig.lispAuthKey());
Jian Li6ef1b3f2016-11-12 18:16:06 +0900204 requestBuilder.withNonce(request.getNonce());
205 requestBuilder.withTtl(request.getTtl());
206 requestBuilder.withEidPrefix(request.getPrefix());
207 requestBuilder.withIsInfoReply(request.isInfoReply());
208 requestBuilder.withMaskLength(request.getMaskLength());
209
yoonseon980cd7c2016-11-18 14:18:46 -0800210 LispInfoRequest authRequest = requestBuilder.build();
Jian Li6ef1b3f2016-11-12 18:16:06 +0900211
212 return Arrays.equals(authRequest.getAuthData(), request.getAuthData());
213 }
Jian Li712ec052016-11-22 03:23:54 +0900214
215 /**
216 * Prevents object instantiation from external.
217 */
Jian Li29986d82016-12-01 03:25:12 +0900218 private static final class SingletonHelper {
219 private static final String ILLEGAL_ACCESS_MSG = "Should not instantiate this class.";
Jian Li712ec052016-11-22 03:23:54 +0900220 private static final LispMapServer INSTANCE = new LispMapServer();
Jian Li29986d82016-12-01 03:25:12 +0900221
222 private SingletonHelper() {
223 throw new IllegalAccessError(ILLEGAL_ACCESS_MSG);
224 }
Jian Li712ec052016-11-22 03:23:54 +0900225 }
Jian Li451cea32016-10-04 15:27:50 +0900226}