1 /*
2 Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above
10       copyright notice, this list of conditions and the following
11       disclaimer in the documentation and/or other materials provided
12       with the distribution.
13     * Neither the name of The Linux Foundation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*!
30 	@file
31 	IPACM_Config.h
32 
33 	@brief
34 	This file implements the IPACM Configuration from XML file
35 
36 	@Author
37 	Skylar Chang
38 
39 */
40 #ifndef IPACM_CONFIG_H
41 #define IPACM_CONFIG_H
42 
43 #include "IPACM_Defs.h"
44 #include "IPACM_Xml.h"
45 #include "IPACM_EvtDispatcher.h"
46 
47 typedef struct
48 {
49   char iface_name[IPA_IFACE_NAME_LEN];
50   bool v4_up;
51   bool v6_up;
52 }NatIfaces;
53 
54 /* for IPACM rm dependency use*/
55 typedef struct _ipa_rm_client
56 {
57     ipa_rm_resource_name producer_rm1;
58     ipa_rm_resource_name consumer_rm1;
59     ipa_rm_resource_name producer_rm2;
60     ipa_rm_resource_name consumer_rm2;
61     bool producer1_up;            /* only monitor producer_rm1, not monitor producer_rm2 */
62     bool consumer1_up;            /* only monitor consumer_rm1, not monitor consumer_rm2 */
63     bool rm_set;                  /* once producer1_up and consumer1_up, will add bi-directional dependency */
64     bool rx_bypass_ipa;          /* support WLAN may not register RX-property, should not add dependency */
65 }ipa_rm_client;
66 
67 #define MAX_NUM_EXT_PROPS 25
68 
69 /* used to hold extended properties */
70 typedef struct
71 {
72 	uint8_t num_ext_props;
73 	ipa_ioc_ext_intf_prop prop[MAX_NUM_EXT_PROPS];
74 } ipacm_ext_prop;
75 
76 /* iface */
77 class IPACM_Config
78 {
79 public:
80 
81 	/* IPACM ipa_client map to rm_resource*/
82 	ipa_rm_resource_name ipa_client_rm_map_tbl[IPA_CLIENT_MAX];
83 
84 	/* IPACM monitored rm_depency table */
85 	ipa_rm_client ipa_rm_tbl[IPA_MAX_RM_ENTRY];
86 
87 	/* IPACM rm_depency a2 endpoint check*/
88 	int ipa_rm_a2_check;
89 
90 	/* Store interested interface and their configuration from XML file */
91 	ipa_ifi_dev_name_t *iface_table;
92 
93 	/* Store interested ALG port from XML file */
94 	ipacm_alg *alg_table;
95 
96 	/* Store private subnet configuration from XML file */
97 	ipa_private_subnet private_subnet_table[IPA_MAX_PRIVATE_SUBNET_ENTRIES];
98 
99 	/* Store the non nat iface names */
100 	NatIfaces *pNatIfaces;
101 
102 	/* Store the bridge iface names */
103 	char ipa_virtual_iface_name[IPA_IFACE_NAME_LEN];
104 
105 	/* Store the number of interface IPACM read from XML file */
106 	int ipa_num_ipa_interfaces;
107 
108 	int ipa_num_private_subnet;
109 
110 	int ipa_num_alg_ports;
111 
112 	int ipa_nat_max_entries;
113 
114 	bool ipacm_odu_router_mode;
115 
116 	bool ipacm_odu_enable;
117 
118 	bool ipacm_odu_embms_enable;
119 
120 	bool ipacm_ip_passthrough_mode;
121 
122 	int ipa_nat_iface_entries;
123 
124 	/* Store the total number of wlan guest ap configured */
125 	int ipa_num_wlan_guest_ap;
126 
127 	/* Max valid rm entry */
128 	int ipa_max_valid_rm_entry;
129 
130 	/* Store SW-enable or not */
131 	bool ipa_sw_rt_enable;
132 
133 	/* Store bridge mode or not */
134 	bool ipa_bridge_enable;
135 
136 	/* Store bridge netdev mac */
137 	uint8_t bridge_mac[IPA_MAC_ADDR_SIZE];
138 
139 	/* Store the flt rule count for each producer client*/
140 	int flt_rule_count_v4[IPA_CLIENT_MAX];
141 	int flt_rule_count_v6[IPA_CLIENT_MAX];
142 
143 	/* IPACM routing table name for v4/v6 */
144 	struct ipa_ioc_get_rt_tbl rt_tbl_lan_v4, rt_tbl_wan_v4, rt_tbl_default_v4, rt_tbl_v6, rt_tbl_wan_v6;
145 	struct ipa_ioc_get_rt_tbl rt_tbl_wan_dl;
146 	struct ipa_ioc_get_rt_tbl rt_tbl_odu_v4, rt_tbl_odu_v6;
147 
148 	bool isMCC_Mode;
149 
150 	/* To return the instance */
151 	static IPACM_Config* GetInstance();
152 
153 	const char* getEventName(ipa_cm_event_id event_id);
154 
increaseFltRuleCount(int index,ipa_ip_type iptype,int increment)155 	inline void increaseFltRuleCount(int index, ipa_ip_type iptype, int increment)
156 	{
157 		if((index >= IPA_CLIENT_MAX) || (index < 0))
158 		{
159 			IPACMERR("Index is out of range: %d.\n", index);
160 			return;
161 		}
162 		if(iptype == IPA_IP_v4)
163 		{
164 			flt_rule_count_v4[index] += increment;
165 			IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]);
166 		}
167 		else
168 		{
169 			flt_rule_count_v6[index] += increment;
170 			IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]);
171 		}
172 		return;
173 	}
174 
decreaseFltRuleCount(int index,ipa_ip_type iptype,int decrement)175 	inline void decreaseFltRuleCount(int index, ipa_ip_type iptype, int decrement)
176 	{
177 		if((index >= IPA_CLIENT_MAX) || (index < 0))
178 		{
179 			IPACMERR("Index is out of range: %d.\n", index);
180 			return;
181 		}
182 		if(iptype == IPA_IP_v4)
183 		{
184 			flt_rule_count_v4[index] -= decrement;
185 			IPACMDBG_H("Now num of v4 flt rules on client %d is %d.\n", index, flt_rule_count_v4[index]);
186 		}
187 		else
188 		{
189 			flt_rule_count_v6[index] -= decrement;
190 			IPACMDBG_H("Now num of v6 flt rules on client %d is %d.\n", index, flt_rule_count_v6[index]);
191 		}
192 		return;
193 	}
194 
getFltRuleCount(int index,ipa_ip_type iptype)195 	inline int getFltRuleCount(int index, ipa_ip_type iptype)
196 	{
197 		if((index >= IPA_CLIENT_MAX) || (index < 0))
198 		{
199 			IPACMERR("Index is out of range: %d.\n", index);
200 			return -1;
201 		}
202 		if(iptype == IPA_IP_v4)
203 		{
204 			return flt_rule_count_v4[index];
205 		}
206 		else
207 		{
208 			return flt_rule_count_v6[index];
209 		}
210 	}
211 
GetAlgPortCnt()212 	inline int GetAlgPortCnt()
213 	{
214 		return ipa_num_alg_ports;
215 	}
216 
217 	int GetAlgPorts(int nPorts, ipacm_alg *pAlgPorts);
218 
GetNatMaxEntries(void)219 	inline int GetNatMaxEntries(void)
220 	{
221 		return ipa_nat_max_entries;
222 	}
223 
GetNatIfacesCnt()224 	inline int GetNatIfacesCnt()
225 	{
226 		return ipa_nat_iface_entries;
227 	}
228 	int GetNatIfaces(int nPorts, NatIfaces *ifaces);
229 
230 	/* for IPACM resource manager dependency usage */
231 	void AddRmDepend(ipa_rm_resource_name rm1,bool rx_bypass_ipa);
232 
233 	void DelRmDepend(ipa_rm_resource_name rm1);
234 
235 	int AddNatIfaces(char *dev_name, ipa_ip_type ip_type);
236 
237 	int DelNatIfaces(char *dev_name);
238 
239 	int CheckNatIfaces(const char *dev_name, ipa_ip_type ip_type);
240 
SetQmapId(uint8_t id)241 	inline void SetQmapId(uint8_t id)
242 	{
243 		qmap_id = id;
244 	}
245 
GetQmapId()246 	inline uint8_t GetQmapId()
247 	{
248 		return qmap_id;
249 	}
250 
251 	int SetExtProp(ipa_ioc_query_intf_ext_props *prop);
252 
253 	ipacm_ext_prop* GetExtProp(ipa_ip_type ip_type);
254 
255 	int DelExtProp(ipa_ip_type ip_type);
256 
257 	enum ipa_hw_type GetIPAVer(bool get = false);
258 
259 	int Init(void);
260 
isPrivateSubnet(uint32_t ip_addr)261 	inline bool isPrivateSubnet(uint32_t ip_addr)
262 	{
263 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
264 		{
265 			if(private_subnet_table[cnt].subnet_addr ==
266 				 (private_subnet_table[cnt].subnet_mask & ip_addr))
267 			{
268 				return true;
269 			}
270 		}
271 
272 		return false;
273 	}
274 #ifdef FEATURE_IPA_ANDROID
AddPrivateSubnet(uint32_t ip_addr,int ipa_if_index)275 	inline bool AddPrivateSubnet(uint32_t ip_addr, int ipa_if_index)
276 	{
277 		ipacm_cmd_q_data evt_data;
278 		ipacm_event_data_fid *data_fid;
279 		uint32_t subnet_mask = ~0;
280 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
281 		{
282 			if(private_subnet_table[cnt].subnet_addr == ip_addr)
283 			{
284 				IPACMDBG("Already has private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, cnt);
285 				return true;
286 			}
287 		}
288 
289 		if(ipa_num_private_subnet < IPA_MAX_PRIVATE_SUBNET_ENTRIES)
290 		{
291 			IPACMDBG("Add IPACM private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, ipa_num_private_subnet);
292 			private_subnet_table[ipa_num_private_subnet].subnet_addr = ip_addr;
293 			private_subnet_table[ipa_num_private_subnet].subnet_mask = (subnet_mask >> 8) << 8;
294 			ipa_num_private_subnet++;
295 
296 			/* IPACM private subnet set changes */
297 			data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
298 			if(data_fid == NULL)
299 			{
300 				IPACMERR("unable to allocate memory for event data_fid\n");
301 				return IPACM_FAILURE;
302 			}
303 			data_fid->if_index = ipa_if_index; // already ipa index, not fid index
304 			evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT;
305 			evt_data.evt_data = data_fid;
306 
307 			/* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */
308 			IPACM_EvtDispatcher::PostEvt(&evt_data);
309 			return true;
310 		}
311 		IPACMERR("IPACM private subnet_addr overflow, total entry(%d)\n", ipa_num_private_subnet);
312 		return false;
313 	}
314 
DelPrivateSubnet(uint32_t ip_addr,int ipa_if_index)315 	inline bool DelPrivateSubnet(uint32_t ip_addr, int ipa_if_index)
316 	{
317 		ipacm_cmd_q_data evt_data;
318 		ipacm_event_data_fid *data_fid;
319 		for(int cnt=0; cnt<ipa_num_private_subnet; cnt++)
320 		{
321 			if(private_subnet_table[cnt].subnet_addr == ip_addr)
322 			{
323 				IPACMDBG("Found private subnet_addr as: 0x%x in entry(%d) \n", ip_addr, cnt);
324 				for (; cnt < ipa_num_private_subnet - 1; cnt++)
325 				{
326 					private_subnet_table[cnt].subnet_addr = private_subnet_table[cnt+1].subnet_addr;
327 				}
328 				ipa_num_private_subnet = ipa_num_private_subnet - 1;
329 
330 				/* IPACM private subnet set changes */
331 				data_fid = (ipacm_event_data_fid *)malloc(sizeof(ipacm_event_data_fid));
332 				if(data_fid == NULL)
333 				{
334 					IPACMERR("unable to allocate memory for event data_fid\n");
335 					return IPACM_FAILURE;
336 				}
337 				data_fid->if_index = ipa_if_index; // already ipa index, not fid index
338 				evt_data.event = IPA_PRIVATE_SUBNET_CHANGE_EVENT;
339 				evt_data.evt_data = data_fid;
340 
341 				/* Insert IPA_PRIVATE_SUBNET_CHANGE_EVENT to command queue */
342 				IPACM_EvtDispatcher::PostEvt(&evt_data);
343 				return true;
344 			}
345 		}
346 		IPACMDBG("can't find private subnet_addr as: 0x%x \n", ip_addr);
347 		return false;
348 	}
349 #endif /* defined(FEATURE_IPA_ANDROID)*/
350 
351 	static const char *DEVICE_NAME_ODU;
352 
353 private:
354 	enum ipa_hw_type ver;
355 	static IPACM_Config *pInstance;
356 	static const char *DEVICE_NAME;
357 	IPACM_Config(void);
358 	int m_fd; /* File descriptor of the IPA device node /dev/ipa */
359 	uint8_t qmap_id;
360 	ipacm_ext_prop ext_prop_v4;
361 	ipacm_ext_prop ext_prop_v6;
362 };
363 
364 #endif /* IPACM_CONFIG */
365