1 /* 2 * Copyright (C) 2017 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 17 package android.net.ip; 18 19 import android.net.INetd; 20 import android.net.InterfaceConfigurationParcel; 21 import android.net.LinkAddress; 22 import android.net.util.SharedLog; 23 import android.os.RemoteException; 24 import android.os.ServiceSpecificException; 25 import android.system.OsConstants; 26 27 import java.net.Inet4Address; 28 import java.net.InetAddress; 29 30 31 /** 32 * Encapsulates the multiple IP configuration operations performed on an interface. 33 * 34 * TODO: refactor/eliminate the redundant ways to set and clear addresses. 35 * 36 * @hide 37 */ 38 public class InterfaceController { 39 private final static boolean DBG = false; 40 41 private final String mIfName; 42 private final INetd mNetd; 43 private final SharedLog mLog; 44 InterfaceController(String ifname, INetd netd, SharedLog log)45 public InterfaceController(String ifname, INetd netd, SharedLog log) { 46 mIfName = ifname; 47 mNetd = netd; 48 mLog = log; 49 } 50 setInterfaceAddress(LinkAddress addr)51 private boolean setInterfaceAddress(LinkAddress addr) { 52 final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel(); 53 ifConfig.ifName = mIfName; 54 ifConfig.ipv4Addr = addr.getAddress().getHostAddress(); 55 ifConfig.prefixLength = addr.getPrefixLength(); 56 ifConfig.hwAddr = ""; 57 ifConfig.flags = new String[0]; 58 try { 59 mNetd.interfaceSetCfg(ifConfig); 60 } catch (RemoteException | ServiceSpecificException e) { 61 logError("Setting IPv4 address to %s/%d failed: %s", 62 ifConfig.ipv4Addr, ifConfig.prefixLength, e); 63 return false; 64 } 65 return true; 66 } 67 68 /** 69 * Set the IPv4 address of the interface. 70 */ setIPv4Address(LinkAddress address)71 public boolean setIPv4Address(LinkAddress address) { 72 if (!(address.getAddress() instanceof Inet4Address)) { 73 return false; 74 } 75 return setInterfaceAddress(address); 76 } 77 78 /** 79 * Clear the IPv4Address of the interface. 80 */ clearIPv4Address()81 public boolean clearIPv4Address() { 82 return setInterfaceAddress(new LinkAddress("0.0.0.0/0")); 83 } 84 setEnableIPv6(boolean enabled)85 private boolean setEnableIPv6(boolean enabled) { 86 try { 87 mNetd.interfaceSetEnableIPv6(mIfName, enabled); 88 } catch (RemoteException | ServiceSpecificException e) { 89 logError("%s IPv6 failed: %s", (enabled ? "enabling" : "disabling"), e); 90 return false; 91 } 92 return true; 93 } 94 95 /** 96 * Enable IPv6 on the interface. 97 */ enableIPv6()98 public boolean enableIPv6() { 99 return setEnableIPv6(true); 100 } 101 102 /** 103 * Disable IPv6 on the interface. 104 */ disableIPv6()105 public boolean disableIPv6() { 106 return setEnableIPv6(false); 107 } 108 109 /** 110 * Enable or disable IPv6 privacy extensions on the interface. 111 * @param enabled Whether the extensions should be enabled. 112 */ setIPv6PrivacyExtensions(boolean enabled)113 public boolean setIPv6PrivacyExtensions(boolean enabled) { 114 try { 115 mNetd.interfaceSetIPv6PrivacyExtensions(mIfName, enabled); 116 } catch (RemoteException | ServiceSpecificException e) { 117 logError("error %s IPv6 privacy extensions: %s", 118 (enabled ? "enabling" : "disabling"), e); 119 return false; 120 } 121 return true; 122 } 123 124 /** 125 * Set IPv6 address generation mode on the interface. 126 * 127 * <p>IPv6 should be disabled before changing the mode. 128 */ setIPv6AddrGenModeIfSupported(int mode)129 public boolean setIPv6AddrGenModeIfSupported(int mode) { 130 try { 131 mNetd.setIPv6AddrGenMode(mIfName, mode); 132 } catch (RemoteException e) { 133 logError("Unable to set IPv6 addrgen mode: %s", e); 134 return false; 135 } catch (ServiceSpecificException e) { 136 if (e.errorCode != OsConstants.EOPNOTSUPP) { 137 logError("Unable to set IPv6 addrgen mode: %s", e); 138 return false; 139 } 140 } 141 return true; 142 } 143 144 /** 145 * Add an address to the interface. 146 */ addAddress(LinkAddress addr)147 public boolean addAddress(LinkAddress addr) { 148 return addAddress(addr.getAddress(), addr.getPrefixLength()); 149 } 150 151 /** 152 * Add an address to the interface. 153 */ addAddress(InetAddress ip, int prefixLen)154 public boolean addAddress(InetAddress ip, int prefixLen) { 155 try { 156 mNetd.interfaceAddAddress(mIfName, ip.getHostAddress(), prefixLen); 157 } catch (ServiceSpecificException | RemoteException e) { 158 logError("failed to add %s/%d: %s", ip, prefixLen, e); 159 return false; 160 } 161 return true; 162 } 163 164 /** 165 * Remove an address from the interface. 166 */ removeAddress(InetAddress ip, int prefixLen)167 public boolean removeAddress(InetAddress ip, int prefixLen) { 168 try { 169 mNetd.interfaceDelAddress(mIfName, ip.getHostAddress(), prefixLen); 170 } catch (ServiceSpecificException | RemoteException e) { 171 logError("failed to remove %s/%d: %s", ip, prefixLen, e); 172 return false; 173 } 174 return true; 175 } 176 177 /** 178 * Remove all addresses from the interface. 179 */ clearAllAddresses()180 public boolean clearAllAddresses() { 181 try { 182 mNetd.interfaceClearAddrs(mIfName); 183 } catch (Exception e) { 184 logError("Failed to clear addresses: %s", e); 185 return false; 186 } 187 return true; 188 } 189 logError(String fmt, Object... args)190 private void logError(String fmt, Object... args) { 191 mLog.e(String.format(fmt, args)); 192 } 193 } 194