1 /* 2 * Copyright (C) 2020 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 com.android.server.connectivity; 18 19 import static android.net.ConnectivityManager.NetworkCallback; 20 import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP; 21 import static android.net.ipsec.ike.SaProposal.DH_GROUP_3072_BIT_MODP; 22 import static android.net.ipsec.ike.SaProposal.DH_GROUP_4096_BIT_MODP; 23 import static android.net.ipsec.ike.SaProposal.DH_GROUP_CURVE_25519; 24 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC; 25 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CTR; 26 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12; 27 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16; 28 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8; 29 import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305; 30 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_CMAC_96; 31 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96; 32 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128; 33 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192; 34 import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256; 35 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128; 36 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_192; 37 import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256; 38 import static android.net.ipsec.ike.SaProposal.KEY_LEN_UNUSED; 39 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_CMAC; 40 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC; 41 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1; 42 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_256; 43 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_384; 44 import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_SHA2_512; 45 46 import android.annotation.NonNull; 47 import android.content.Context; 48 import android.net.Ikev2VpnProfile; 49 import android.net.InetAddresses; 50 import android.net.IpPrefix; 51 import android.net.IpSecAlgorithm; 52 import android.net.IpSecTransform; 53 import android.net.Network; 54 import android.net.RouteInfo; 55 import android.net.eap.EapSessionConfig; 56 import android.net.ipsec.ike.ChildSaProposal; 57 import android.net.ipsec.ike.ChildSessionCallback; 58 import android.net.ipsec.ike.ChildSessionConfiguration; 59 import android.net.ipsec.ike.ChildSessionParams; 60 import android.net.ipsec.ike.IkeFqdnIdentification; 61 import android.net.ipsec.ike.IkeIdentification; 62 import android.net.ipsec.ike.IkeIpv4AddrIdentification; 63 import android.net.ipsec.ike.IkeIpv6AddrIdentification; 64 import android.net.ipsec.ike.IkeKeyIdIdentification; 65 import android.net.ipsec.ike.IkeRfc822AddrIdentification; 66 import android.net.ipsec.ike.IkeSaProposal; 67 import android.net.ipsec.ike.IkeSessionCallback; 68 import android.net.ipsec.ike.IkeSessionConfiguration; 69 import android.net.ipsec.ike.IkeSessionParams; 70 import android.net.ipsec.ike.IkeTrafficSelector; 71 import android.net.ipsec.ike.TunnelModeChildSessionParams; 72 import android.net.ipsec.ike.exceptions.IkeException; 73 import android.net.ipsec.ike.exceptions.IkeProtocolException; 74 import android.system.OsConstants; 75 import android.util.Log; 76 77 import com.android.internal.net.VpnProfile; 78 import com.android.internal.util.HexDump; 79 import com.android.net.module.util.IpRange; 80 81 import java.net.Inet4Address; 82 import java.net.Inet6Address; 83 import java.net.InetAddress; 84 import java.util.ArrayList; 85 import java.util.Arrays; 86 import java.util.Collection; 87 import java.util.HashSet; 88 import java.util.List; 89 90 /** 91 * Utility class to build and convert IKEv2/IPsec parameters. 92 * 93 * @hide 94 */ 95 public class VpnIkev2Utils { 96 private static final String TAG = VpnIkev2Utils.class.getSimpleName(); 97 buildIkeSessionParams( @onNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network)98 static IkeSessionParams buildIkeSessionParams( 99 @NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) { 100 final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity()); 101 final IkeIdentification remoteId = parseIkeIdentification(profile.getServerAddr()); 102 103 final IkeSessionParams.Builder ikeOptionsBuilder = 104 new IkeSessionParams.Builder(context) 105 .setServerHostname(profile.getServerAddr()) 106 .setNetwork(network) 107 .setLocalIdentification(localId) 108 .setRemoteIdentification(remoteId); 109 setIkeAuth(profile, ikeOptionsBuilder); 110 111 for (final IkeSaProposal ikeProposal : getIkeSaProposals()) { 112 ikeOptionsBuilder.addSaProposal(ikeProposal); 113 } 114 115 return ikeOptionsBuilder.build(); 116 } 117 buildChildSessionParams(List<String> allowedAlgorithms)118 static ChildSessionParams buildChildSessionParams(List<String> allowedAlgorithms) { 119 final TunnelModeChildSessionParams.Builder childOptionsBuilder = 120 new TunnelModeChildSessionParams.Builder(); 121 122 for (final ChildSaProposal childProposal : getChildSaProposals(allowedAlgorithms)) { 123 childOptionsBuilder.addSaProposal(childProposal); 124 } 125 126 childOptionsBuilder.addInternalAddressRequest(OsConstants.AF_INET); 127 childOptionsBuilder.addInternalAddressRequest(OsConstants.AF_INET6); 128 childOptionsBuilder.addInternalDnsServerRequest(OsConstants.AF_INET); 129 childOptionsBuilder.addInternalDnsServerRequest(OsConstants.AF_INET6); 130 131 return childOptionsBuilder.build(); 132 } 133 setIkeAuth( @onNull Ikev2VpnProfile profile, @NonNull IkeSessionParams.Builder builder)134 private static void setIkeAuth( 135 @NonNull Ikev2VpnProfile profile, @NonNull IkeSessionParams.Builder builder) { 136 switch (profile.getType()) { 137 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: 138 final EapSessionConfig eapConfig = 139 new EapSessionConfig.Builder() 140 .setEapMsChapV2Config(profile.getUsername(), profile.getPassword()) 141 .build(); 142 builder.setAuthEap(profile.getServerRootCaCert(), eapConfig); 143 break; 144 case VpnProfile.TYPE_IKEV2_IPSEC_PSK: 145 builder.setAuthPsk(profile.getPresharedKey()); 146 break; 147 case VpnProfile.TYPE_IKEV2_IPSEC_RSA: 148 builder.setAuthDigitalSignature( 149 profile.getServerRootCaCert(), 150 profile.getUserCert(), 151 profile.getRsaPrivateKey()); 152 break; 153 default: 154 throw new IllegalArgumentException("Unknown auth method set"); 155 } 156 } 157 getIkeSaProposals()158 private static List<IkeSaProposal> getIkeSaProposals() { 159 // TODO: Add ability to filter this when IKEv2 API is made Public API 160 final List<IkeSaProposal> proposals = new ArrayList<>(); 161 162 final IkeSaProposal.Builder normalModeBuilder = new IkeSaProposal.Builder(); 163 164 // Add normal mode encryption algorithms 165 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_256); 166 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256); 167 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_192); 168 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192); 169 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, KEY_LEN_AES_128); 170 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128); 171 172 // Authentication/Integrity Algorithms 173 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); 174 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); 175 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); 176 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96); 177 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_CMAC_96); 178 179 // Add AEAD options 180 final IkeSaProposal.Builder aeadBuilder = new IkeSaProposal.Builder(); 181 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, KEY_LEN_UNUSED); 182 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256); 183 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256); 184 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256); 185 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192); 186 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192); 187 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192); 188 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128); 189 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128); 190 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128); 191 192 // Add dh, prf for both builders 193 for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) { 194 builder.addDhGroup(DH_GROUP_4096_BIT_MODP); 195 196 // Curve25519 has the same security strength as MODP 3072 and cost less bytes 197 builder.addDhGroup(DH_GROUP_CURVE_25519); 198 199 builder.addDhGroup(DH_GROUP_3072_BIT_MODP); 200 builder.addDhGroup(DH_GROUP_2048_BIT_MODP); 201 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_512); 202 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_384); 203 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_SHA2_256); 204 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC); 205 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_CMAC); 206 builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1); 207 } 208 209 proposals.add(normalModeBuilder.build()); 210 proposals.add(aeadBuilder.build()); 211 return proposals; 212 } 213 214 /** Builds a child SA proposal based on the allowed IPsec algorithms */ getChildSaProposals(List<String> allowedAlgorithms)215 private static List<ChildSaProposal> getChildSaProposals(List<String> allowedAlgorithms) { 216 final List<ChildSaProposal> proposals = new ArrayList<>(); 217 218 final List<Integer> aesKeyLenOptions = 219 Arrays.asList(KEY_LEN_AES_256, KEY_LEN_AES_192, KEY_LEN_AES_128); 220 221 // Add non-AEAD options 222 if (Ikev2VpnProfile.hasNormalModeAlgorithms(allowedAlgorithms)) { 223 final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder(); 224 225 // Encryption Algorithms: 226 // AES-CBC and AES_CTR are currently the only supported encryption algorithms. 227 for (int len : aesKeyLenOptions) { 228 if (allowedAlgorithms.contains(IpSecAlgorithm.CRYPT_AES_CTR)) { 229 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CTR, len); 230 } 231 if (allowedAlgorithms.contains(IpSecAlgorithm.CRYPT_AES_CBC)) { 232 normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, len); 233 } 234 } 235 236 // Authentication/Integrity Algorithms: 237 // Guaranteed by Ikev2VpnProfile constructor to contain at least one of these. 238 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA512)) { 239 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256); 240 } 241 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA384)) { 242 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192); 243 } 244 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_HMAC_SHA256)) { 245 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128); 246 } 247 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_AES_XCBC)) { 248 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96); 249 } 250 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_AES_CMAC)) { 251 normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_CMAC_96); 252 } 253 254 ChildSaProposal proposal = normalModeBuilder.build(); 255 if (proposal.getIntegrityAlgorithms().isEmpty()) { 256 // Should be impossible; Verified in Ikev2VpnProfile. 257 Log.wtf(TAG, "Missing integrity algorithm when buildling Child SA proposal"); 258 } else { 259 proposals.add(normalModeBuilder.build()); 260 } 261 } 262 263 // Add AEAD options 264 if (Ikev2VpnProfile.hasAeadAlgorithms(allowedAlgorithms)) { 265 final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder(); 266 267 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_CRYPT_CHACHA20_POLY1305)) { 268 aeadBuilder.addEncryptionAlgorithm( 269 ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, KEY_LEN_UNUSED); 270 } 271 if (allowedAlgorithms.contains(IpSecAlgorithm.AUTH_CRYPT_AES_GCM)) { 272 aeadBuilder.addEncryptionAlgorithm( 273 ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256); 274 aeadBuilder.addEncryptionAlgorithm( 275 ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256); 276 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256); 277 aeadBuilder.addEncryptionAlgorithm( 278 ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192); 279 aeadBuilder.addEncryptionAlgorithm( 280 ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192); 281 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192); 282 aeadBuilder.addEncryptionAlgorithm( 283 ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128); 284 aeadBuilder.addEncryptionAlgorithm( 285 ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128); 286 aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128); 287 } 288 289 proposals.add(aeadBuilder.build()); 290 } 291 292 return proposals; 293 } 294 295 static class IkeSessionCallbackImpl implements IkeSessionCallback { 296 private final String mTag; 297 private final Vpn.IkeV2VpnRunnerCallback mCallback; 298 private final Network mNetwork; 299 IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network)300 IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) { 301 mTag = tag; 302 mCallback = callback; 303 mNetwork = network; 304 } 305 306 @Override onOpened(@onNull IkeSessionConfiguration ikeSessionConfig)307 public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) { 308 Log.d(mTag, "IkeOpened for network " + mNetwork); 309 // Nothing to do here. 310 } 311 312 @Override onClosed()313 public void onClosed() { 314 Log.d(mTag, "IkeClosed for network " + mNetwork); 315 mCallback.onSessionLost(mNetwork, null); // Server requested session closure. Retry? 316 } 317 318 @Override onClosedExceptionally(@onNull IkeException exception)319 public void onClosedExceptionally(@NonNull IkeException exception) { 320 Log.d(mTag, "IkeClosedExceptionally for network " + mNetwork, exception); 321 mCallback.onSessionLost(mNetwork, exception); 322 } 323 324 @Override onError(@onNull IkeProtocolException exception)325 public void onError(@NonNull IkeProtocolException exception) { 326 Log.d(mTag, "IkeError for network " + mNetwork, exception); 327 // Non-fatal, log and continue. 328 } 329 } 330 331 static class ChildSessionCallbackImpl implements ChildSessionCallback { 332 private final String mTag; 333 private final Vpn.IkeV2VpnRunnerCallback mCallback; 334 private final Network mNetwork; 335 ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network)336 ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) { 337 mTag = tag; 338 mCallback = callback; 339 mNetwork = network; 340 } 341 342 @Override onOpened(@onNull ChildSessionConfiguration childConfig)343 public void onOpened(@NonNull ChildSessionConfiguration childConfig) { 344 Log.d(mTag, "ChildOpened for network " + mNetwork); 345 mCallback.onChildOpened(mNetwork, childConfig); 346 } 347 348 @Override onClosed()349 public void onClosed() { 350 Log.d(mTag, "ChildClosed for network " + mNetwork); 351 mCallback.onSessionLost(mNetwork, null); 352 } 353 354 @Override onClosedExceptionally(@onNull IkeException exception)355 public void onClosedExceptionally(@NonNull IkeException exception) { 356 Log.d(mTag, "ChildClosedExceptionally for network " + mNetwork, exception); 357 mCallback.onSessionLost(mNetwork, exception); 358 } 359 360 @Override onIpSecTransformCreated(@onNull IpSecTransform transform, int direction)361 public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) { 362 Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; network " + mNetwork); 363 mCallback.onChildTransformCreated(mNetwork, transform, direction); 364 } 365 366 @Override onIpSecTransformDeleted(@onNull IpSecTransform transform, int direction)367 public void onIpSecTransformDeleted(@NonNull IpSecTransform transform, int direction) { 368 // Nothing to be done; no references to the IpSecTransform are held by the 369 // Ikev2VpnRunner (or this callback class), and this transform will be closed by the 370 // IKE library. 371 Log.d(mTag, 372 "ChildTransformDeleted; Direction: " + direction + "; for network " + mNetwork); 373 } 374 } 375 376 static class Ikev2VpnNetworkCallback extends NetworkCallback { 377 private final String mTag; 378 private final Vpn.IkeV2VpnRunnerCallback mCallback; 379 Ikev2VpnNetworkCallback(String tag, Vpn.IkeV2VpnRunnerCallback callback)380 Ikev2VpnNetworkCallback(String tag, Vpn.IkeV2VpnRunnerCallback callback) { 381 mTag = tag; 382 mCallback = callback; 383 } 384 385 @Override onAvailable(@onNull Network network)386 public void onAvailable(@NonNull Network network) { 387 Log.d(mTag, "Starting IKEv2/IPsec session on new network: " + network); 388 mCallback.onDefaultNetworkChanged(network); 389 } 390 391 @Override onLost(@onNull Network network)392 public void onLost(@NonNull Network network) { 393 Log.d(mTag, "Tearing down; lost network: " + network); 394 mCallback.onSessionLost(network, null); 395 } 396 } 397 398 /** 399 * Identity parsing logic using similar logic to open source implementations of IKEv2 400 * 401 * <p>This method does NOT support using type-prefixes (eg 'fqdn:' or 'keyid'), or ASN.1 encoded 402 * identities. 403 */ parseIkeIdentification(@onNull String identityStr)404 private static IkeIdentification parseIkeIdentification(@NonNull String identityStr) { 405 // TODO: Add identity formatting to public API javadocs. 406 if (identityStr.contains("@")) { 407 if (identityStr.startsWith("@#")) { 408 // KEY_ID 409 final String hexStr = identityStr.substring(2); 410 return new IkeKeyIdIdentification(HexDump.hexStringToByteArray(hexStr)); 411 } else if (identityStr.startsWith("@@")) { 412 // RFC822 (USER_FQDN) 413 return new IkeRfc822AddrIdentification(identityStr.substring(2)); 414 } else if (identityStr.startsWith("@")) { 415 // FQDN 416 return new IkeFqdnIdentification(identityStr.substring(1)); 417 } else { 418 // RFC822 (USER_FQDN) 419 return new IkeRfc822AddrIdentification(identityStr); 420 } 421 } else if (InetAddresses.isNumericAddress(identityStr)) { 422 final InetAddress addr = InetAddresses.parseNumericAddress(identityStr); 423 if (addr instanceof Inet4Address) { 424 // IPv4 425 return new IkeIpv4AddrIdentification((Inet4Address) addr); 426 } else if (addr instanceof Inet6Address) { 427 // IPv6 428 return new IkeIpv6AddrIdentification((Inet6Address) addr); 429 } else { 430 throw new IllegalArgumentException("IP version not supported"); 431 } 432 } else { 433 if (identityStr.contains(":")) { 434 // KEY_ID 435 return new IkeKeyIdIdentification(identityStr.getBytes()); 436 } else { 437 // FQDN 438 return new IkeFqdnIdentification(identityStr); 439 } 440 } 441 } 442 getRoutesFromTrafficSelectors( List<IkeTrafficSelector> trafficSelectors)443 static Collection<RouteInfo> getRoutesFromTrafficSelectors( 444 List<IkeTrafficSelector> trafficSelectors) { 445 final HashSet<RouteInfo> routes = new HashSet<>(); 446 447 for (final IkeTrafficSelector selector : trafficSelectors) { 448 for (final IpPrefix prefix : 449 new IpRange(selector.startingAddress, selector.endingAddress).asIpPrefixes()) { 450 routes.add(new RouteInfo(prefix, null /*gateway*/, null /*iface*/, 451 RouteInfo.RTN_UNICAST)); 452 } 453 } 454 455 return routes; 456 } 457 } 458