com.offbynull.portmapper.common.NetworkUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.offbynull.portmapper.common.NetworkUtils.java

Source

/*
 * Copyright (c) 2013-2014, Kasra Faghihi, All rights reserved.
 * 
 * This library 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; either
 * version 3.0 of the License, or (at your option) any later version.
 * 
 * This library 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 for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.offbynull.portmapper.common;

import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.nio.channels.MulticastChannel;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.commons.lang3.Validate;

/**
 * Network-related utility class.
 * @author Kasra Faghihi
 */
public final class NetworkUtils {
    /**
     * IPs grabbed from http://www.techspot.com/guides/287-default-router-ip-addresses/ + comments @ 1/19/2014.
     */
    @SuppressWarnings("PMD")
    private static final Set<String> PRESET_IPV4_GATEWAY_ADDRESSES = Collections
            .unmodifiableSet(new LinkedHashSet<>(Arrays.asList("192.168.1.1", // 3Com
                    "10.0.1.1", // Apple
                    "192.168.1.1", "192.168.1.220", // Asus
                    "192.168.2.1", "10.1.1.1", // Belkin
                    "192.168.15.1", // Cisco
                    "192.168.11.1", // Buffalo
                    "192.168.1.1", // Dell
                    "192.168.0.1", "192.168.0.30", "192.168.0.50", "192.168.1.1", "192.10.1.1.1", // D-Link
                    "192.168.0.1", "192.168.1.1", // Linksys
                    "192.168.2.1", // Microsoft
                    "192.168.10.1", "192.168.20.1", "192.168.30.1", "192.168.62.1", "192.168.100.1",
                    "192.168.102.1", "192.168.1.254", // Motorola
                    "192.168.1.254", // MSI
                    "192.168.0.1", "192.168.0.227", "192.168.1.1", // Netgear
                    "192.168.0.1", // Senao
                    "10.0.0.138", "192.168.1.254", // SpeedTouch
                    "10.0.0.138", // Telstra
                    "192.168.1.1", // TP-LINK
                    "192.168.0.1", "192.168.1.1", "192.168.2.1", "192.168.10.1", // Trendnet
                    "192.168.1.1", "192.168.2.1", "192.168.123.254", // U.S. Robotics
                    "192.168.1.1", "192.168.2.1", "192.168.4.1", "192.168.10.1", "192.168.1.254", "10.0.0.2",
                    "10.0.0.138" // Zyxel
    )));

    private NetworkUtils() {
        // do nothing
    }

    /**
     * Convert a IP address to a IPv6 address and dump as a byte array. Essentially, if the input is IPv4 it'll be converted to an
     * IPv4-to-IPv6 address. Otherwise, the IPv6 address will be dumped as-is.
     * @param address address to convert to a ipv6 byte array
     * @return ipv6 byte array
     * @throws NullPointerException if any argument is {@code null}
     */
    public static byte[] convertToIpv6Array(InetAddress address) {
        Validate.notNull(address);

        byte[] addrArr = address.getAddress();
        switch (addrArr.length) {
        case 4: {
            // convert ipv4 address to ipv4-mapped ipv6 address
            byte[] newAddrArr = new byte[16];
            newAddrArr[10] = (byte) 0xff;
            newAddrArr[11] = (byte) 0xff;
            System.arraycopy(addrArr, 0, newAddrArr, 12, 4);

            return newAddrArr;
        }
        case 16: {
            return addrArr;
        }
        default:
            throw new IllegalStateException();
        }
    }

    /**
     * Get IP addresses for all interfaces on this machine that are IPv4.
     * @return IPv4 addresses assigned to this machine
     * @throws IOException if there's an error
     * @throws NullPointerException if any argument is {@code null}
     */
    public static Set<InetAddress> getAllLocalIpv4Addresses() throws IOException {
        Set<InetAddress> ret = new HashSet<>();

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            Enumeration<InetAddress> addrs = networkInterface.getInetAddresses();
            while (addrs.hasMoreElements()) { // make sure atleast 1 ipv4 addr bound to interface
                InetAddress addr = addrs.nextElement();

                if (addr instanceof Inet4Address && !addr.isAnyLocalAddress()) {
                    ret.add(addr);
                }
            }
        }

