/* * 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.ospf.controller.impl; import com.fasterxml.jackson.databind.JsonNode; import org.onlab.packet.Ip4Address; import org.onosproject.ospf.controller.OspfArea; import org.onosproject.ospf.controller.OspfInterface; import org.onosproject.ospf.controller.OspfProcess; import org.onosproject.ospf.controller.area.OspfAreaImpl; import org.onosproject.ospf.controller.area.OspfInterfaceImpl; import org.onosproject.ospf.controller.area.OspfProcessImpl; import org.onosproject.ospf.protocol.util.OspfUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; /** * Representation of OSPF network configuration parsing util. */ public final class OspfConfigUtil { public static final String PROCESSID = "processId"; public static final String AREAS = "areas"; public static final String INTERFACEINDEX = "interfaceIndex"; public static final String AREAID = "areaId"; public static final String ROUTERID = "routerId"; public static final String INTERFACE = "interface"; public static final String HELLOINTERVAL = "helloIntervalTime"; public static final String ROUTERDEADINTERVAL = "routerDeadIntervalTime"; public static final String INTERFACETYPE = "interfaceType"; public static final String EXTERNALROUTINGCAPABILITY = "externalRoutingCapability"; protected static final Logger log = LoggerFactory.getLogger(OspfConfigUtil.class); private static final String ISOPAQUE = "isOpaqueEnable"; /** * Creates an instance of this. */ private OspfConfigUtil() { } /** * Returns list of OSPF process from the json nodes. * * @param jsonNodes represents one or more OSPF process configuration * @return list of OSPF processes. */ public static List<OspfProcess> processes(JsonNode jsonNodes) { List<OspfProcess> ospfProcesses = new ArrayList<>(); if (jsonNodes == null) { return ospfProcesses; } //From each Process nodes, get area and related interface details. jsonNodes.forEach(jsonNode -> { List<OspfArea> areas = new ArrayList<>(); //Get configured areas for the process. for (JsonNode areaNode : jsonNode.path(AREAS)) { List<OspfInterface> interfaceList = new ArrayList<>(); for (JsonNode interfaceNode : areaNode.path(INTERFACE)) { OspfInterface ospfInterface = interfaceDetails(interfaceNode); if (ospfInterface != null) { interfaceList.add(ospfInterface); } } //Get the area details OspfArea area = areaDetails(areaNode); if (area != null) { area.setOspfInterfaceList(interfaceList); areas.add(area); } } OspfProcess process = new OspfProcessImpl(); process.setProcessId(jsonNode.path(PROCESSID).asText()); process.setAreas(areas); ospfProcesses.add(process); }); return ospfProcesses; } /** * Returns interface IP by index. * * @param interfaceIndex interface index * @return interface IP by index */ private static Ip4Address getInterfaceIp(int interfaceIndex) { Ip4Address ipAddress = null; try { NetworkInterface networkInterface = NetworkInterface.getByIndex(interfaceIndex); Enumeration ipAddresses = networkInterface.getInetAddresses(); while (ipAddresses.hasMoreElements()) { InetAddress address = (InetAddress) ipAddresses.nextElement(); if (!address.isLinkLocalAddress()) { ipAddress = Ip4Address.valueOf(address.getAddress()); break; } } } catch (Exception e) { log.debug("Error while getting Interface IP by index"); return OspfUtil.DEFAULTIP; } return ipAddress; } /** * Returns interface MAC by index. * * @param interfaceIndex interface index * @return interface IP by index */ private static String getInterfaceMask(int interfaceIndex) { String subnetMask = null; try { Ip4Address ipAddress = getInterfaceIp(interfaceIndex); NetworkInterface networkInterface = NetworkInterface.getByInetAddress( InetAddress.getByName(ipAddress.toString())); Enumeration ipAddresses = networkInterface.getInetAddresses(); int index = 0; while (ipAddresses.hasMoreElements()) { InetAddress address = (InetAddress) ipAddresses.nextElement(); if (!address.isLinkLocalAddress()) { break; } index++; } int prfLen = networkInterface.getInterfaceAddresses().get(index).getNetworkPrefixLength(); int shft = 0xffffffff << (32 - prfLen); int oct1 = ((byte) ((shft & 0xff000000) >> 24)) & 0xff; int oct2 = ((byte) ((shft & 0x00ff0000) >> 16)) & 0xff; int oct3 = ((byte) ((shft & 0x0000ff00) >> 8)) & 0xff; int oct4 = ((byte) (shft & 0x000000ff)) & 0xff; subnetMask = oct1 + "." + oct2 + "." + oct3 + "." + oct4; } catch (Exception e) { log.debug("Error while getting Interface network mask by index"); return subnetMask; } return subnetMask; } /** * Checks if valid digit or not. * * @param strInput input value * @return true if valid else false */ private static boolean isValidDigit(String strInput) { boolean isValid = true; if (isPrimitive(strInput)) { int input = Integer.parseInt(strInput); if (input < 1 || input > 255) { log.debug("Wrong config input value: {}", strInput); isValid = false; } else { isValid = true; } } else { isValid = false; } return isValid; } /** * Checks if primitive or not. * * @param value input value * @return true if number else false */ private static boolean isPrimitive(String value) { boolean status = true; value = value.trim(); if (value.length() < 1) { return false; } for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!Character.isDigit(c)) { status = false; break; } } return status; } /** * Checks if boolean or not. * * @param value input value * @return true if boolean else false */ private static boolean isBoolean(String value) { boolean status = false; value = value.trim(); if (value.equals("true") || value.equals("false")) { return true; } return status; } /** * Checks if given id is valid or not. * * @param value input value * @return true if valid else false */ private static boolean isValidIpAddress(String value) { boolean status = true; try { Ip4Address ipAddress = Ip4Address.valueOf(value); } catch (Exception e) { log.debug("Invalid IP address string: {}", value); return false; } return status; } /** * Returns OSPF area instance from configuration. * * @param areaNode area configuration * @return OSPF area instance */ private static OspfArea areaDetails(JsonNode areaNode) { OspfArea area = new OspfAreaImpl(); String areaId = areaNode.path(AREAID).asText(); if (isValidIpAddress(areaId)) { area.setAreaId(Ip4Address.valueOf(areaId)); } else { log.debug("Wrong areaId: {}", areaId); return null; } String routerId = areaNode.path(ROUTERID).asText(); if (isValidIpAddress(routerId)) { area.setRouterId(Ip4Address.valueOf(routerId)); } else { log.debug("Wrong routerId: {}", routerId); return null; } String routingCapability = areaNode.path(EXTERNALROUTINGCAPABILITY).asText(); if (isBoolean(routingCapability)) { area.setExternalRoutingCapability(Boolean.valueOf(routingCapability)); } else { log.debug("Wrong routingCapability: {}", routingCapability); return null; } String isOpaqueEnabled = areaNode.path(ISOPAQUE).asText(); if (isBoolean(isOpaqueEnabled)) { area.setIsOpaqueEnabled(Boolean.valueOf(isOpaqueEnabled)); } else { log.debug("Wrong isOpaqueEnabled: {}", isOpaqueEnabled); return null; } area.setOptions(OspfUtil.HELLO_PACKET_OPTIONS); return area; } /** * Returns OSPF interface instance from configuration. * * @param interfaceNode interface configuration * @return OSPF interface instance */ private static OspfInterface interfaceDetails(JsonNode interfaceNode) { OspfInterface ospfInterface = new OspfInterfaceImpl(); String index = interfaceNode.path(INTERFACEINDEX).asText(); if (isValidDigit(index)) { ospfInterface.setInterfaceIndex(Integer.parseInt(index)); } else { log.debug("Wrong interface index: {}", index); return null; } Ip4Address interfaceIp = getInterfaceIp(ospfInterface.interfaceIndex()); if (interfaceIp.equals(OspfUtil.DEFAULTIP)) { return null; } ospfInterface.setIpAddress(interfaceIp); ospfInterface.setIpNetworkMask(Ip4Address.valueOf(getInterfaceMask( ospfInterface.interfaceIndex()))); ospfInterface.setBdr(OspfUtil.DEFAULTIP); ospfInterface.setDr(OspfUtil.DEFAULTIP); String helloInterval = interfaceNode.path(HELLOINTERVAL).asText(); if (isValidDigit(helloInterval)) { ospfInterface.setHelloIntervalTime(Integer.parseInt(helloInterval)); } else { log.debug("Wrong hello interval: {}", helloInterval); return null; } String routerDeadInterval = interfaceNode.path(ROUTERDEADINTERVAL).asText(); if (isValidDigit(routerDeadInterval)) { ospfInterface.setRouterDeadIntervalTime(Integer.parseInt(routerDeadInterval)); } else { log.debug("Wrong routerDeadInterval: {}", routerDeadInterval); return null; } String interfaceType = interfaceNode.path(INTERFACETYPE).asText(); if (isValidDigit(interfaceType)) { ospfInterface.setInterfaceType(Integer.parseInt(interfaceType)); } else { log.debug("Wrong interfaceType: {}", interfaceType); return null; } ospfInterface.setReTransmitInterval(OspfUtil.RETRANSMITINTERVAL); ospfInterface.setMtu(OspfUtil.MTU); ospfInterface.setRouterPriority(OspfUtil.ROUTER_PRIORITY); return ospfInterface; } }