下面列出了怎么用android.net.RouteInfo的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space.
*
* This returns true if the passed LinkedProperties contains routes to either most of the IPv4
* space or to most of the IPv6 address space, where "most" is defined by the value of the
* MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched
* by any of the routes, then it's decided that most of the space is routed.
* @hide
*/
@VisibleForTesting
static boolean providesRoutesToMostDestinations(LinkProperties lp) {
final List<RouteInfo> routes = lp.getAllRoutes();
if (routes.size() > MAX_ROUTES_TO_EVALUATE) return true;
final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator();
TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
for (final RouteInfo route : routes) {
IpPrefix destination = route.getDestination();
if (destination.isIPv4()) {
ipv4Prefixes.add(destination);
} else {
ipv6Prefixes.add(destination);
}
}
if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) {
return true;
}
return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes)
.compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
}
private LinkProperties makeLinkProperties(LinkAddress clatAddress) {
LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName(mIface);
// Although the clat interface is a point-to-point tunnel, we don't
// point the route directly at the interface because some apps don't
// understand routes without gateways (see, e.g., http://b/9597256
// http://b/9597516). Instead, set the next hop of the route to the
// clat IPv4 address itself (for those apps, it doesn't matter what
// the IP of the gateway is, only that there is one).
RouteInfo ipv4Default = new RouteInfo(
new LinkAddress(Inet4Address.ANY, 0),
clatAddress.getAddress(), mIface);
stacked.addRoute(ipv4Default);
stacked.addLinkAddress(clatAddress);
return stacked;
}
@Override
public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
// create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
final LinkAddress la = routeInfo.getDestinationLinkAddress();
cmd.appendArg(routeInfo.getInterface());
cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
if (routeInfo.hasGateway()) {
cmd.appendArg(routeInfo.getGateway().getHostAddress());
}
try {
mConnector.execute(cmd);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
for (RouteInfo route : prop.getAllRoutes()) {
// Currently legacy VPN only works on IPv4.
if (route.isDefaultRoute() && route.getGateway() instanceof Inet4Address) {
return route;
}
}
throw new IllegalStateException("Unable to find IPv4 default gateway");
}
private static ArrayList<RouteInfo> getLocalRoutesFor(
String ifname, HashSet<IpPrefix> prefixes) {
final ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
for (IpPrefix ipp : prefixes) {
localRoutes.add(new RouteInfo(ipp, null, ifname));
}
return localRoutes;
}
public void removeDownstreamInterface(String ifname) {
final LinkProperties lp = mDownstreams.remove(ifname);
if (lp == null) return;
if (!started()) return;
for (RouteInfo route : lp.getRoutes()) {
if (shouldIgnoreDownstreamRoute(route)) continue;
mHwInterface.removeDownstreamPrefix(ifname, route.getDestination().toString());
}
}
private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) {
final LinkProperties v6only = new LinkProperties();
if (lp == null) {
return v6only;
}
// NOTE: At this time we don't copy over any information about any
// stacked links. No current stacked link configuration has IPv6.
v6only.setInterfaceName(lp.getInterfaceName());
v6only.setMtu(lp.getMtu());
for (LinkAddress linkAddr : lp.getLinkAddresses()) {
if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) {
v6only.addLinkAddress(linkAddr);
}
}
for (RouteInfo routeInfo : lp.getRoutes()) {
final IpPrefix destination = routeInfo.getDestination();
if ((destination.getAddress() instanceof Inet6Address) &&
(destination.getPrefixLength() <= 64)) {
v6only.addRoute(routeInfo);
}
}
for (InetAddress dnsServer : lp.getDnsServers()) {
if (isIPv6GlobalAddress(dnsServer)) {
// For now we include ULAs.
v6only.addDnsServer(dnsServer);
}
}
v6only.setDomains(lp.getDomains());
return v6only;
}
private static LinkProperties getUniqueLocalConfig(byte[] ulp, short subnetId) {
final LinkProperties lp = new LinkProperties();
final IpPrefix local48 = makeUniqueLocalPrefix(ulp, (short) 0, 48);
lp.addRoute(new RouteInfo(local48, null, null));
final IpPrefix local64 = makeUniqueLocalPrefix(ulp, subnetId, 64);
// Because this is a locally-generated ULA, we don't have an upstream
// address. But because the downstream IP address management code gets
// its prefix from the upstream's IP address, we create a fake one here.
lp.addLinkAddress(new LinkAddress(local64.getAddress(), 64));
lp.setMtu(NetworkConstants.ETHER_MTU);
return lp;
}
/**
* Notify our observers of a route change.
*/
private void notifyRouteChange(String action, RouteInfo route) {
if (action.equals("updated")) {
invokeForAllObservers(o -> o.routeUpdated(route));
} else {
invokeForAllObservers(o -> o.routeRemoved(route));
}
}
private void modifyRoute(String action, String netId, RouteInfo route) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
final Command cmd = new Command("network", "route", action, netId);
// create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
cmd.appendArg(route.getInterface());
cmd.appendArg(route.getDestination().toString());
switch (route.getType()) {
case RouteInfo.RTN_UNICAST:
if (route.hasGateway()) {
cmd.appendArg(route.getGateway().getHostAddress());
}
break;
case RouteInfo.RTN_UNREACHABLE:
cmd.appendArg("unreachable");
break;
case RouteInfo.RTN_THROW:
cmd.appendArg("throw");
break;
}
try {
mConnector.execute(cmd);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
}
@Override
public void tetherInterface(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
mConnector.execute("tether", "interface", "add", iface);
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
List<RouteInfo> routes = new ArrayList<>();
// The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
// suitable to use as a route destination.
routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
addInterfaceToLocalNetwork(iface, routes);
}
@Override
public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
modifyInterfaceInNetwork("add", "local", iface);
for (RouteInfo route : routes) {
if (!route.isDefaultRoute()) {
modifyRoute("add", "local", route);
}
}
}
@Override
public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
int failures = 0;
for (RouteInfo route : routes) {
try {
modifyRoute("remove", "local", route);
} catch (IllegalStateException e) {
failures++;
}
}
return failures;
}
/**
* Returns true if the specified link properties have any default route
* @param linkProperties
* @return true if the specified link properties have default route or false otherwise
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private boolean linkPropertiesHasDefaultRoute(LinkProperties linkProperties) {
for (RouteInfo route : linkProperties.getRoutes()) {
if (route.isDefaultRoute()) {
return true;
}
}
return false;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean hasDefaultRoute(LinkProperties linkProperties) {
for (RouteInfo route : linkProperties.getRoutes()) {
if (route.isDefaultRoute()) {
return true;
}
}
return false;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean hasDefaultRoute(LinkProperties linkProperties) {
for(RouteInfo route: linkProperties.getRoutes()) {
if (route.isDefaultRoute()) {
return true;
}
}
return false;
}
public NetworkDiagnostics(Network network, LinkProperties lp, long timeoutMs) {
mNetwork = network;
mLinkProperties = lp;
mInterfaceIndex = getInterfaceIndex(mLinkProperties.getInterfaceName());
mTimeoutMs = timeoutMs;
mStartTime = now();
mDeadlineTime = mStartTime + mTimeoutMs;
// Hardcode measurements to TEST_DNS4 and TEST_DNS6 in order to test off-link connectivity.
// We are free to modify mLinkProperties with impunity because ConnectivityService passes us
// a copy and not the original object. It's easier to do it this way because we don't need
// to check whether the LinkProperties already contains these DNS servers because
// LinkProperties#addDnsServer checks for duplicates.
if (mLinkProperties.isReachable(TEST_DNS4)) {
mLinkProperties.addDnsServer(TEST_DNS4);
}
// TODO: we could use mLinkProperties.isReachable(TEST_DNS6) here, because we won't set any
// DNS servers for which isReachable() is false, but since this is diagnostic code, be extra
// careful.
if (mLinkProperties.hasGlobalIPv6Address() || mLinkProperties.hasIPv6DefaultRoute()) {
mLinkProperties.addDnsServer(TEST_DNS6);
}
for (RouteInfo route : mLinkProperties.getRoutes()) {
if (route.hasGateway()) {
InetAddress gateway = route.getGateway();
prepareIcmpMeasurement(gateway);
if (route.isIPv6Default()) {
prepareExplicitSourceIcmpMeasurements(gateway);
}
}
}
for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
prepareIcmpMeasurement(nameserver);
prepareDnsMeasurement(nameserver);
}
mCountDownLatch = new CountDownLatch(totalMeasurementCount());
startMeasurements();
mDescription = "ifaces{" + TextUtils.join(",", mLinkProperties.getAllInterfaceNames()) + "}"
+ " index{" + mInterfaceIndex + "}"
+ " network{" + mNetwork + "}"
+ " nethandle{" + mNetwork.getNetworkHandle() + "}";
}
private boolean pushUpstreamParameters(String prevUpstream) {
final String iface = currentUpstreamInterface();
if (TextUtils.isEmpty(iface)) {
final boolean rval = mHwInterface.setUpstreamParameters("", ANYIP, ANYIP, null);
// Update stats after we've told the hardware to stop forwarding so
// we don't miss packets.
maybeUpdateStats(prevUpstream);
return rval;
}
// A stacked interface cannot be an upstream for hardware offload.
// Consequently, we examine only the primary interface name, look at
// getAddresses() rather than getAllAddresses(), and check getRoutes()
// rather than getAllRoutes().
final ArrayList<String> v6gateways = new ArrayList<>();
String v4addr = null;
String v4gateway = null;
for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) {
if (ip instanceof Inet4Address) {
v4addr = ip.getHostAddress();
break;
}
}
// Find the gateway addresses of all default routes of either address family.
for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) {
if (!ri.hasGateway()) continue;
final String gateway = ri.getGateway().getHostAddress();
if (ri.isIPv4Default()) {
v4gateway = gateway;
} else if (ri.isIPv6Default()) {
v6gateways.add(gateway);
}
}
boolean success = mHwInterface.setUpstreamParameters(
iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
if (!success) {
return success;
}
// Update stats after we've told the hardware to change routing so we don't miss packets.
maybeUpdateStats(prevUpstream);
// Data limits can only be set once offload is running on the upstream.
success = maybeUpdateDataLimit(iface);
if (!success) {
// If we failed to set a data limit, don't use this upstream, because we don't want to
// blow through the data limit that we were told to apply.
mLog.log("Setting data limit for " + iface + " failed, disabling offload.");
stop();
}
return success;
}
private static boolean shouldIgnoreDownstreamRoute(RouteInfo route) {
// Ignore any link-local routes.
if (!route.getDestinationLinkAddress().isGlobalPreferred()) return true;
return false;
}
private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
final RouteInfo ri = (lp != null)
? RouteInfo.selectBestRoute(lp.getAllRoutes(), dst)
: null;
return (ri != null) ? ri.getInterface() : null;
}
private static String getInterfaceForDestination(LinkProperties lp, InetAddress dst) {
final RouteInfo ri = (lp != null)
? RouteInfo.selectBestRoute(lp.getAllRoutes(), dst)
: null;
return (ri != null) ? ri.getInterface() : null;
}
@Override
public void addRoute(int netId, RouteInfo route) {
modifyRoute("add", "" + netId, route);
}
@Override
public void removeRoute(int netId, RouteInfo route) {
modifyRoute("remove", "" + netId, route);
}