/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.abiserver.networking; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringTokenizer; import com.abiquo.abiserver.exception.InvalidMaskException; import com.abiquo.abiserver.exception.InvalidPrivateNetworkClassTypeException; /** * This class is used to define all the ranges used by the private networks. */ public class NetworkResolver { /** * Specify all the masks user can choose */ private String[] allMasks = {"255.0.0.0", "255.128.0.0", "255.192.0.0", "255.224.0.0", "255.240.0.0", "255.248.0.0", "255.252.0.0", "255.254.0.0", "255.255.0.0", "255.255.128.0", "255.255.192.0", "255.255.224.0", "255.255.240.0", "255.255.248.0", "255.255.252.0", "255.255.254.0", "255.255.255.0", "255.255.255.128", "255.255.255.192", "255.255.255.224", "255.255.255.240", "255.255.255.248", "255.255.255.252"}; /** * List of values from 0 to 255 */ private List<String> possibleValues; /** * Error messages */ private static String CLASSTYPE_CANNOT_BE_NULL = "Network class type can not be null."; private static String INVALID_CLASSTYPE = "Invalid private network ClassType."; private static String INVALID_NETWORK_MASK = "Network mask is invalid."; public NetworkResolver() { possibleValues = new ArrayList<String>(); for (int i = 0; i < 256; i++) { possibleValues.add(String.valueOf(i)); } } /** * Retrieve the list of enabled masks. * * @param privateNetworkClassType class type of the subnet. * @return a list of available masks. * @throws InvalidPrivateNetworkClassTypeException if the privateNetworkClassType is not * supported. */ public List<String> resolveMask(final String privateNetworkClassType) throws InvalidPrivateNetworkClassTypeException { List<String> masks = new ArrayList<String>(); if (privateNetworkClassType == null) { throw new InvalidPrivateNetworkClassTypeException(CLASSTYPE_CANNOT_BE_NULL); } if (privateNetworkClassType.equalsIgnoreCase("A")) { // masks = Arrays.asList(allMasks); masks = Arrays.asList(allMasks).subList(14, allMasks.length); } else if (privateNetworkClassType.equalsIgnoreCase("B")) { // masks = Arrays.asList(allMasks).subList(8, allMasks.length); masks = Arrays.asList(allMasks).subList(14, allMasks.length); } else if (privateNetworkClassType.equalsIgnoreCase("C")) { masks = Arrays.asList(allMasks).subList(16, allMasks.length); } else { throw new InvalidPrivateNetworkClassTypeException(INVALID_CLASSTYPE); } return masks; } /** * @param privateNetworkClassType * @param mask * @return * @throws InvalidPrivateNetworkClassTypeException * @throws InvalidMaskException */ public List<List<String>> resolvePossibleNetworks(final String privateNetworkClassType, final IPAddress mask) throws InvalidPrivateNetworkClassTypeException, InvalidMaskException { List<List<String>> networks = new ArrayList<List<String>>(); List<String> firstElement = new ArrayList<String>(); List<String> secondElement = new ArrayList<String>(); List<String> thirdElement = new ArrayList<String>(); List<String> fourthElement = new ArrayList<String>(); String maskString = mask.toString(); // check correct values // First check if the class type is defined according with the standard network private // class types if (privateNetworkClassType == null || !privateNetworkClassType.equalsIgnoreCase("A") && !privateNetworkClassType.equalsIgnoreCase("B") && !privateNetworkClassType.equalsIgnoreCase("C")) { throw new InvalidPrivateNetworkClassTypeException(INVALID_CLASSTYPE); } // After check if the mask is inside the array of the accepted masks if (privateNetworkClassType.equalsIgnoreCase("A") && !Arrays.asList(allMasks).subList(14, allMasks.length).contains(maskString) || privateNetworkClassType.equalsIgnoreCase("B") && !Arrays.asList(allMasks).subList(14, allMasks.length).contains(maskString) || privateNetworkClassType.equalsIgnoreCase("C") && !Arrays.asList(allMasks).subList(16, allMasks.length).contains(maskString)) { throw new InvalidMaskException(INVALID_NETWORK_MASK); } StringTokenizer tokenizer = new StringTokenizer(maskString, "."); // First element of the list of lists. // First element is always depending on the class mask. tokenizer.nextToken(); firstElement.add(defineFirstList(privateNetworkClassType)); // Second element of the list of lists secondElement.addAll(defineSecondList(privateNetworkClassType, tokenizer.nextToken())); // Third and fourth element of the list token depends on absolutly the mask thirdElement.addAll(defineListFromMask(tokenizer.nextToken())); fourthElement.addAll(defineListFromMask(tokenizer.nextToken())); networks.add(firstElement); networks.add(secondElement); networks.add(thirdElement); networks.add(fourthElement); return networks; } /** * @param privateNetworkClassType * @return */ private String defineFirstList(final String privateNetworkClassType) { if (privateNetworkClassType.equalsIgnoreCase("A")) { return "10"; } else if (privateNetworkClassType.equalsIgnoreCase("B")) { return "172"; } else { return "192"; } } private List<String> defineSecondList(final String privateNetworkClassType, final String nextToken) { List<String> secondList = new ArrayList<String>(); if (privateNetworkClassType.equalsIgnoreCase("C")) { secondList.add("168"); } else if (privateNetworkClassType.equalsIgnoreCase("B")) { for (int i = 16; i < 32; i++) { secondList.add(String.valueOf(i)); } } else { secondList.addAll(defineListFromMask(nextToken)); } return secondList; } /** * From all the range of possible values in a network slot, it will return the sublist of all * the ranges that the user will choose depending on its mask. * * @param mask value from 0 to 255 * @return */ private List<String> defineListFromMask(final String mask) { int token = Integer.parseInt(mask); int numberOfValues = 256; String binari = Integer.toBinaryString(token); List<String> list = new ArrayList<String>(); if (mask.equalsIgnoreCase("0")) { list.add("0"); } else { int numberOfOnes = binari.lastIndexOf("1") + 1; for (int i = 0; i < numberOfOnes; i++) { numberOfValues = numberOfValues / 2; } list = mapModule(numberOfValues); } return list; } /** * Apply the operation module to all the values in array possibleValues. * * @param mod module value. * @return List of 'possibleValues' variable where its values are equal to 0 applying the * module. */ private List<String> mapModule(final Integer mod) { List<String> moduleZero = new ArrayList<String>(); for (String value : possibleValues) { if (Integer.valueOf(value) % mod == 0) { moduleZero.add(value); } } return moduleZero; } public static String getDhcpOption(final String networkAddress, final Integer mask, final String gateway) { IPAddress address = IPAddress.newIPAddress(networkAddress); int firstOctet = Integer.valueOf(address.getFirstOctet()); int secondOctet = Integer.valueOf(address.getSecondOctet()); int thirdOctet = Integer.valueOf(address.getThirdOctet()); int fouthOctet = Integer.valueOf(address.getFourthOctet()); String encoding = ""; if (mask >= 1 && mask < 8) { encoding = toHex(mask) + ":" + toHex(firstOctet) + ":"; } if (mask >= 8 && mask < 16) { encoding = toHex(mask) + ":" + toHex(firstOctet) + ":" + toHex(secondOctet); } if (mask >= 16 && mask < 24) { encoding = toHex(mask) + ":" + toHex(firstOctet) + ":" + toHex(secondOctet) + ":" + toHex(thirdOctet); } if (mask >= 24) { encoding = toHex(mask) + ":" + toHex(firstOctet) + ":" + toHex(secondOctet) + ":" + toHex(thirdOctet) + ":" + toHex(fouthOctet); } String[] gatewayIp = gateway.split("\\."); for (String element : gatewayIp) { encoding = encoding + ":" + toHex(Integer.valueOf(element)); } return encoding; } private static String toHex(final Integer val) { String valHex = Integer.toHexString(val).toUpperCase(); if (valHex.length() < 2) { valHex = "0" + valHex; } return valHex; } }