OPNFLWPLUG-1032: Neon-MRI: Bump odlparent, yangtools, mdsal
[openflowplugin.git] / applications / topology-lldp-discovery / src / main / java / org / opendaylight / openflowplugin / applications / topology / lldp / utils / LLDPDiscoveryUtils.java
index cf2cfd1bb50c9d85ec46a16b0eacb9dd39b31665..485926a9da2144ba44a34b261e404ec8caebdc74 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.openflowplugin.applications.topology.lldp.utils;
 
+import com.google.common.base.Preconditions;
 import com.google.common.hash.HashCode;
 import com.google.common.hash.HashFunction;
 import com.google.common.hash.Hasher;
@@ -14,17 +15,23 @@ import com.google.common.hash.Hashing;
 import java.lang.management.ManagementFactory;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
 import java.util.Objects;
+import java.util.Optional;
+
 import org.apache.commons.lang3.ArrayUtils;
-import org.opendaylight.controller.liblldp.BitBufferHelper;
-import org.opendaylight.controller.liblldp.CustomTLVKey;
-import org.opendaylight.controller.liblldp.Ethernet;
-import org.opendaylight.controller.liblldp.LLDP;
-import org.opendaylight.controller.liblldp.LLDPTLV;
-import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.mdsal.eos.binding.api.Entity;
+import org.opendaylight.mdsal.eos.binding.api.EntityOwnershipService;
+import org.opendaylight.mdsal.eos.common.api.EntityOwnershipState;
 import org.opendaylight.openflowplugin.applications.topology.lldp.LLDPActivator;
