All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onosproject.ospf.protocol.util.OspfUtil Maven / Gradle / Ivy

/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.ospf.protocol.util;

import com.google.common.primitives.Bytes;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.DatatypeConverter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

/**
 * Representation of an OSPF constants and utility methods.
 */
public final class OspfUtil {
    public static final int OSPF_VERSION_2 = 2;
    public static final int OSPF_VERSION = OSPF_VERSION_2;
    public static final int PACKET_MINIMUM_LENGTH = 24;
    public static final int METADATA_LEN = 5;
    public static final int MINIMUM_FRAME_LEN = 1487;
    public static final int OSPF_HEADER_LENGTH = 24;
    public static final int LSA_HEADER_LENGTH = 20;
    public static final int DD_HEADER_LENGTH = OSPF_HEADER_LENGTH + 8;
    public static final int LSREQUEST_LENGTH = 12;
    public static final int OSPFPACKET_LENGTH_POS1 = 2;
    public static final int OSPFPACKET_LENGTH_POS2 = 3;
    public static final int OSPFPACKET_CHECKSUM_POS1 = 12;
    public static final int OSPFPACKET_CHECKSUM_POS2 = 13;
    public static final int LSAPACKET_CHECKSUM_POS1 = 16;
    public static final int LSAPACKET_CHECKSUM_POS2 = 17;
    public static final Ip4Address ALL_SPF_ROUTERS = Ip4Address.valueOf("224.0.0.5");
    public static final Ip4Address ALL_DROUTERS = Ip4Address.valueOf("224.0.0.6");
    public static final Ip4Address DEFAULTIP = Ip4Address.valueOf("0.0.0.0");
    public static final int RETRANSMITINTERVAL = 5;
    public static final int ONLY_ALL_SPF_ROUTERS = 1;
    public static final int JOIN_ALL_DROUTERS = 2;
    public static final int INITIALIZE_SET = 1;
    public static final int INITIALIZE_NOTSET = 0;
    public static final int MORE_SET = 1;
    public static final int MORE_NOTSET = 0;
    public static final int IS_MASTER = 1;
    public static final int NOT_MASTER = 0;
    public static final int NOT_ASSIGNED = 0;
    public static final int FOUR_BYTES = 4;
    public static final int FIVE_BYTES = 5;
    public static final int EIGHT_BYTES = 8;
    public static final int TWELVE_BYTES = 12;
    public static final int EXTERNAL_DESTINATION_LENGTH = 12;
    public static final String SHOST = "127.0.0.1";
    public static final int SPORT = 7000;
    public static final int MTU = 1500;
    public static final char CONFIG_LENGTH = 1498;
    public static final char ROUTER_PRIORITY = 0;
    public static final int HELLO_PACKET_OPTIONS = 2;
    private static final Logger log =
            LoggerFactory.getLogger(OspfUtil.class);

    /**
     * Creates an instance.
     */
    private OspfUtil() {

    }

    /**
     * Checks given IPs are in same network or not.
     *
     * @param ip1  IP address
     * @param ip2  IP address
     * @param mask network mask
     * @return true if both are in same network else false
     */
    public static boolean sameNetwork(Ip4Address ip1, Ip4Address ip2, Ip4Address mask) {

        byte[] a1 = ip1.toOctets();
        byte[] a2 = ip2.toOctets();
        byte[] m = mask.toOctets();

        for (int i = 0; i < a1.length; i++) {
            if ((a1[i] & m[i]) != (a2[i] & m[i])) {
                return false;
            }
        }

        return true;
    }

    /**
     * Converts IP address to long.
     *
     * @param ipAddress IP address
     * @return long value represents IP address
     */
    public static long ipAddressToLong(String ipAddress) {
        StringTokenizer st = new StringTokenizer(ipAddress, ".");
        long ipAsNumber = Long.parseLong(st.nextToken()) * (long) Math.pow(256, 3);
        ipAsNumber += Long.parseLong(st.nextToken()) * (long) Math.pow(256, 2);
        ipAsNumber += Long.parseLong(st.nextToken()) * 256;
        ipAsNumber += +Long.parseLong(st.nextToken());

        return ipAsNumber;
    }

