initial artemis application commit
Change-Id: I01967b1e8e8df08cf95a2865566423a4aeb34ea9
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java
new file mode 100644
index 0000000..d0cb96c
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java
@@ -0,0 +1,124 @@
+/*
+ * 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.artemis.impl;
+
+import com.google.common.collect.Sets;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.artemis.impl.bgpspeakers.BgpSpeakers;
+import org.onosproject.artemis.impl.bgpspeakers.QuaggaBgpSpeakers;
+import org.onosproject.routing.bgp.BgpInfoService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * Timertask class which detects and mitigates BGP hijacks.
+ */
+class Deaggregator extends java.util.TimerTask {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private Set<ArtemisConfig.ArtemisPrefixes> prefixes = Sets.newHashSet();
+ private Set<BgpSpeakers> bgpSpeakers = Sets.newHashSet();
+
+ Deaggregator(BgpInfoService bgpInfoService) {
+ super();
+ // deaggregator must know the type of the connected BGP speakers and the BGP info.
+ // for this example we only have one Quagga BGP speaker.
+ bgpSpeakers.add(new QuaggaBgpSpeakers(bgpInfoService));
+ }
+
+ @Override
+ public void run() {
+ ArrayList<JSONObject> messagesArray = DataHandler.getInstance().getData();
+// log.info("Messages size: " + messagesArray.size());
+
+ // Example of BGP Update message:
+ // {
+ // "path":[65001, 65002, 65004], (origin being last)
+ // "prefix":"12.0.0.0/8",
+ // }
+
+ prefixes.forEach(prefix -> {
+ IpPrefix monitoredPrefix = prefix.prefix();
+
+ // for each update message in memory check for hijack
+ for (JSONObject tmp : messagesArray) {
+ IpPrefix receivedPrefix = null;
+ try {
+ receivedPrefix = IpPrefix.valueOf(tmp.getString("prefix"));
+ } catch (JSONException e) {
+ log.warn("JSONException: " + e.getMessage());
+ e.printStackTrace();
+ }
+ if (receivedPrefix == null) {
+ continue;
+ }
+
+ // check if the announced network address is inside our subnet
+ if (monitoredPrefix.contains(receivedPrefix)) {
+ JSONArray path = null;
+ try {
+ path = tmp.getJSONArray("path");
+ } catch (JSONException e) {
+ log.warn("JSONException: " + e.getMessage());
+ e.printStackTrace();
+ }
+ if (path == null) {
+ continue;
+ }
+
+ int state = prefix.checkPath(path);
+ if (state >= 100) {
+ log.warn("BGP Hijack detected of type " +
+ (state - 100) + "\n" + tmp.toString());
+ DataHandler.Serializer.writeHijack(tmp);
+ // can only de-aggregate /23 subnets and higher
+ int cidr = receivedPrefix.prefixLength();
+ if (receivedPrefix.prefixLength() < 24) {
+ byte[] octets = receivedPrefix.address().toOctets();
+ int byteGroup = (cidr + 1) / 8,
+ bitPos = 8 - (cidr + 1) % 8;
+
+ octets[byteGroup] = (byte) (octets[byteGroup] & ~(1 << bitPos));
+ String low = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
+ octets[byteGroup] = (byte) (octets[byteGroup] | (1 << bitPos));
+ String high = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
+
+ String[] prefixes = {low, high};
+ bgpSpeakers.forEach(bgpSpeakers -> bgpSpeakers.announceSubPrefixes(prefixes));
+ } else {
+ log.warn("Cannot announce smaller prefix than /24");
+ }
+ }
+ }
+ }
+ });
+ }
+
+ public Set<ArtemisConfig.ArtemisPrefixes> getPrefixes() {
+ return prefixes;
+ }
+
+ public void setPrefixes(Set<ArtemisConfig.ArtemisPrefixes> prefixes) {
+ this.prefixes = prefixes;
+ }
+}
\ No newline at end of file