+import org.opendaylight.openflowplugin.libraries.liblldp.BufferException;
+import org.opendaylight.openflowplugin.libraries.liblldp.Ethernet;
+import org.opendaylight.openflowplugin.libraries.liblldp.LLDP;
+import org.opendaylight.openflowplugin.libraries.liblldp.LLDPTLV;
+import org.opendaylight.openflowplugin.libraries.liblldp.NetUtils;
+import org.opendaylight.openflowplugin.libraries.liblldp.PacketException;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -37,8 +44,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
-public class LLDPDiscoveryUtils {
+public final class LLDPDiscoveryUtils {
     private static final Logger LOG = LoggerFactory.getLogger(LLDPDiscoveryUtils.class);
 
     private static final short MINIMUM_LLDP_SIZE = 61;
@@ -46,18 +52,24 @@ public class LLDPDiscoveryUtils {
     public static final short ETHERNET_TYPE_LLDP = (short) 0x88cc;
     private static final short ETHERNET_TYPE_OFFSET = 12;
     private static final short ETHERNET_VLAN_OFFSET = ETHERNET_TYPE_OFFSET + 4;
+    private static final String SERVICE_ENTITY_TYPE = "org.opendaylight.mdsal.ServiceEntityType";
+
+    private LLDPDiscoveryUtils() {
+    }
 
     public static String macToString(byte[] mac) {
-        StringBuilder b = new StringBuilder();
+        StringBuilder builder = new StringBuilder();
         for (int i = 0; i < mac.length; i++) {
-            b.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : ""));
+            builder.append(String.format("%02X%s", mac[i], i < mac.length - 1 ? ":" : ""));
         }
 
-        return b.toString();
+        return builder.toString();
     }
 
     /**
-     * @param payload
+     * Returns the encoded in custom TLV for the given lldp.
+     *
+     * @param payload lldp payload
      * @return nodeConnectorId - encoded in custom TLV of given lldp
      * @see LLDPDiscoveryUtils#lldpToNodeConnectorRef(byte[], boolean)
      */
@@ -66,18 +78,21 @@ public class LLDPDiscoveryUtils {
     }
 
     /**
-     * @param payload
+     * Returns the encoded in custom TLV for the given lldp.
+     *
+     * @param payload lldp payload
      * @param useExtraAuthenticatorCheck make it more secure (CVE-2015-1611 CVE-2015-1612)
      * @return nodeConnectorId - encoded in custom TLV of given lldp
      */
+    @SuppressWarnings("checkstyle:IllegalCatch")
     public static NodeConnectorRef lldpToNodeConnectorRef(byte[] payload, boolean useExtraAuthenticatorCheck)  {
         NodeConnectorRef nodeConnectorRef = null;
 
         if (isLLDP(payload)) {
             Ethernet ethPkt = new Ethernet();
             try {
-                ethPkt.deserialize(payload, 0, payload.length * NetUtils.NumBitsInAByte);
-            } catch (Exception e) {
+                ethPkt.deserialize(payload, 0, payload.length * NetUtils.NUM_BITS_IN_A_BYTE);
+            } catch (PacketException e) {
                 LOG.warn("Failed to decode LLDP packet {}", e);
                 return nodeConnectorRef;
             }
@@ -96,8 +111,7 @@ public class LLDPDiscoveryUtils {
                     throw new Exception("Node id wasn't specified via systemNameId in LLDP packet.");
                 }
 
-                final LLDPTLV nodeConnectorIdLldptlv = lldp.getCustomTLV(
-                        new CustomTLVKey(BitBufferHelper.getInt(LLDPTLV.OFOUI), LLDPTLV.CUSTOM_TLV_SUB_TYPE_NODE_CONNECTOR_ID[0]));
+                final LLDPTLV nodeConnectorIdLldptlv = lldp.getCustomTLV(LLDPTLV.createPortSubTypeCustomTLVKey());
                 if (nodeConnectorIdLldptlv != null) {
                     srcNodeConnectorId = new NodeConnectorId(LLDPTLV.getCustomString(
                             nodeConnectorIdLldptlv.getValue(), nodeConnectorIdLldptlv.getLength()));
@@ -109,51 +123,49 @@ public class LLDPDiscoveryUtils {
                     boolean secure = checkExtraAuthenticator(lldp, srcNodeConnectorId);
                     if (!secure) {
                         LOG.warn("SECURITY ALERT: there is probably a LLDP spoofing attack in progress.");
-                        throw new Exception("Attack. LLDP packet with inconsistent extra authenticator field was received.");
+                        throw new Exception(
+                                "Attack. LLDP packet with inconsistent extra authenticator field was received.");
                     }
                 }
 
                 InstanceIdentifier<NodeConnector> srcInstanceId = InstanceIdentifier.builder(Nodes.class)
                         .child(Node.class, new NodeKey(srcNodeId))
                         .child(NodeConnector.class, new NodeConnectorKey(srcNodeConnectorId))
-                        .toInstance();
+                        .build();
                 nodeConnectorRef = new NodeConnectorRef(srcInstanceId);
             } catch (Exception e) {
-                LOG.debug("Caught exception while parsing out lldp optional and custom fields: {}", e.getMessage(), e);
+                LOG.debug("Caught exception while parsing out lldp optional and custom fields", e);
             }
         }
         return nodeConnectorRef;
     }
 
     /**
-     * @param nodeConnectorId
+     * Gets an extra authenticator for lldp security.
+     *
+     * @param nodeConnectorId the NodeConnectorId
      * @return extra authenticator for lldp security
-     * @throws NoSuchAlgorithmException
      */
-    public static byte[] getValueForLLDPPacketIntegrityEnsuring(final NodeConnectorId nodeConnectorId) throws NoSuchAlgorithmException {
+    public static byte[] getValueForLLDPPacketIntegrityEnsuring(final NodeConnectorId nodeConnectorId)
+            throws NoSuchAlgorithmException {
         String finalKey;
-        if(LLDPActivator.getLldpSecureKey() !=null && !LLDPActivator.getLldpSecureKey().isEmpty()) {
+        if (LLDPActivator.getLldpSecureKey() != null && !LLDPActivator.getLldpSecureKey().isEmpty()) {
             finalKey = LLDPActivator.getLldpSecureKey();
         } else {
             finalKey = ManagementFactory.getRuntimeMXBean().getName();
         }
         final String pureValue = nodeConnectorId + finalKey;
 
-        final byte[] pureBytes = pureValue.getBytes();
+        final byte[] pureBytes = pureValue.getBytes(StandardCharsets.UTF_8);
         HashFunction hashFunction = Hashing.md5();
         Hasher hasher = hashFunction.newHasher();
         HashCode hashedValue = hasher.putBytes(pureBytes).hash();
         return hashedValue.asBytes();
     }
 
-    /**
-     * @param lldp
-     * @param srcNodeConnectorId
-     * @throws NoSuchAlgorithmException
-     */
-    private static boolean checkExtraAuthenticator(LLDP lldp, NodeConnectorId srcNodeConnectorId) throws NoSuchAlgorithmException {
-        final LLDPTLV hashLldptlv = lldp.getCustomTLV(
-                new CustomTLVKey(BitBufferHelper.getInt(LLDPTLV.OFOUI), LLDPTLV.CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC[0]));
+    private static boolean checkExtraAuthenticator(LLDP lldp, NodeConnectorId srcNodeConnectorId)
+            throws NoSuchAlgorithmException, BufferException {
+        final LLDPTLV hashLldptlv = lldp.getCustomTLV(LLDPTLV.createSecSubTypeCustomTLVKey());
         boolean secAuthenticatorOk = false;
         if (hashLldptlv != null) {
             byte[] rawTlvValue = hashLldptlv.getValue();
@@ -180,6 +192,35 @@ public class LLDPDiscoveryUtils {
             ethernetType = bb.getShort(ETHERNET_VLAN_OFFSET);
         }
 
-        return (ethernetType == ETHERNET_TYPE_LLDP);
+        return ethernetType == ETHERNET_TYPE_LLDP;
+    }
+
+    public static boolean isEntityOwned(final EntityOwnershipService eos, final String nodeId) {
+        Preconditions.checkNotNull(eos, "Entity ownership service must not be null");
+
+        EntityOwnershipState state = null;
+        java.util.Optional<EntityOwnershipState> status = getCurrentOwnershipStatus(eos, nodeId);
+        if (status.isPresent()) {
+            state = status.get();
+        } else {
+            LOG.error("Fetching ownership status failed for node {}", nodeId);
+        }
+        return state != null && state.equals(EntityOwnershipState.IS_OWNER);
+    }
+
+    private static java.util.Optional<EntityOwnershipState> getCurrentOwnershipStatus(final EntityOwnershipService eos,
+            final String nodeId) {
+        Entity entity = createNodeEntity(nodeId);
+        Optional<EntityOwnershipState> ownershipStatus = eos.getOwnershipState(entity);
+
+        if (ownershipStatus.isPresent()) {
+            LOG.debug("Fetched ownership status for node {} is {}", nodeId, ownershipStatus.get());
+            return java.util.Optional.of(ownershipStatus.get());
+        }
+        return java.util.Optional.empty();
+    }
+
+    private static Entity createNodeEntity(final String nodeId) {
+        return new Entity(SERVICE_ENTITY_TYPE, nodeId);
     }
 }