1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.net.shared; 17 18 import static android.net.RouteInfo.RTN_THROW; 19 import static android.net.RouteInfo.RTN_UNICAST; 20 import static android.net.RouteInfo.RTN_UNREACHABLE; 21 22 import android.net.INetd; 23 import android.net.IpPrefix; 24 import android.net.RouteInfo; 25 import android.os.RemoteException; 26 import android.os.ServiceSpecificException; 27 28 import java.util.List; 29 30 /** @hide*/ 31 public class RouteUtils { 32 33 /** Used to modify the specified route. */ 34 public enum ModifyOperation { 35 ADD, 36 REMOVE, 37 } 38 findNextHop(final RouteInfo route)39 private static String findNextHop(final RouteInfo route) { 40 final String nextHop; 41 switch (route.getType()) { 42 case RTN_UNICAST: 43 if (route.hasGateway()) { 44 nextHop = route.getGateway().getHostAddress(); 45 } else { 46 nextHop = INetd.NEXTHOP_NONE; 47 } 48 break; 49 case RTN_UNREACHABLE: 50 nextHop = INetd.NEXTHOP_UNREACHABLE; 51 break; 52 case RTN_THROW: 53 nextHop = INetd.NEXTHOP_THROW; 54 break; 55 default: 56 nextHop = INetd.NEXTHOP_NONE; 57 break; 58 } 59 return nextHop; 60 } 61 62 /** Add |routes| to local network. */ addRoutesToLocalNetwork(final INetd netd, final String iface, final List<RouteInfo> routes)63 public static void addRoutesToLocalNetwork(final INetd netd, final String iface, 64 final List<RouteInfo> routes) { 65 66 for (RouteInfo route : routes) { 67 if (!route.isDefaultRoute()) { 68 modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID, route); 69 } 70 } 71 72 // IPv6 link local should be activated always. 73 modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID, 74 new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST)); 75 } 76 77 /** Remove routes from local network. */ removeRoutesFromLocalNetwork(final INetd netd, final List<RouteInfo> routes)78 public static int removeRoutesFromLocalNetwork(final INetd netd, final List<RouteInfo> routes) { 79 int failures = 0; 80 81 for (RouteInfo route : routes) { 82 try { 83 modifyRoute(netd, ModifyOperation.REMOVE, INetd.LOCAL_NET_ID, route); 84 } catch (IllegalStateException e) { 85 failures++; 86 } 87 } 88 89 return failures; 90 } 91 92 /** Add or remove |route|. */ modifyRoute(final INetd netd, final ModifyOperation op, final int netId, final RouteInfo route)93 public static void modifyRoute(final INetd netd, final ModifyOperation op, final int netId, 94 final RouteInfo route) { 95 final String ifName = route.getInterface(); 96 final String dst = route.getDestination().toString(); 97 final String nextHop = findNextHop(route); 98 99 try { 100 switch(op) { 101 case ADD: 102 netd.networkAddRoute(netId, ifName, dst, nextHop); 103 break; 104 case REMOVE: 105 netd.networkRemoveRoute(netId, ifName, dst, nextHop); 106 break; 107 default: 108 throw new IllegalStateException("Unsupported modify operation:" + op); 109 } 110 } catch (RemoteException | ServiceSpecificException e) { 111 throw new IllegalStateException(e); 112 } 113 } 114 115 } 116