    /**
     * Checks option field to see whether opaque enabled or not.
     * 2nd Bit in options field of DdPacket represents Opaque.
     * 7th bit is external capability.
     * This method checks Opaque bit is set in the options or not.
     *
     * @param options options value
     * @return true if opaque enabled else false.
     */
    public static boolean isOpaqueEnabled(int options) {
        Boolean[] bits = new Boolean[8];
        for (int i = 7; i >= 0; i--) {
            bits[i] = (options & (1 << i)) != 0;
        }

        List list = Arrays.asList(bits);
        Collections.reverse(list);

        //2nd bit is Opaque.
        return list.get(1);
    }

    /**
     * Converts a byte to integer variable.
     *
     * @param bytesToConvert bytes to convert
     * @return integer representation of bytes
     */
    public static int byteToInteger(byte[] bytesToConvert) {
        final StringBuilder builder = new StringBuilder();
        for (byte eachByte : bytesToConvert) {
            builder.append(String.format("%02x", eachByte));
        }
        int num = Integer.parseInt(builder.toString(), 16);
        return num;
    }

    /**
     * Converts a byte to long variable.
     *
     * @param bytesToConvert bytes to convert
     * @return long representation of bytes
     */
    public static long byteToLong(byte[] bytesToConvert) {
        final StringBuilder builder = new StringBuilder();
        for (byte eachByte : bytesToConvert) {
            builder.append(String.format("%02x", eachByte));
        }
        long num = Long.parseLong(builder.toString(), 16);
        return num;
    }

    /**
     * Creates a random number.
     *
     * @return random number
     */
    public static int createRandomNumber() {
        Random rnd = new SecureRandom();
        int randomNumber = 10000000 + rnd.nextInt(90000000);
        return randomNumber;
    }

    /**
     * Reads the LSA header from channel buffer.
     *
     * @param channelBuffer channel buffer instance
     * @return LSA header instance.
     */
    public static LsaHeader readLsaHeader(ChannelBuffer channelBuffer) {
        //add all the LSA Headers - one header is of 20 bytes
        LsaHeader lsaHeader = null;
        if (channelBuffer.readableBytes() >= OspfUtil.LSA_HEADER_LENGTH) {
            byte[] byteArray = new byte[OspfUtil.FOUR_BYTES];
            channelBuffer.readBytes(byteArray, 0, OspfUtil.FOUR_BYTES);
            ChannelBuffer tempBuffer = ChannelBuffers.copiedBuffer(byteArray);
            int lsType = byteArray[3];
            if (lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA || lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA
                    || lsType == OspfParameters.AS_OPAQUE_LSA) {
                OpaqueLsaHeader header = new OpaqueLsaHeader();
                header.setAge(tempBuffer.readShort());
                header.setOptions(tempBuffer.readByte());
                header.setLsType(tempBuffer.readByte());
                header.setOpaqueType(channelBuffer.readByte());
                header.setOpaqueId(channelBuffer.readUnsignedMedium());
                byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
                header.setLsSequenceNo(channelBuffer.readInt());
                header.setLsCheckSum(channelBuffer.readUnsignedShort());
                header.setLsPacketLen(channelBuffer.readShort());
                byte[] opaqueIdBytes = OspfUtil.convertToTwoBytes(header.opaqueId());
                header.setLinkStateId(header.opaqueType() + "." + "0" + "." +
                                              opaqueIdBytes[0] + "." + opaqueIdBytes[1]);
                lsaHeader = header;
            } else {
                LsaHeader header = new LsaHeader();
                header.setAge(tempBuffer.readShort());
                header.setOptions(tempBuffer.readByte());
                header.setLsType(tempBuffer.readByte());
                byte[] tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                try {
                    header.setLinkStateId(InetAddress.getByAddress(tempByteArray).getHostName());
                } catch (UnknownHostException uhe) {
                    log.warn("Can't look up host", uhe);
                }
                tempByteArray = new byte[OspfUtil.FOUR_BYTES];
                channelBuffer.readBytes(tempByteArray, 0, OspfUtil.FOUR_BYTES);
                header.setAdvertisingRouter(Ip4Address.valueOf(tempByteArray));
                header.setLsSequenceNo(channelBuffer.readInt());
                header.setLsCheckSum(channelBuffer.readUnsignedShort());
                header.setLsPacketLen(channelBuffer.readShort());
                lsaHeader = header;
            }
        }
        return lsaHeader;
    }


