Tries to force the interface to reset its IPv6 addresses by setting it down and then up. - Android Network

Android examples for Network:IPv6

Description

Tries to force the interface to reset its IPv6 addresses by setting it down and then up.

Demo Code

/*****************************************************************************
 *  Project: Android IPv6Config//from w  w  w . j  ava 2 s. c om
 *  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);
    /** Identifies the gateway of a route. */
    private final static String ROUTE_GATEWAY = "via";
    /** Identifies the device of a route. */
    private final static String ROUTE_DEVICE = "dev";
    /** 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";
    /** Path for the IPv6 configuration kernel options. */
    public final static String IPV6_CONFIG_TREE = "/proc/sys/net/ipv6/conf/";
    /** Interface "name" to denote all network interface for kernel configuration options. */
    private final static String CONF_INTERFACES_ALL = "all";
    /** Interface "name" to denote the default kernel configuration options for new (hotplug enabled) network interfaces. */
    private final static String CONF_INTERFACES_DEFAULT = "default";
    /** 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 set network interface down. */
    private final static String DOWN = " down";
    /** Option to add network interface / addresses / routes. */
    private final static String ADD = " add ";
    /** Delay between setting an interface down and up to force its IPv6 address to be reset (in milliseconds). */
    public final static int INTERFACE_DOWN_UP_DELAY = 100;
    /** 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;
    /** Tries to force the interface to reset its addresses by setting it down and then up. */
    public static boolean forceAddressReload(String iface) {
        String cmd = getIPCommandLocation() + SET_INTERFACE + iface + " ";

        try {
            if (Command.executeCommand(SH_COMMAND, true, cmd + DOWN, null,
                    null) == 0) {
                // wait just a little for the interface to properly go down
                Thread.sleep(INTERFACE_DOWN_UP_DELAY);
                if (Command.executeCommand(SH_COMMAND, true, cmd + UP,
                        null, null) == 0) {
                    logger.finer("Reset interface " + iface
                            + " to force address reload");
                    return true;
                } else {
                    logger.warning("Set interface " + iface
                            + " down but was unable to set it up again");
                    return false;
                }
            } else {
                logger.warning("Unable to set interface " + iface + " down");
                return false;
            }
        } catch (IOException e) {
            logger.severe("Unable to execute system command, new addresses may not have been set (access privileges missing?) "
                    + e);
            return false;
        } catch (InterruptedException e) {
            return false;
        }
    }
    /** Tries to force all specified interfaces to reset their addresses by setting them down and then up. */
    public static boolean forceAddressReload(List<String> ifaces) {
        boolean ret = true;
        LinkedList<String> downedIfaces = new LinkedList<String>();

        String cmd = getIPCommandLocation() + SET_INTERFACE;

        // remember the default route so that we can restore it later on
        String currentDefaultRoute = getIPv4DefaultRouteSpecification();

        try {
            // first set all interfaces down
            for (String iface : ifaces) {
                // only try to enable if this is indeed known as an IPv6-capable interface to the kernel
                File configDir = new File(IPV6_CONFIG_TREE + iface);
                if (configDir.isDirectory()
                        && !iface.equals(CONF_INTERFACES_ALL)
                        && !iface.equals(CONF_INTERFACES_DEFAULT)) {
                    if (Command.executeCommand(SH_COMMAND, true, cmd
                            + iface + DOWN, null, null) == 0)
                        downedIfaces.add(iface);
                    else {
                        logger.warning("Unable to set interface " + iface
                                + " down, will not try to set it up again");
                        ret = false;
                    }
                }
            }

            // then wait just a little for the interfaces to properly go down
            Thread.sleep(INTERFACE_DOWN_UP_DELAY);

            // and start all those again that were set down
            for (String iface : downedIfaces) {
                if (Command.executeCommand(SH_COMMAND, true, cmd + iface
                        + UP, null, null) == 0)
                    logger.finer("Reset interface " + iface
                            + " to force address reload");
                else {
                    logger.warning("Set interface " + iface
                            + " down but was unable to set it up again");
                    ret = false;
                }
            }

            // if we had one, restore old default route
            if (currentDefaultRoute != null
                    && currentDefaultRoute.length() > 0) {
                if (Command.executeCommand(SH_COMMAND, true,
                        getIPCommandLocation() + ROUTES_COMMAND + ADD
                                + currentDefaultRoute, null, null) == 0)
                    logger.fine("Reloaded default route '"
                            + currentDefaultRoute + "'");
                else {
                    logger.warning("Unable to reload default route '"
                            + currentDefaultRoute
                            + "', connectivity may be broken until next network interface change!");
                }
            }

            return ret;
        } catch (IOException e) {
            logger.severe("Unable to execute system command, new addresses may not have been set (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;
    }
    /** Returns the IPv4 default route specification (the full line of 
     * "ip route" output) for restoring it later on (e.g. after an interface
     * reload) or null if no default route is known.
     */
    public static String getIPv4DefaultRouteSpecification() {
        LinkedList<RouteDetail> routes;
        try {
            routes = LinuxIPCommandHelper.getRouteOutput(false);
            for (RouteDetail route : routes) {
                if (route.target.equalsIgnoreCase("default")
                        || route.target.equals("0.0.0.0/0")) {
                    // ok, default route found
                    logger.info("Found default IPv4 route pointing to gateway '"
                            + route.gateway
                            + "' on interface '"
                            + route.iface + "'");
                    return route.fullRouteLine;
                }
            }
        } catch (IOException e) {
            logger.warning("Unable to query Linux IPv4 main routing table"
                    + e);
        }
        return null;
    }
    /** 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;
    }
    /** Returns the list of routes in the main routing table. 
     *  
     * @param queryIPv6 If true, then IPv6 routes are queried. If false, then IPv4 routes are queried.
     */
    public static LinkedList<RouteDetail> getRouteOutput(boolean queryIPv6)
            throws IOException {
        String cmd = getIPCommandLocation()
                + (queryIPv6 ? OPTION_IPv6_ONLY : "") + ROUTES_COMMAND;
        StringTokenizer lines = null;
        LinkedList<RouteDetail> list = new LinkedList<RouteDetail>();

        logger.warning("Acquiring route details with command '" + cmd + "'");

        try {
            lines = new StringTokenizer(Command.executeCommand(cmd, false,
                    false, null), "\n");
        } catch (Exception e) {
            logger.log(Level.WARNING,
                    "Tried to parse routes, but could not", e);
        }

        RouteDetail cur = null;
        while (lines != null && lines.hasMoreTokens()) {
            String line = lines.nextToken();
            logger.finest("getRouteOutput: parsing line '" + line + "'");

            StringTokenizer fields = new StringTokenizer(line, " \t");

            // the first field is always the target
            cur = new RouteDetail();
            cur.fullRouteLine = line;
            cur.target = fields.nextToken();

            // then we get options defined by "dev" or "via" (and others that we ignore)
            while (fields.hasMoreTokens()) {
                String opt = fields.nextToken().trim();
                logger.finest("getRouteOutput: trying to parse option '"
                        + opt + "'");

                if (opt.equals(ROUTE_GATEWAY) && fields.hasMoreTokens()) {
                    cur.gateway = InetAddress.getByName(fields.nextToken()
                            .trim());
                    logger.finest("getRouteOutput: found gateway "
                            + cur.gateway + " for target " + cur.target);
                } else if (opt.equals(ROUTE_DEVICE)
                        && fields.hasMoreTokens()) {
                    cur.iface = fields.nextToken().trim();
                    logger.finest("getRouteOutput: found interface "
                            + cur.iface + " for target " + cur.target);
                } else {
                    logger.finest("getRouteOutput: ignoring unknown option '"
                            + opt
                            + "' or no further field in string. Cannot parse.");
                }
            }

            // line finished, add route to list
            list.add(cur);
        }

        return list;
    }
}

Related Tutorials