Create a new 6to4 tunnel interface. - Android Network

Android examples for Network:IP Address

Description

Create a new 6to4 tunnel interface.

Demo Code

/*****************************************************************************
 *  Project: Android IPv6Config/*from w ww .ja  va2  s  .  com*/
 *  Description: Android application to change IPv6 kernel configuration
 *  Author: Ren? Mayrhofer
 *  Copyright: Ren? Mayrhofer, 2011-2014
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 
 * as published by the Free Software Foundation.
 *****************************************************************************/
import java.io.File;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main{
    /** Our logger for this class. */
    private final static Logger logger = java.util.logging.Logger
            .getLogger(Constants.LOG_TAG);
    /** Identifier for starting the MTU option in the interface line. */
    private final static String INTERFACE_MTU = "mtu";
    /** Search for the "ip" and "busybox" binaries at these locations. */
    public final static String[] LINUX_BINARY_LOCATIONS = { "/sbin/",
            "/bin/", "/system/bin/", "/system/xbin/" };
    /** Preferred is to use the "ip" binary directly. 
     * @see BUSYBOX_BINARY_PREFIX
     */
    public final static String IP_BINARY = "ip";
    /** But if no (working) ip binary can be found, then try to use busybox with an "ip" applet.
     * @see IP_BINARY
     */
    public final static String BUSYBOX_BINARY = "busybox";
    /** Command to get and set network interface addresses and options under modern Linux systems. */
    private final static String ADDRESSES_COMMAND = " addr";
    /** Command to get and set routes under modern Linux systems. */
    private final static String ROUTES_COMMAND = " route";
    /** Option to select only IPv6 addresses/routes. */
    private final static String OPTION_IPv6_ONLY = " -6 ";
    /** Simply the shell command (and if necessary path) to execute a standard POSIX shell. */
    public final static String SH_COMMAND = "sh";
    /** Command to get and set network interface status under modern Linux systems (up/down mostly). */
    private final static String SET_INTERFACE = " link set ";
    /** Option to set network interface up.  */
    private final static String UP = " up";
    /** Option to add network interface / addresses / routes. */
    private final static String ADD = " add ";
    /** Command to the "ip" binary to create a tunnel interface under modern Linux systems. */
    private final static String ADD_TUNNEL_INTERFACE = " tunnel" + ADD;
    private final static String ADD_TUNNEL_INTERFACE_OPTIONS_1 = " mode sit remote any local ";
    private final static String ADD_TUNNEL_INTERFACE_OPTIONS_2 = " ttl 255 ";
    /** Static initializer: find out where to call the "ip" binary from and remember for future use. */
    private static String ipBinaryLocation = null;
    private static String ipBinaryTriedPaths = null;
    /** Create a new 6to4 tunnel interface.
     * 
     * @param iface The interface name to create.
     * @param localIPv4Endpoint The local IPv4 endpoint address to assign to the tunnel.
     * @param ipv6Prefix The 6to4 prefix derived from the endpoint address that will be
     *                   used to create the IPv6 address.
     * @param mtu The maximum transfer unit for the new interface. If a value 
     *            <=0 is passed as argument, a default of 1430 will be used.
     * @return true if successfully created and addresses and routes added, false otherwise.
     */
    public static boolean create6to4TunnelInterface(String iface,
            Inet4Address localIPv4Endpoint, String ipv6Prefix, int mtu) {
        if (mtu <= 0)
            mtu = 1430;

        if (localIPv4Endpoint == null || ipv6Prefix == null
                || iface == null) {
            logger.severe("Unable to create 6to4 tunnel, null parameters");
            return false;
        }

        String cmdTunnel = getIPCommandLocation() + ADD_TUNNEL_INTERFACE
                + iface + ADD_TUNNEL_INTERFACE_OPTIONS_1
                + localIPv4Endpoint.getHostAddress()
                + ADD_TUNNEL_INTERFACE_OPTIONS_2;
        String cmdSetUp = getIPCommandLocation() + SET_INTERFACE + iface
                + UP + " " + INTERFACE_MTU + " " + mtu;
        /* Experienced IPv6 users will wonder why the netmask for sit0 is /16, not /64; 
         * by setting the netmask to /16, you instruct your system to send packets 
         * directly to the IPv4 address of other 6to4 users; if it was /64, you'd send 
         * packets via the nearest relay router, increasing latency. */
        String cmd6to4Addr = getIPCommandLocation() + OPTION_IPv6_ONLY
                + ADDRESSES_COMMAND + ADD + ipv6Prefix + "::/16 dev "
                + iface;
        String cmd6to4Route1 = getIPCommandLocation() + OPTION_IPv6_ONLY
                + ROUTES_COMMAND + ADD + " 0:0:0:0:0:ffff::/96 dev "
                + iface + " metric 1";
        String cmd6to4Route2 = getIPCommandLocation() + OPTION_IPv6_ONLY
                + ROUTES_COMMAND + ADD + " 2000::/3 via ::192.88.99.1 dev "
                + iface + " metric 1";

        try {
            logger.finer("Trying to create 6to4 tunnel interface " + iface
                    + " with local endpoint "
                    + localIPv4Endpoint.getHostAddress() + " for prefix "
                    + ipv6Prefix + " with MTU " + mtu);

            if (Command.executeCommand(SH_COMMAND, true, cmdTunnel, null,
                    null) != 0) {
                logger.severe("Unable to create tunnel interface " + iface);
                return false;
            }
            if (Command.executeCommand(SH_COMMAND, true, cmdSetUp, null,
                    null) != 0) {
                logger.severe("Unable to set tunnel interface " + iface
                        + " up with MTU " + mtu);
                return false;
            }
            if (Command.executeCommand(SH_COMMAND, true, cmd6to4Addr, null,
                    null) != 0) {
                logger.severe("Unable to add 6to4 address " + ipv6Prefix
                        + " to tunnel interface " + iface);
                return false;
            }
            if (Command.executeCommand(SH_COMMAND, true, cmd6to4Route1,
                    null, null) != 0) {
                logger.severe("Unable to add 6to4 route 1 to tunnel interface "
                        + iface);
                return false;
            }
            if (Command.executeCommand(SH_COMMAND, true, cmd6to4Route2,
                    null, null) != 0) {
                logger.severe("Unable to add 6to4 route 2 to tunnel interface "
                        + iface);
                return false;
            }

            logger.info("Successfully created 6to4 tunnel interface "
                    + iface + " with local endpoint "
                    + localIPv4Endpoint.getHostAddress() + " for prefix "
                    + ipv6Prefix + " with MTU " + mtu);
            return true;
        } catch (IOException e) {
            logger.severe("Unable to execute system command, tunnel interface not deleted (access privileges missing?) "
                    + e);
            return false;
        } catch (InterruptedException e) {
            return false;
        }
    }
    /** Helper to locate a usable "ip" command or null if none is found. */
    public static String getIPCommandLocation() {
        if (ipBinaryLocation == null) {
            ipBinaryTriedPaths = "";

            if (!tryIPBinaries(LINUX_BINARY_LOCATIONS, IP_BINARY, null)
                    && !tryIPBinaries(LINUX_BINARY_LOCATIONS,
                            BUSYBOX_BINARY, IP_BINARY))
                logger.severe("Could not find ip binary in"
                        + ipBinaryTriedPaths
                        + ", will be unable to read network interface details");
        }
        return ipBinaryLocation;
    }
    /** Helper function to try a list of paths with a command to verify if "ip addr" can be executed correctly.
     * 
     * @return true if a working "ip addr" call could be made, false otherwise. If true is returned,
     *          the working full binary path is stored in ipBinaryLocation.
     * @see ipBinaryLocation 
     */
    private static boolean tryIPBinaries(String[] paths, String cmd,
            String cmd2) {
        for (String path : paths) {
            String binary = path + cmd;
            // sanity check: can we actually execute our command?
            logger.finer("Checking for availibility of command '" + binary
                    + "'");
            if (new File(binary).canRead()) {
                if (cmd2 != null)
                    binary = binary + " " + cmd2;
                /* second sanity check: does this binary work?
                 * (E.g. on the Samsung Galaxy S2, there actually is a binary under 
                 * /system/bin/ip that claims to work, but doesn't).
                 */
                try {
                    logger.fine("Trying to execute cmd '" + binary
                            + ADDRESSES_COMMAND + "'");
                    Command.executeCommand(binary + ADDRESSES_COMMAND,
                            false, false, null);
                    logger.fine("Found working ip binary in " + binary);
                    ipBinaryLocation = binary;
                    return true;
                } catch (Exception e) {
                    logger.warning("Found ip binary in "
                            + binary
                            + ", but does not behave as expected. Trying next location.");
                }
            }
            ipBinaryTriedPaths = ipBinaryTriedPaths + " '" + binary + "'";
        }
        return false;
    }
}

Related Tutorials