blob: aca2c76be2976187f5bf754241323515f175d08e [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.lisp.ctl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.onosproject.lisp.msg.authentication.LispAuthenticationFactory;
import org.onosproject.lisp.msg.exceptions.LispWriterException;
import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
import org.onosproject.lisp.msg.protocols.LispEidRecord;
import org.onosproject.lisp.msg.protocols.LispMapNotify;
import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
import org.onosproject.lisp.msg.protocols.LispMapRegister;
import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
import org.onosproject.lisp.msg.protocols.LispMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetSocketAddress;
import java.util.Arrays;
import static org.onosproject.lisp.msg.authentication.LispAuthenticationKeyEnum.valueOf;
/**
* LISP map server class.
* Handles map-register message and acknowledges with map-notify message.
*/
public class LispMapServer {
private static final int NOTIFY_PORT = 4342;
// TODO: need to be configurable
private static final String AUTH_KEY = "onos";
// TODO: need to be configurable
private static final short AUTH_METHOD = 1;
private static final Logger log = LoggerFactory.getLogger(LispMapServer.class);
private LispAuthenticationFactory factory;
private LispEidRlocMap mapInfo;
public LispMapServer() {
factory = LispAuthenticationFactory.getInstance();
mapInfo = LispEidRlocMap.getInstance();
}
/**
* Handles map-register message and replies with map-notify message.
*
* @param message map-register message
* @return map-notify message
*/
public LispMapNotify processMapRegister(LispMessage message) {
LispMapRegister register = (LispMapRegister) message;
if (!checkAuthData(register)) {
log.warn("Unmatched authentication data of Map-Register");
return null;
}
// build temp notify message
NotifyBuilder authNotifyBuilder = new DefaultNotifyBuilder();
authNotifyBuilder.withKeyId(AUTH_METHOD);
authNotifyBuilder.withAuthDataLength(valueOf(AUTH_METHOD).getHashLength());
authNotifyBuilder.withNonce(register.getNonce());
authNotifyBuilder.withMapRecords(register.getMapRecords());
byte[] authData = new byte[valueOf(AUTH_METHOD).getHashLength()];
Arrays.fill(authData, (byte) 0);
authNotifyBuilder.withAuthenticationData(authData);
ByteBuf byteBuf = Unpooled.buffer();
try {
authNotifyBuilder.build().writeTo(byteBuf);
} catch (LispWriterException e) {
e.printStackTrace();
}
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
byte[] calcAuthData = factory.createAuthenticationData(
valueOf(register.getKeyId()), AUTH_KEY, bytes);
NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
notifyBuilder.withKeyId(AUTH_METHOD);
notifyBuilder.withAuthDataLength((short) calcAuthData.length);
notifyBuilder.withAuthenticationData(calcAuthData);
notifyBuilder.withNonce(register.getNonce());
notifyBuilder.withMapRecords(register.getMapRecords());
LispMapNotify notify = notifyBuilder.build();
InetSocketAddress address =
new InetSocketAddress(register.getSender().getAddress(), NOTIFY_PORT);
notify.configSender(address);
register.getMapRecords().forEach(record -> {
LispEidRecord eidRecord =
new LispEidRecord(record.getMaskLength(), record.getEidPrefixAfi());
mapInfo.insertMapRecord(eidRecord, record);
});
return notify;
}
/**
* Checks the integrity of the received map-register message by calculating
* authentication data from received map-register message.
*
* @param register map-register message
* @return evaluation result
*/
private boolean checkAuthData(LispMapRegister register) {
ByteBuf byteBuf = Unpooled.buffer();
RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
registerBuilder.withKeyId(register.getKeyId());
registerBuilder.withAuthDataLength(register.getAuthDataLength());
registerBuilder.withNonce(register.getNonce());
registerBuilder.withIsProxyMapReply(register.isProxyMapReply());
registerBuilder.withIsWantMapNotify(register.isWantMapNotify());
registerBuilder.withMapRecords(register.getMapRecords());
byte[] authData = register.getAuthenticationData();
if (authData != null) {
authData = authData.clone();
Arrays.fill(authData, (byte) 0);
}
registerBuilder.withAuthenticationData(authData);
try {
registerBuilder.build().writeTo(byteBuf);
} catch (LispWriterException e) {
e.printStackTrace();
}
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
byte[] calculatedAuthData = factory.createAuthenticationData(
valueOf(register.getKeyId()), AUTH_KEY, bytes);
return Arrays.equals(calculatedAuthData, register.getAuthenticationData());
}
}