        return ret;
    }

    /**
     * Get IP addresses for all interfaces on this machine that are IPv6.
     * @return IPv6 addresses assigned to this machine
     * @throws IOException if there's an error
     * @throws NullPointerException if any argument is {@code null}
     */
    public static Set<InetAddress> getAllLocalIpv6Addresses() throws IOException {
        Set<InetAddress> ret = new HashSet<>();

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            Enumeration<InetAddress> addrs = networkInterface.getInetAddresses();
            while (addrs.hasMoreElements()) { // make sure atleast 1 ipv4 addr bound to interface
                InetAddress addr = addrs.nextElement();

                if (addr instanceof Inet6Address && !addr.isAnyLocalAddress()) {
                    ret.add(addr);
                }
            }
        }

        return ret;
    }

    /**
     * Set a {@link MulticastChannel} to listen on all IPv4 interfaces.
     * @param channel multicast channel to listen on
     * @throws IOException if there's an error
     * @throws NullPointerException if any argument is {@code null}
     */
    public static void multicastListenOnAllIpv4InterfaceAddresses(MulticastChannel channel) throws IOException {
        Validate.notNull(channel);

        final InetAddress ipv4Group = InetAddress.getByName("224.0.0.1"); // NOPMD

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            Enumeration<InetAddress> addrs = networkInterface.getInetAddresses();
            while (addrs.hasMoreElements()) { // make sure atleast 1 ipv4 addr bound to interface
                InetAddress addr = addrs.nextElement();

                try {
                    if (addr instanceof Inet4Address) {
                        channel.join(ipv4Group, networkInterface);
                    }
                } catch (IOException ioe) { // NOPMD
                    // occurs with certain interfaces
                    // do nothing
                }
            }
        }
    }

    /**
     * Set a {@link MulticastChannel} to listen on all IPv6 interfaces.
     * @param channel multicast channel to listen on
     * @throws IOException if there's an error
     * @throws NullPointerException if any argument is {@code null}
     */
    public static void multicastListenOnAllIpv6InterfaceAddresses(MulticastChannel channel) throws IOException {
        Validate.notNull(channel);

        final InetAddress ipv6Group = InetAddress.getByName("ff02::1"); // NOPMD

        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            Enumeration<InetAddress> addrs = networkInterface.getInetAddresses();
            while (addrs.hasMoreElements()) { // make sure atleast 1 ipv4 addr bound to interface
                InetAddress addr = addrs.nextElement();

                try {
                    if (addr instanceof Inet6Address) {
                        channel.join(ipv6Group, networkInterface);
                    }
                } catch (IOException ioe) { // NOPMD
                    // occurs with certain interfaces, do nothing
                }
            }
        }
    }

    /**
     * Attempts to put together a list of gateway addresses using pre-set values and running OS-specific processes.
     * @return a list of possible addresses for gateway device
     * @throws InterruptedException if interrupted
     */
    public static Set<InetAddress> getPotentialGatewayAddresses() throws InterruptedException {
        // Ask OS for gateway address
        String netstatOutput = "";
        try {
            netstatOutput = ProcessUtils.runProcessAndDumpOutput(5000L, "netstat", "-rn");
        } catch (IOException ioe) { // NOPMD
            // do nothing
            if (Thread.currentThread().isInterrupted()) {
                throw new InterruptedException();
            }
        }
        LinkedHashSet<String> strAddresses = new LinkedHashSet<>(RegexUtils.findAllIpv4Addresses(netstatOutput));

        // Push in defaults
        strAddresses.addAll(PRESET_IPV4_GATEWAY_ADDRESSES);

        LinkedHashSet<InetAddress> addresses = new LinkedHashSet<>();
        for (String strAddress : strAddresses) {
            try {
                InetAddress addr = InetAddress.getByName(strAddress);
                if (!addr.isAnyLocalAddress()) {
                    addresses.add(addr);
                }
            } catch (UnknownHostException uhe) { // NOPMD
                // do nothing
            }
        }

        return addresses;
    }
}