    /**
     * Converts an integer to two bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToTwoBytes(int numberToConvert) {

        byte[] numInBytes = new byte[2];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
        }
        return numInBytes;
    }

    /**
     * Converts a number to three bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToThreeBytes(int numberToConvert) {
        byte[] numInBytes = new byte[3];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
        }
        return numInBytes;
    }

    /**
     * Converts a number to four bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToFourBytes(int numberToConvert) {

        byte[] numInBytes = new byte[4];
        String s1 = Integer.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = 0;
            numInBytes[3] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
            numInBytes[3] = hexas[1];
        } else if (hexas.length == 3) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
            numInBytes[3] = hexas[2];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
            numInBytes[3] = hexas[3];
        }
        return numInBytes;
    }

    /**
     * Converts a number to four bytes.
     *
     * @param numberToConvert number to convert
     * @return given number as bytes
     */
    public static byte[] convertToFourBytes(long numberToConvert) {

        byte[] numInBytes = new byte[4];
        String s1 = Long.toHexString(numberToConvert);
        if (s1.length() % 2 != 0) {
            s1 = "0" + s1;
        }
        if (s1.length() == 16) {
            s1 = s1.substring(8, s1.length());
        }
        byte[] hexas = DatatypeConverter.parseHexBinary(s1);
        if (hexas.length == 1) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = 0;
            numInBytes[3] = hexas[0];
        } else if (hexas.length == 2) {
            numInBytes[0] = 0;
            numInBytes[1] = 0;
            numInBytes[2] = hexas[0];
            numInBytes[3] = hexas[1];
        } else if (hexas.length == 3) {
            numInBytes[0] = 0;
            numInBytes[1] = hexas[0];
            numInBytes[2] = hexas[1];
            numInBytes[3] = hexas[2];
        } else {
            numInBytes[0] = hexas[0];
            numInBytes[1] = hexas[1];
            numInBytes[2] = hexas[2];
            numInBytes[3] = hexas[3];
        }
        return numInBytes;
    }

    /**
     * Adds the checksum and length in packet.
     *
     * @param ospfPacket       ospf packet
     * @param lengthBytePos1   length byte position
     * @param lengthBytePos2   length byte position
     * @param checksumBytePos1 checksum byte position
     * @param checksumBytePos2 checksum byte position
     * @return byte array with checksum and length
     */
    public static byte[] addLengthAndCheckSum(byte[] ospfPacket, int lengthBytePos1, int lengthBytePos2,
                                              int checksumBytePos1, int checksumBytePos2) {
        //Set the length of the packet
        //Get the total length of the packet
        int length = ospfPacket.length;
        //Convert the lenth to two bytes as the length field is 2 bytes
        byte[] lenthInTwoBytes = OspfUtil.convertToTwoBytes(length);
        //ospf header 3rd and 4th position represents length
        ospfPacket[lengthBytePos1] = lenthInTwoBytes[0]; //assign 1st byte in lengthBytePos1
        ospfPacket[lengthBytePos2] = lenthInTwoBytes[1]; //assign 2st byte in lengthBytePos2

        //Get the checksum as two bytes.
        byte[] checkSumInTwoBytes = new ChecksumCalculator().calculateOspfCheckSum(ospfPacket,
                                                                                   checksumBytePos1, checksumBytePos2);
        ospfPacket[checksumBytePos1] = checkSumInTwoBytes[0]; //assign 1st byte in checksumBytePos1
        ospfPacket[checksumBytePos2] = checkSumInTwoBytes[1]; //assign 2st byte in checksumBytePos2

        return ospfPacket;
    }

    /**
     * Adds metadata to ospf packet like whether to join multi cast group and destination IP.
     *
     * @param interfaceIndex   interface index
     * @param ospfPacket       OSPF packet
     * @param allDroutersValue whether to join multi cast or not
     * @param destinationIp    destination ip address
     * @return byte array
     */
    public static byte[] addMetadata(int interfaceIndex, byte[] ospfPacket, int allDroutersValue,
                                     Ip4Address destinationIp) {
        byte[] packet;
        byte[] interfaceIndexByteVal = {(byte) interfaceIndex};
        byte[] allDroutersByteVal = {(byte) allDroutersValue};
        byte[] destIpAsBytes = destinationIp.toOctets();
        byte[] metadata = Bytes.concat(interfaceIndexByteVal, allDroutersByteVal);
        metadata = Bytes.concat(metadata, destIpAsBytes);
        packet = Bytes.concat(ospfPacket, metadata);

        return packet;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy