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

org.apache.brooklyn.util.net.Cidr Maven / Gradle / Ivy

Go to download

Utility classes and methods developed for Brooklyn but not dependendent on Brooklyn or much else

There is a newer version: 1.1.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.brooklyn.util.net;


import java.io.Serializable;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.List;

import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.math.BitList;
import org.apache.brooklyn.util.math.BitUtils;
import org.apache.brooklyn.util.text.Strings;

import com.google.common.collect.ImmutableList;

/** represents a CIDR (classless inter-domain routing) token, i.e. 10.0.0.0/8 or 192.168.4.0/24 */
public class Cidr implements Serializable {

    private static final long serialVersionUID = -4605909101590811958L;

    /** 0.0.0.0/0 -- matches all addresses */
    public static final Cidr UNIVERSAL = new Cidr();
    
    public static final Cidr _10 = new Cidr(10);
    public static final Cidr _172_16 = new Cidr("172.16.0.0/12");
    public static final Cidr _192_168 = new Cidr(192, 168);
    public static final Cidr CLASS_A = _10;
    public static final Cidr CLASS_B = _172_16;
    public static final Cidr CLASS_C = _192_168;
    
    public static final List PRIVATE_NETWORKS_RFC_1918 = ImmutableList.of(_192_168, _172_16, _10);
    
    public static final Cidr _169_254 = new Cidr("169.254.0.0/16");
    public static final Cidr LINK_LOCAL = _169_254;
    
    public static final Cidr _127 = new Cidr("127.0.0.0/8");
    public static final Cidr LOOPBACK = _127;

    public static final List NON_PUBLIC_CIDRS = ImmutableList.builder().addAll(PRIVATE_NETWORKS_RFC_1918).add(LINK_LOCAL).add(LOOPBACK).build();


    final int[] subnetBytes = new int[] { 0, 0, 0, 0 };
    final int length;
    
    
    public Cidr(String cidr) {
        if (Strings.isBlank(cidr))
            // useful e.g. if user leaves it blank in gui
            cidr = "0.0.0.0/0";
        int slash = cidr.indexOf('/');
        if (slash==-1) throw new IllegalArgumentException("CIDR should be of form 192.168.0.0/16 (missing slash); input="+cidr);
        String subnet = cidr.substring(0, slash);
        String lengthS = cidr.substring(slash+1);
        this.length = Integer.parseInt(lengthS);
        String[] bytes = subnet.split("\\.");
        int i=0;
        for (; i4)
            throw new IllegalArgumentException("Cannot create CIDR beyond 4 bytes: "+Arrays.toString(subnetBytes));
        if (length>32)
            throw new IllegalArgumentException("Cannot create CIDR beyond 4 bytes: length "+length);
        // reverse the bits to remove zeroed bits, then reverse back
        byte[] significantSubnetBytes = BitList.newInstance(BitUtils.reverseBitSignificanceInBytes(subnetBytes)).resized(length).asBytes();
        for (int i=0; i0) sb.append(".");
            sb.append(""+subnetBytes[i]);
            i++;
        }
        while (i<4) {
            if (sb.length()>0) sb.append(".");
            sb.append("0");
            i++;
        }
        sb.append("/");
        sb.append(""+length);
        return sb.toString();
    }

    public int[] getBytes() {
        return Arrays.copyOf(subnetBytes, 4);
    }

    public int getLength() {
        return length;
    }

    public Cidr subnet(int ...extraUnsignedBytes) {
        if ((length%8)!=0) throw new IllegalStateException("subnet can only be used for byte boundary subnetted CIDR's; not "+this);
        int[] newBytes = getBytes();
        int newLen = this.length + extraUnsignedBytes.length*8;
        if (newLen>32) throw new IllegalStateException("further subnet for "+Arrays.toString(extraUnsignedBytes)+" not possible on CIDR "+this);
        for (int i=0; i0) {
            if (lengthLeft>=8) {
                netmaskBytes[i] = (byte)255;
            } else {
                netmaskBytes[i] = (byte) ( (1 << lengthLeft) - 1 );
            }
            lengthLeft -= 8;
            i++;
        }
        return Networking.getInetAddressWithFixedName(netmaskBytes);
    }

    /** taking the addresses in the CIDR in order, returns the one in the offset^th position 
     * (starting with the CIDR itself, even if final bits are 0) */
    public InetAddress addressAtOffset(int offset) {
        int[] ints = getBytes();
        ints[3] += offset;
        {
            int i=3;
            while (ints[i]>=256) {
                ints[i-1] += (ints[i] / 256);
                ints[i] %= 256;
                i--;
            }
        }
        byte[] bytes = new byte[] { 0, 0, 0, 0 };
        for (int i=0; i<4; i++)
            bytes[i] = (byte) ints[i];
        return Networking.getInetAddressWithFixedName(bytes);
    }

    /** returns length of the prefix in common between the two cidrs */
    public int commonPrefixLength(Cidr other) {
        return asBitList().commonPrefixLength(other.asBitList());
    }

    public Cidr commonPrefix(Cidr other) {
        return new Cidr(other.getBytes(), commonPrefixLength(other));
    }

    /** returns list of bits for the significant (length) bits of this CIDR */ 
    public BitList asBitList() {
        return BitList.newInstance(BitUtils.reverseBitSignificanceInBytes(getBytes())).resized(getLength());
    }
    
    public boolean contains(Cidr target) {
        return commonPrefixLength(target) == getLength();
    }

    // FIXME remove from here, promote NetworkUtils
    /** @deprecated use {@link Networking#getInetAddressWithFixedName(byte[])} */
    @Deprecated
    public static InetAddress getInetAddressWithFixedName(byte[] ip) {
        return Networking.getInetAddressWithFixedName(ip);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy