Package org.apache.james.dnsservice.library.inetnetwork

Source Code of org.apache.james.dnsservice.library.inetnetwork.InetNetworkBuilder

/****************************************************************
* 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.james.dnsservice.library.inetnetwork;

import java.net.UnknownHostException;

import org.apache.james.dnsservice.api.DNSService;
import org.apache.james.dnsservice.library.inetnetwork.model.Inet4Network;
import org.apache.james.dnsservice.library.inetnetwork.model.Inet6Network;
import org.apache.james.dnsservice.library.inetnetwork.model.InetNetwork;

/**
* <p>
* Builds a InetNetwork (Inet4Network or Inet6Network) in function on the
* provided string pattern that represents a subnet.
* </p>
*
* <p>
* Inet4Network is constructed based on the IPv4 subnet expressed in one of
* several formats:
*
* <pre>
*     IPv4 Format                     Example
*     Explicit address                127.0.0.1
*     Address with a wildcard         127.0.0.*
*     Domain name                     myHost.com
*     Domain name + prefix-length     myHost.com/24
*     Domain name + mask              myHost.com/255.255.255.0
*     IP address + prefix-length      127.0.0.0/8
*     IP + mask                       127.0.0.0/255.0.0.0
* </pre>
*
* For more information on IP V4, see RFC 1518 and RFC 1519.
* </p>
*
* <p>
* Inet6Network is constructed based on the IPv4 subnet expressed in one of
* several formats:
*
* <pre>
*     IPv6 Format                     Example
*     Explicit address                0000:0000:0000:0000:0000:0000:0000:0001
*     IP address + subnet mask (/)   0000:0000:0000:0000:0000:0000:0000:0001/64
*     IP address + subnet mask (%)   0000:0000:0000:0000:0000:0000:0000:0001%64
*     The following V6 formats will be supported later:
*     Domain name                     myHost.com
*     Domain name + mask (/)          myHost.com/48
*     Domain name + mask (%)          myHost.com%48
*     Explicit shorted address        ::1
* </pre>
*
* For more information on IP V6, see RFC 2460. (See also <a
* href="http://en.wikipedia.org/wiki/IPv6_address"
* >http://en.wikipedia.org/wiki/IPv6_address</a>)
* </p>
*/
public class InetNetworkBuilder {

    /**
     * The DNS Server used to create InetAddress for hostnames and IP adresses.
     */
    private final DNSService dnsService;

    /**
     * Constructs a InetNetwork.
     *
     * @param dnsServer
     *            the DNSService to use
     */
    public InetNetworkBuilder(DNSService dnsServer) {
        this.dnsService = dnsServer;
    }

    /**
     * Creates a InetNetwork for the given String. Depending on the provided
     * pattern and the platform configuration (IPv4 and/or IPv6), the returned
     * type will be Inet4Network or Inet6Network.
     *
     * @param netspec
     *            the String which is will converted to InetNetwork
     * @return network the InetNetwork
     * @throws java.net.UnknownHostException
     */
    public InetNetwork getFromString(String netspec) throws UnknownHostException {
        return isV6(netspec) ? getV6FromString(netspec) : getV4FromString(netspec);
    }

    /**
     * Returns true if the string parameters is a IPv6 pattern. Currently, only
     * tests for presence of ':'.
     *
     * @param netspec
     * @return boolean
     *              <code>true</code> if is a IPv6 pattern else <code>false</code>
     */
    public static boolean isV6(String netspec) {
        return netspec.contains(":");
    }

    /**
     * Get a Inet4Network for the given String.
     *
     * @param netspec
     *            the String which is will converted to InetNetwork
     * @return network the InetNetwork
     * @throws java.net.UnknownHostException
     */
    private InetNetwork getV4FromString(String netspec) throws UnknownHostException {

        if (netspec.endsWith("*")) {
            netspec = normalizeV4FromAsterisk(netspec);
        } else {
            int iSlash = netspec.indexOf('/');
            if (iSlash == -1) {
                netspec += "/255.255.255.255";
            } else if (netspec.indexOf('.', iSlash) == -1) {
                netspec = normalizeV4FromCIDR(netspec);
            }
        }

        return new Inet4Network(dnsService.getByName(netspec.substring(0, netspec.indexOf('/'))), dnsService.getByName(netspec.substring(netspec.indexOf('/') + 1)));
    }

    /**
     * Get a Inet6Network for the given String.
     *
     * @param netspec
     *            the String which is will converted to InetNetwork
     * @return network the InetNetwork
     * @throws java.net.UnknownHostException
     */
    private InetNetwork getV6FromString(String netspec) throws UnknownHostException {

        if (netspec.endsWith("*")) {
            throw new UnsupportedOperationException("Wildcard for IPv6 not supported");
        }

        // Netmask can be separated with %
        netspec = netspec.replaceAll("%", "/");

        if (netspec.indexOf('/') == -1) {
            netspec += "/32768";
        }

        return new Inet6Network(dnsService.getByName(netspec.substring(0, netspec.indexOf('/'))), new Integer(netspec.substring(netspec.indexOf('/') + 1)));
    }

    /**
     * This converts from an uncommon "wildcard" CIDR format to "address + mask"
     * format:
     *
     * <pre>
     * * => 000.000.000.0/000.000.000.0
     * xxx.* => xxx.000.000.0/255.000.000.0
     * xxx.xxx.* => xxx.xxx.000.0/255.255.000.0
     * xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0
     * </pre>
     *
     * @param netspec
     * @return addrMask the address/mask of the given argument
     */
    private static String normalizeV4FromAsterisk(final String netspec) {

        String[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" };

        char[] srcb = netspec.toCharArray();

        int octets = 0;

        for (int i = 1; i < netspec.length(); i++) {
            if (srcb[i] == '.')
                octets++;
        }

        return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() - 1).concat(masks[octets]);

    }

    /**
     * RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR) This converts from
     * "prefix + prefix-length" format to "address + mask" format, e.g. from
     *
     * <pre>
     * xxx.xxx.xxx.xxx / yy
     * </pre>
     *
     * to
     *
     * <pre>
     * xxx.xxx.xxx.xxx / yyy.yyy.yyy.yyy
     * </pre>
     *
     * .
     *
     * @param netspec
     *            the xxx.xxx.xxx.xxx/yyy format
     * @return addrMask the xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy format
     */
    private static String normalizeV4FromCIDR(final String netspec) {

        final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/') + 1));

        final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits) - 1);

        return netspec.substring(0, netspec.indexOf('/') + 1) + Integer.toString(mask >> 24 & 0xFF, 10) + "." + Integer.toString(mask >> 16 & 0xFF, 10) + "." + Integer.toString(mask >> 8 & 0xFF, 10) + "." + Integer.toString(mask & 0xFF, 10);
    }

}
TOP

Related Classes of org.apache.james.dnsservice.library.inetnetwork.InetNetworkBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.