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 17 package android.net.ipsec.ike; 18 19 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_ADDRESS; 20 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DHCP; 21 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_DNS; 22 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_NETMASK; 23 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP4_SUBNET; 24 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_ADDRESS; 25 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_DNS; 26 import static com.android.internal.net.ipsec.ike.message.IkeConfigPayload.CONFIG_ATTR_INTERNAL_IP6_SUBNET; 27 28 import android.annotation.NonNull; 29 import android.annotation.SystemApi; 30 import android.net.IpPrefix; 31 import android.net.LinkAddress; 32 33 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload; 34 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttribute; 35 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Address; 36 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dhcp; 37 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Dns; 38 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Netmask; 39 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv4Subnet; 40 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Address; 41 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Dns; 42 import com.android.internal.net.ipsec.ike.message.IkeConfigPayload.ConfigAttributeIpv6Subnet; 43 44 import java.net.InetAddress; 45 import java.util.ArrayList; 46 import java.util.Collections; 47 import java.util.List; 48 import java.util.Objects; 49 50 /** 51 * ChildSessionConfiguration represents the negotiated configuration for a Child Session. 52 * 53 * <p>Configurations include traffic selectors and internal network information. 54 */ 55 public final class ChildSessionConfiguration { 56 private static final int IPv4_DEFAULT_PREFIX_LEN = 32; 57 58 private final List<IkeTrafficSelector> mInboundTs = new ArrayList<>(); 59 private final List<IkeTrafficSelector> mOutboundTs = new ArrayList<>(); 60 private final List<LinkAddress> mInternalAddressList = new ArrayList<>(); 61 private final List<InetAddress> mInternalDnsAddressList = new ArrayList<>(); 62 private final List<IpPrefix> mSubnetAddressList = new ArrayList<>(); 63 private final List<InetAddress> mInternalDhcpAddressList = new ArrayList<>(); 64 65 /** 66 * Construct an instance of {@link ChildSessionConfiguration}. 67 * 68 * <p>ChildSessionConfiguration may contain negotiated configuration information that is 69 * included in a Configure(Reply) Payload. Thus the input configPayload should always be a 70 * Configure(Reply), and never be a Configure(Request). 71 * 72 * @hide 73 */ ChildSessionConfiguration( List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs, IkeConfigPayload configPayload)74 public ChildSessionConfiguration( 75 List<IkeTrafficSelector> inTs, 76 List<IkeTrafficSelector> outTs, 77 IkeConfigPayload configPayload) { 78 this(inTs, outTs); 79 80 if (configPayload.configType != IkeConfigPayload.CONFIG_TYPE_REPLY) { 81 throw new IllegalArgumentException( 82 "Cannot build ChildSessionConfiguration with configuration type: " 83 + configPayload.configType); 84 } 85 86 // It is validated in IkeConfigPayload that a config reply only has at most one non-empty 87 // netmask and netmask exists only when IPv4 internal address exists. 88 ConfigAttributeIpv4Netmask netmaskAttr = null; 89 for (ConfigAttribute att : configPayload.recognizedAttributeList) { 90 if (att.attributeType == CONFIG_ATTR_INTERNAL_IP4_NETMASK && !att.isEmptyValue()) { 91 netmaskAttr = (ConfigAttributeIpv4Netmask) att; 92 } 93 } 94 95 for (ConfigAttribute att : configPayload.recognizedAttributeList) { 96 if (att.isEmptyValue()) continue; 97 switch (att.attributeType) { 98 case CONFIG_ATTR_INTERNAL_IP4_ADDRESS: 99 ConfigAttributeIpv4Address addressAttr = (ConfigAttributeIpv4Address) att; 100 if (netmaskAttr != null) { 101 mInternalAddressList.add( 102 new LinkAddress(addressAttr.address, netmaskAttr.getPrefixLen())); 103 } else { 104 mInternalAddressList.add( 105 new LinkAddress(addressAttr.address, IPv4_DEFAULT_PREFIX_LEN)); 106 } 107 break; 108 case CONFIG_ATTR_INTERNAL_IP4_NETMASK: 109 // No action. 110 break; 111 case CONFIG_ATTR_INTERNAL_IP6_ADDRESS: 112 mInternalAddressList.add(((ConfigAttributeIpv6Address) att).linkAddress); 113 break; 114 case CONFIG_ATTR_INTERNAL_IP4_DNS: 115 mInternalDnsAddressList.add(((ConfigAttributeIpv4Dns) att).address); 116 break; 117 case CONFIG_ATTR_INTERNAL_IP6_DNS: 118 mInternalDnsAddressList.add(((ConfigAttributeIpv6Dns) att).address); 119 break; 120 case CONFIG_ATTR_INTERNAL_IP4_SUBNET: 121 ConfigAttributeIpv4Subnet ipv4SubnetAttr = (ConfigAttributeIpv4Subnet) att; 122 mSubnetAddressList.add( 123 new IpPrefix( 124 ipv4SubnetAttr.linkAddress.getAddress(), 125 ipv4SubnetAttr.linkAddress.getPrefixLength())); 126 break; 127 case CONFIG_ATTR_INTERNAL_IP6_SUBNET: 128 ConfigAttributeIpv6Subnet ipV6SubnetAttr = (ConfigAttributeIpv6Subnet) att; 129 mSubnetAddressList.add( 130 new IpPrefix( 131 ipV6SubnetAttr.linkAddress.getAddress(), 132 ipV6SubnetAttr.linkAddress.getPrefixLength())); 133 break; 134 case CONFIG_ATTR_INTERNAL_IP4_DHCP: 135 mInternalDhcpAddressList.add(((ConfigAttributeIpv4Dhcp) att).address); 136 break; 137 default: 138 // Not relevant to child session 139 } 140 } 141 } 142 143 /** 144 * Construct an instance of {@link ChildSessionConfiguration}. 145 * 146 * @hide 147 */ ChildSessionConfiguration( List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs)148 public ChildSessionConfiguration( 149 List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs) { 150 mInboundTs.addAll(inTs); 151 mOutboundTs.addAll(outTs); 152 } 153 154 /** 155 * Construct an instance of {@link ChildSessionConfiguration}. 156 * 157 * @hide 158 */ ChildSessionConfiguration( List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs, List<LinkAddress> internalAddresses, List<IpPrefix> internalSubnets, List<InetAddress> internalDnsServers, List<InetAddress> internalDhcpServers)159 private ChildSessionConfiguration( 160 List<IkeTrafficSelector> inTs, 161 List<IkeTrafficSelector> outTs, 162 List<LinkAddress> internalAddresses, 163 List<IpPrefix> internalSubnets, 164 List<InetAddress> internalDnsServers, 165 List<InetAddress> internalDhcpServers) { 166 this(inTs, outTs); 167 mInternalAddressList.addAll(internalAddresses); 168 mSubnetAddressList.addAll(internalSubnets); 169 mInternalDnsAddressList.addAll(internalDnsServers); 170 mInternalDhcpAddressList.addAll(internalDhcpServers); 171 } 172 173 174 /** 175 * Returns the negotiated inbound traffic selectors. 176 * 177 * <p>Only inbound traffic within the range is acceptable to the Child Session. 178 * 179 * <p>The Android platform does not support port-based routing. Port ranges of traffic selectors 180 * are only informational. 181 * 182 * @return the inbound traffic selectors. 183 */ 184 @NonNull getInboundTrafficSelectors()185 public List<IkeTrafficSelector> getInboundTrafficSelectors() { 186 return mInboundTs; 187 } 188 189 /** 190 * Returns the negotiated outbound traffic selectors. 191 * 192 * <p>Only outbound traffic within the range is acceptable to the Child Session. 193 * 194 * <p>The Android platform does not support port-based routing. Port ranges of traffic selectors 195 * are only informational. 196 * 197 * @return the outbound traffic selectors. 198 */ 199 @NonNull getOutboundTrafficSelectors()200 public List<IkeTrafficSelector> getOutboundTrafficSelectors() { 201 return mOutboundTs; 202 } 203 204 /** 205 * Returns the assigned internal addresses. 206 * 207 * @return the assigned internal addresses, or an empty list when no addresses are assigned by 208 * the remote IKE server (e.g. for a non-tunnel mode Child Session). 209 * @hide 210 */ 211 @SystemApi 212 @NonNull getInternalAddresses()213 public List<LinkAddress> getInternalAddresses() { 214 return Collections.unmodifiableList(mInternalAddressList); 215 } 216 217 /** 218 * Returns the internal subnets protected by the IKE server. 219 * 220 * @return the internal subnets, or an empty list when no information of protected subnets is 221 * provided by the IKE server (e.g. for a non-tunnel mode Child Session). 222 * @hide 223 */ 224 @SystemApi 225 @NonNull getInternalSubnets()226 public List<IpPrefix> getInternalSubnets() { 227 return Collections.unmodifiableList(mSubnetAddressList); 228 } 229 230 /** 231 * Returns the internal DNS server addresses. 232 * 233 * @return the internal DNS server addresses, or an empty list when no DNS server is provided by 234 * the IKE server (e.g. for a non-tunnel mode Child Session). 235 * @hide 236 */ 237 @SystemApi 238 @NonNull getInternalDnsServers()239 public List<InetAddress> getInternalDnsServers() { 240 return Collections.unmodifiableList(mInternalDnsAddressList); 241 } 242 243 /** 244 * Returns the internal DHCP server addresses. 245 * 246 * @return the internal DHCP server addresses, or an empty list when no DHCP server is provided 247 * by the IKE server (e.g. for a non-tunnel mode Child Session). 248 * @hide 249 */ 250 @SystemApi 251 @NonNull getInternalDhcpServers()252 public List<InetAddress> getInternalDhcpServers() { 253 return Collections.unmodifiableList(mInternalDhcpAddressList); 254 } 255 256 /** 257 * This class can be used to incrementally construct a {@link ChildSessionConfiguration}. 258 * 259 * <p>Except for testing, IKE library users normally do not instantiate {@link 260 * ChildSessionConfiguration} themselves but instead get a reference via {@link 261 * ChildSessionCallback} 262 */ 263 public static final class Builder { 264 private final List<IkeTrafficSelector> mInboundTs = new ArrayList<>(); 265 private final List<IkeTrafficSelector> mOutboundTs = new ArrayList<>(); 266 private final List<LinkAddress> mInternalAddressList = new ArrayList<>(); 267 private final List<IpPrefix> mSubnetAddressList = new ArrayList<>(); 268 private final List<InetAddress> mInternalDnsAddressList = new ArrayList<>(); 269 private final List<InetAddress> mInternalDhcpAddressList = new ArrayList<>(); 270 271 /** 272 * Constructs a Builder. 273 * 274 * @param inTs the negotiated inbound traffic selectors 275 * @param outTs the negotiated outbound traffic selectors 276 */ Builder( @onNull List<IkeTrafficSelector> inTs, @NonNull List<IkeTrafficSelector> outTs)277 public Builder( 278 @NonNull List<IkeTrafficSelector> inTs, @NonNull List<IkeTrafficSelector> outTs) { 279 Objects.requireNonNull(inTs, "inTs was null"); 280 Objects.requireNonNull(outTs, "outTs was null"); 281 if (inTs.isEmpty() || outTs.isEmpty()) { 282 throw new IllegalArgumentException("inTs or outTs is empty."); 283 } 284 mInboundTs.addAll(inTs); 285 mOutboundTs.addAll(outTs); 286 } 287 288 /** 289 * Adds an assigned internal address for the {@link ChildSessionConfiguration} being built. 290 * 291 * @param address an assigned internal addresses 292 * @return Builder this, to facilitate chaining 293 * @hide 294 */ 295 @SystemApi 296 @NonNull addInternalAddress(@onNull LinkAddress address)297 public Builder addInternalAddress(@NonNull LinkAddress address) { 298 Objects.requireNonNull(address, "address was null"); 299 mInternalAddressList.add(address); 300 return this; 301 } 302 303 /** 304 * Clears all assigned internal addresses from the {@link ChildSessionConfiguration} being 305 * built. 306 * 307 * @return Builder this, to facilitate chaining 308 * @hide 309 */ 310 @SystemApi 311 @NonNull clearInternalAddresses()312 public Builder clearInternalAddresses() { 313 mInternalAddressList.clear(); 314 return this; 315 } 316 317 /** 318 * Adds an assigned internal subnet for the {@link ChildSessionConfiguration} being built. 319 * 320 * @param subnet an assigned internal subnet 321 * @return Builder this, to facilitate chaining 322 * @hide 323 */ 324 @SystemApi 325 @NonNull addInternalSubnet(@onNull IpPrefix subnet)326 public Builder addInternalSubnet(@NonNull IpPrefix subnet) { 327 Objects.requireNonNull(subnet, "subnet was null"); 328 mSubnetAddressList.add(subnet); 329 return this; 330 } 331 332 /** 333 * Clears all assigned internal subnets from the {@link ChildSessionConfiguration} being 334 * built. 335 * 336 * @return Builder this, to facilitate chaining 337 * @hide 338 */ 339 @SystemApi 340 @NonNull clearInternalSubnets()341 public Builder clearInternalSubnets() { 342 mSubnetAddressList.clear(); 343 return this; 344 } 345 346 /** 347 * Adds an assigned internal DNS server for the {@link ChildSessionConfiguration} being 348 * built. 349 * 350 * @param dnsServer an assigned internal DNS server 351 * @return Builder this, to facilitate chaining 352 * @hide 353 */ 354 @SystemApi 355 @NonNull addInternalDnsServer(@onNull InetAddress dnsServer)356 public Builder addInternalDnsServer(@NonNull InetAddress dnsServer) { 357 Objects.requireNonNull(dnsServer, "dnsServer was null"); 358 mInternalDnsAddressList.add(dnsServer); 359 return this; 360 } 361 362 /** 363 * Clears all assigned internal DNS servers from the {@link ChildSessionConfiguration} being 364 * built. 365 * 366 * @return Builder this, to facilitate chaining 367 * @hide 368 */ 369 @SystemApi 370 @NonNull clearInternalDnsServers()371 public Builder clearInternalDnsServers() { 372 mInternalDnsAddressList.clear(); 373 return this; 374 } 375 376 /** 377 * Adds an assigned internal DHCP server for the {@link ChildSessionConfiguration} being 378 * built. 379 * 380 * @param dhcpServer an assigned internal DHCP server 381 * @return Builder this, to facilitate chaining 382 * @hide 383 */ 384 @SystemApi 385 @NonNull addInternalDhcpServer(@onNull InetAddress dhcpServer)386 public Builder addInternalDhcpServer(@NonNull InetAddress dhcpServer) { 387 Objects.requireNonNull(dhcpServer, "dhcpServer was null"); 388 mInternalDhcpAddressList.add(dhcpServer); 389 return this; 390 } 391 392 /** 393 * Clears all assigned internal DHCP servers for the {@link ChildSessionConfiguration} being 394 * built. 395 * 396 * @return Builder this, to facilitate chaining 397 * @hide 398 */ 399 @SystemApi 400 @NonNull clearInternalDhcpServers()401 public Builder clearInternalDhcpServers() { 402 mInternalDhcpAddressList.clear(); 403 return this; 404 } 405 406 /** Constructs an {@link ChildSessionConfiguration} instance. */ 407 @NonNull build()408 public ChildSessionConfiguration build() { 409 return new ChildSessionConfiguration( 410 mInboundTs, 411 mOutboundTs, 412 mInternalAddressList, 413 mSubnetAddressList, 414 mInternalDnsAddressList, 415 mInternalDhcpAddressList); 416 } 417 } 418 } 419