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.Collections;
46 import java.util.LinkedList;
47 import java.util.List;
48 
49 /**
50  * ChildSessionConfiguration represents the negotiated configuration for a Child Session.
51  *
52  * <p>Configurations include traffic selectors and internal network information.
53  *
54  * @hide
55  */
56 @SystemApi
57 public final class ChildSessionConfiguration {
58     private static final int IPv4_DEFAULT_PREFIX_LEN = 32;
59 
60     private final List<IkeTrafficSelector> mInboundTs;
61     private final List<IkeTrafficSelector> mOutboundTs;
62     private final List<LinkAddress> mInternalAddressList;
63     private final List<InetAddress> mInternalDnsAddressList;
64     private final List<IpPrefix> mSubnetAddressList;
65     private final List<InetAddress> mInternalDhcpAddressList;
66 
67     /**
68      * Construct an instance of {@link ChildSessionConfiguration}.
69      *
70      * <p>It is only supported to build a {@link ChildSessionConfiguration} with a Configure(Reply)
71      * Payload.
72      *
73      * @hide
74      */
ChildSessionConfiguration( List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs, IkeConfigPayload configPayload)75     public ChildSessionConfiguration(
76             List<IkeTrafficSelector> inTs,
77             List<IkeTrafficSelector> outTs,
78             IkeConfigPayload configPayload) {
79         this(inTs, outTs);
80 
81         if (configPayload.configType != IkeConfigPayload.CONFIG_TYPE_REPLY) {
82             throw new IllegalArgumentException(
83                     "Cannot build ChildSessionConfiguration with configuration type: "
84                             + configPayload.configType);
85         }
86 
87         // It is validated in IkeConfigPayload that a config reply only has at most one non-empty
88         // netmask and netmask exists only when IPv4 internal address exists.
89         ConfigAttributeIpv4Netmask netmaskAttr = null;
90         for (ConfigAttribute att : configPayload.recognizedAttributeList) {
91             if (att.attributeType == CONFIG_ATTR_INTERNAL_IP4_NETMASK && !att.isEmptyValue()) {
92                 netmaskAttr = (ConfigAttributeIpv4Netmask) att;
93             }
94         }
95 
96         for (ConfigAttribute att : configPayload.recognizedAttributeList) {
97             if (att.isEmptyValue()) continue;
98             switch (att.attributeType) {
99                 case CONFIG_ATTR_INTERNAL_IP4_ADDRESS:
100                     ConfigAttributeIpv4Address addressAttr = (ConfigAttributeIpv4Address) att;
101                     if (netmaskAttr != null) {
102                         mInternalAddressList.add(
103                                 new LinkAddress(addressAttr.address, netmaskAttr.getPrefixLen()));
104                     } else {
105                         mInternalAddressList.add(
106                                 new LinkAddress(addressAttr.address, IPv4_DEFAULT_PREFIX_LEN));
107                     }
108                     break;
109                 case CONFIG_ATTR_INTERNAL_IP4_NETMASK:
110                     // No action.
111                     break;
112                 case CONFIG_ATTR_INTERNAL_IP6_ADDRESS:
113                     mInternalAddressList.add(((ConfigAttributeIpv6Address) att).linkAddress);
114                     break;
115                 case CONFIG_ATTR_INTERNAL_IP4_DNS:
116                     mInternalDnsAddressList.add(((ConfigAttributeIpv4Dns) att).address);
117                     break;
118                 case CONFIG_ATTR_INTERNAL_IP6_DNS:
119                     mInternalDnsAddressList.add(((ConfigAttributeIpv6Dns) att).address);
120                     break;
121                 case CONFIG_ATTR_INTERNAL_IP4_SUBNET:
122                     ConfigAttributeIpv4Subnet ipv4SubnetAttr = (ConfigAttributeIpv4Subnet) att;
123                     mSubnetAddressList.add(
124                             new IpPrefix(
125                                     ipv4SubnetAttr.linkAddress.getAddress(),
126                                     ipv4SubnetAttr.linkAddress.getPrefixLength()));
127                     break;
128                 case CONFIG_ATTR_INTERNAL_IP6_SUBNET:
129                     ConfigAttributeIpv6Subnet ipV6SubnetAttr = (ConfigAttributeIpv6Subnet) att;
130                     mSubnetAddressList.add(
131                             new IpPrefix(
132                                     ipV6SubnetAttr.linkAddress.getAddress(),
133                                     ipV6SubnetAttr.linkAddress.getPrefixLength()));
134                     break;
135                 case CONFIG_ATTR_INTERNAL_IP4_DHCP:
136                     mInternalDhcpAddressList.add(((ConfigAttributeIpv4Dhcp) att).address);
137                     break;
138                 default:
139                     // Not relevant to child session
140             }
141         }
142     }
143 
144     /**
145      * Construct an instance of {@link ChildSessionConfiguration}.
146      *
147      * @hide
148      */
ChildSessionConfiguration( List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs)149     public ChildSessionConfiguration(
150             List<IkeTrafficSelector> inTs, List<IkeTrafficSelector> outTs) {
151         mInboundTs = Collections.unmodifiableList(inTs);
152         mOutboundTs = Collections.unmodifiableList(outTs);
153         mInternalAddressList = new LinkedList<>();
154         mInternalDnsAddressList = new LinkedList<>();
155         mSubnetAddressList = new LinkedList<>();
156         mInternalDhcpAddressList = new LinkedList<>();
157     }
158 
159     /**
160      * Returns the negotiated inbound traffic selectors.
161      *
162      * <p>Only inbound traffic within the range is acceptable to the Child Session.
163      *
164      * <p>The Android platform does not support port-based routing. Port ranges of traffic selectors
165      * are only informational.
166      *
167      * @return the inbound traffic selectors.
168      */
169     @NonNull
getInboundTrafficSelectors()170     public List<IkeTrafficSelector> getInboundTrafficSelectors() {
171         return mInboundTs;
172     }
173 
174     /**
175      * Returns the negotiated outbound traffic selectors.
176      *
177      * <p>Only outbound 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 outbound traffic selectors.
183      */
184     @NonNull
getOutboundTrafficSelectors()185     public List<IkeTrafficSelector> getOutboundTrafficSelectors() {
186         return mOutboundTs;
187     }
188 
189     /**
190      * Returns the assigned internal addresses.
191      *
192      * @return the assigned internal addresses, or an empty list when no addresses are assigned by
193      *     the remote IKE server (e.g. for a non-tunnel mode Child Session).
194      */
195     @NonNull
getInternalAddresses()196     public List<LinkAddress> getInternalAddresses() {
197         return Collections.unmodifiableList(mInternalAddressList);
198     }
199 
200     /**
201      * Returns the internal subnets protected by the IKE server.
202      *
203      * @return the internal subnets, or an empty list when no information of protected subnets is
204      *     provided by the IKE server (e.g. for a non-tunnel mode Child Session).
205      */
206     @NonNull
getInternalSubnets()207     public List<IpPrefix> getInternalSubnets() {
208         return Collections.unmodifiableList(mSubnetAddressList);
209     }
210 
211     /**
212      * Returns the internal DNS server addresses.
213      *
214      * @return the internal DNS server addresses, or an empty list when no DNS server is provided by
215      *     the IKE server (e.g. for a non-tunnel mode Child Session).
216      */
217     @NonNull
getInternalDnsServers()218     public List<InetAddress> getInternalDnsServers() {
219         return Collections.unmodifiableList(mInternalDnsAddressList);
220     }
221 
222     /**
223      * Returns the internal DHCP server addresses.
224      *
225      * @return the internal DHCP server addresses, or an empty list when no DHCP server is provided
226      *     by the IKE server (e.g. for a non-tunnel mode Child Session).
227      */
228     @NonNull
getInternalDhcpServers()229     public List<InetAddress> getInternalDhcpServers() {
230         return Collections.unmodifiableList(mInternalDhcpAddressList);
231     }
232 }
233