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.Z
28 */
29 /*!
30 @file
31 IPACM_Iface.cpp
32
33 @brief
34 This file implements the basis Iface functionality.
35
36 @Author
37 Skylar Chang
38
39 */
40 #include <fcntl.h>
41 #include <sys/ioctl.h>
42 #include <IPACM_Netlink.h>
43 #include <IPACM_Iface.h>
44 #include <IPACM_Lan.h>
45 #include <IPACM_Wan.h>
46 #include <IPACM_Wlan.h>
47 #include <string.h>
48
49 extern "C"
50 {
51 #include <ifaddrs.h>
52 }
53
54
55 const char *IPACM_Iface::DEVICE_NAME = "/dev/ipa";
56 IPACM_Routing IPACM_Iface::m_routing;
57 IPACM_Filtering IPACM_Iface::m_filtering;
58 IPACM_Header IPACM_Iface::m_header;
59
60 IPACM_Config *IPACM_Iface::ipacmcfg = IPACM_Config::GetInstance();
61
IPACM_Iface(int iface_index)62 IPACM_Iface::IPACM_Iface(int iface_index)
63 {
64 ip_type = IPACM_IP_NULL; /* initially set invalid */
65 num_dft_rt_v6 = 0;
66 softwarerouting_act = false;
67 ipa_if_num = iface_index;
68 ipa_if_cate = IPACM_Iface::ipacmcfg->iface_table[iface_index].if_cat;
69
70 iface_query = NULL;
71 tx_prop = NULL;
72 rx_prop = NULL;
73
74 memcpy(dev_name,
75 IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name,
76 sizeof(IPACM_Iface::ipacmcfg->iface_table[iface_index].iface_name));
77
78 memset(dft_v4fl_rule_hdl, 0, sizeof(dft_v4fl_rule_hdl));
79 memset(dft_v6fl_rule_hdl, 0, sizeof(dft_v6fl_rule_hdl));
80
81 memset(dft_rt_rule_hdl, 0, sizeof(dft_rt_rule_hdl));
82 memset(software_routing_fl_rule_hdl, 0, sizeof(software_routing_fl_rule_hdl));
83 memset(ipv6_addr, 0, sizeof(ipv6_addr));
84
85 query_iface_property();
86 IPACMDBG_H(" create iface-index(%d) constructor\n", ipa_if_num);
87 return;
88 }
89
90 /* software routing enable */
handle_software_routing_enable(void)91 int IPACM_Iface::handle_software_routing_enable(void)
92 {
93
94 int res = IPACM_SUCCESS;
95 struct ipa_flt_rule_add flt_rule_entry;
96 ipa_ioc_add_flt_rule *m_pFilteringTable;
97
98 IPACMDBG("\n");
99 if (softwarerouting_act == true)
100 {
101 IPACMDBG("already setup software_routing rule for (%s)iface ip-family %d\n",
102 IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
103 return IPACM_SUCCESS;
104 }
105
106 if(rx_prop == NULL)
107 {
108 IPACMDBG("No rx properties registered for iface %s\n", dev_name);
109 return IPACM_SUCCESS;
110 }
111
112 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)
113 calloc(1,
114 sizeof(struct ipa_ioc_add_flt_rule) +
115 1 * sizeof(struct ipa_flt_rule_add)
116 );
117 if (!m_pFilteringTable)
118 {
119 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
120 return IPACM_FAILURE;
121 }
122
123 m_pFilteringTable->commit = 1;
124 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
125 m_pFilteringTable->global = false;
126 m_pFilteringTable->num_rules = (uint8_t)1;
127
128
129 /* Configuring Software-Routing Filtering Rule */
130 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
131
132 flt_rule_entry.at_rear = false;
133 flt_rule_entry.flt_rule_hdl = -1;
134 flt_rule_entry.status = -1;
135 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
136 #ifdef FEATURE_IPA_V3
137 flt_rule_entry.rule.hashable = true;
138 #endif
139 memcpy(&flt_rule_entry.rule.attrib,
140 &rx_prop->rx[0].attrib,
141 sizeof(flt_rule_entry.rule.attrib));
142
143 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
144
145 /* check iface is v4 or v6 or both*/
146 // if (ip_type == IPA_IP_MAX)
147 // {
148 /* handle v4 */
149 m_pFilteringTable->ip = IPA_IP_v4;
150 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
151 {
152 IPACMERR("Error Adding Filtering rule, aborting...\n");
153 res = IPACM_FAILURE;
154 goto fail;
155 }
156 else if (m_pFilteringTable->rules[0].status)
157 {
158 IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
159 res = IPACM_FAILURE;
160 goto fail;
161 }
162
163 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
164 IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
165 /* copy filter hdls */
166 software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
167
168
169 /* handle v6*/
170 m_pFilteringTable->ip = IPA_IP_v6;
171 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
172 {
173 IPACMERR("Error Adding Filtering rule, aborting...\n");
174 res = IPACM_FAILURE;
175 goto fail;
176 }
177 else if (m_pFilteringTable->rules[0].status)
178 {
179 IPACMDBG("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
180 res = IPACM_FAILURE;
181 goto fail;
182 }
183
184 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
185 IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
186 /* copy filter hdls */
187 software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
188 softwarerouting_act = true;
189 #if 0
190 }
191 else
192 {
193 if (ip_type == IPA_IP_v4)
194 {
195 m_pFilteringTable->ip = IPA_IP_v4;
196 }
197 else
198 {
199 m_pFilteringTable->ip = IPA_IP_v6;
200 }
201
202 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
203 {
204 IPACMERR("Error Adding Filtering rule, aborting...\n");
205 res = IPACM_FAILURE;
206 goto fail;
207 }
208 else if (m_pFilteringTable->rules[0].status)
209 {
210 IPACMERR("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status);
211 res = IPACM_FAILURE;
212 goto fail;
213 }
214
215 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, ip_type, 1);
216 IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl);
217 /* copy filter hdls */
218 if (ip_type == IPA_IP_v4)
219 {
220 software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl;
221 }
222 else
223 {
224 software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl;
225 }
226 softwarerouting_act = true;
227 }
228 #endif
229
230 fail:
231 free(m_pFilteringTable);
232
233 return res;
234 }
235
236 /* software routing disable */
handle_software_routing_disable(void)237 int IPACM_Iface::handle_software_routing_disable(void)
238 {
239 int res = IPACM_SUCCESS;
240
241 if (rx_prop == NULL)
242 {
243 IPACMDBG("No rx properties registered for iface %s\n", dev_name);
244 return IPACM_SUCCESS;
245 }
246
247 if (softwarerouting_act == false)
248 {
249 IPACMDBG("already delete software_routing rule for (%s)iface ip-family %d\n", IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ip_type);
250 return IPACM_SUCCESS;
251 }
252
253 // if (ip_type == IPA_IP_MAX)
254 // {
255 /* ipv4 case */
256 if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0],
257 IPA_IP_v4, 1) == false)
258 {
259 IPACMERR("Error Adding Filtering rule, aborting...\n");
260 res = IPACM_FAILURE;
261 goto fail;
262 }
263 IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1);
264
265 /* ipv6 case */
266 if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1],
267 IPA_IP_v6, 1) == false)
268 {
269 IPACMERR("Error Adding Filtering rule, aborting...\n");
270 res = IPACM_FAILURE;
271 goto fail;
272 }
273 IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1);
274 softwarerouting_act = false;
275 #if 0
276 }
277 else
278 {
279 if (ip_type == IPA_IP_v4)
280 {
281 ip = IPA_IP_v4;
282 }
283 else
284 {
285 ip = IPA_IP_v6;
286 }
287
288
289 if (ip_type == IPA_IP_v4)
290 {
291 flt_hdl = software_routing_fl_rule_hdl[0];
292 }
293 else
294 {
295 flt_hdl = software_routing_fl_rule_hdl[1];
296 }
297
298 if (m_filtering.DeleteFilteringHdls(&flt_hdl, ip, 1) == false)
299 {
300 IPACMERR("Error Adding Filtering rule, aborting...\n");
301 res = IPACM_FAILURE;
302 goto fail;
303 }
304 IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1);
305 softwarerouting_act = false;
306 }
307 #endif
308
309 fail:
310 return res;
311 }
312
313 /* Query ipa_interface_index by given linux interface_index */
iface_ipa_index_query(int interface_index)314 int IPACM_Iface::iface_ipa_index_query
315 (
316 int interface_index
317 )
318 {
319 int fd;
320 int link = INVALID_IFACE;
321 int i = 0;
322 struct ifreq ifr;
323
324
325 if(IPACM_Iface::ipacmcfg->iface_table == NULL)
326 {
327 IPACMERR("Iface table in IPACM_Config is not available.\n");
328 return link;
329 }
330
331 /* Search known linux interface-index and map to IPA interface-index*/
332 for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
333 {
334 if (interface_index == IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index)
335 {
336 link = i;
337 IPACMDBG("Interface (%s) found: linux(%d) ipa(%d) \n",
338 IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
339 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index,
340 link);
341 return link;
342 break;
343 }
344 }
345
346 /* Search/Configure linux interface-index and map it to IPA interface-index */
347 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
348 {
349 PERROR("get interface name socket create failed");
350 return IPACM_FAILURE;
351 }
352
353 memset(&ifr, 0, sizeof(struct ifreq));
354
355 ifr.ifr_ifindex = interface_index;
356 IPACMDBG_H("Interface index %d\n", interface_index);
357
358 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
359 {
360 PERROR("call_ioctl_on_dev: ioctl failed:");
361 close(fd);
362 return IPACM_FAILURE;
363 }
364 close(fd);
365
366 IPACMDBG_H("Received interface name %s\n", ifr.ifr_name);
367 for (i = 0; i < IPACM_Iface::ipacmcfg->ipa_num_ipa_interfaces; i++)
368 {
369 if (strncmp(ifr.ifr_name,
370 IPACM_Iface::ipacmcfg->iface_table[i].iface_name,
371 sizeof(IPACM_Iface::ipacmcfg->iface_table[i].iface_name)) == 0)
372 {
373 IPACMDBG_H("Interface (%s) linux(%d) mapped to ipa(%d) \n", ifr.ifr_name,
374 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index, i);
375
376 link = i;
377 IPACM_Iface::ipacmcfg->iface_table[i].netlink_interface_index = interface_index;
378 break;
379 }
380 }
381
382 return link;
383 }
384
385 /* Query ipa_interface ipv4_addr by given linux interface_index */
iface_addr_query(int interface_index)386 void IPACM_Iface::iface_addr_query
387 (
388 int interface_index
389 )
390 {
391 int fd;
392 struct ifreq ifr;
393 struct ifaddrs *myaddrs, *ifa;
394 ipacm_cmd_q_data evt_data;
395 ipacm_event_data_addr *data_addr;
396 struct in_addr iface_ipv4;
397
398 /* use linux interface-index to find interface name */
399 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
400 {
401 PERROR("get interface name socket create failed");
402 return ;
403 }
404
405 memset(&ifr, 0, sizeof(struct ifreq));
406
407 ifr.ifr_ifindex = interface_index;
408 IPACMDBG_H("Interface index %d\n", interface_index);
409
410 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
411 {
412 PERROR("call_ioctl_on_dev: ioctl failed:");
413 close(fd);
414 return ;
415 }
416 IPACMDBG_H("Interface index %d name: %s\n", interface_index,ifr.ifr_name);
417 close(fd);
418
419 /* query ipv4/v6 address */
420 if(getifaddrs(&myaddrs) != 0)
421 {
422 IPACMERR("getifaddrs");
423 return ;
424 }
425
426 for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
427 {
428 if (ifa->ifa_addr == NULL)
429 continue;
430 if (!(ifa->ifa_flags & IFF_UP))
431 continue;
432
433 if(strcmp(ifr.ifr_name,ifa->ifa_name) == 0) // find current iface
434 {
435 IPACMDBG_H("Internal post new_addr event for iface %s\n", ifa->ifa_name);
436 switch (ifa->ifa_addr->sa_family)
437 {
438 case AF_INET:
439 {
440 struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
441 IPACMDBG_H("ipv4 address %s\n",inet_ntoa(s4->sin_addr));
442 iface_ipv4 = s4->sin_addr;
443 /* post new_addr event to command queue */
444 data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
445 if(data_addr == NULL)
446 {
447 IPACMERR("unable to allocate memory for event data_addr\n");
448 freeifaddrs(myaddrs);
449 return ;
450 }
451 memset(data_addr, 0, sizeof(ipacm_event_data_addr));
452 data_addr->iptype = IPA_IP_v4;
453 data_addr->if_index = interface_index;
454 data_addr->ipv4_addr = iface_ipv4.s_addr;
455 data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
456 strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
457 IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv4 addr:0x%x\n",
458 data_addr->if_index,
459 data_addr->iface_name,
460 data_addr->ipv4_addr);
461
462 evt_data.event = IPA_ADDR_ADD_EVENT;
463 evt_data.evt_data = data_addr;
464 IPACM_EvtDispatcher::PostEvt(&evt_data);
465 break;
466 }
467
468 case AF_INET6:
469 {
470 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
471 /* post new_addr event to command queue */
472 data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
473 if(data_addr == NULL)
474 {
475 IPACMERR("unable to allocate memory for event data_addr\n");
476 freeifaddrs(myaddrs);
477 return ;
478 }
479 memset(data_addr, 0, sizeof(ipacm_event_data_addr));
480 data_addr->iptype = IPA_IP_v6;
481 data_addr->if_index = interface_index;
482 memcpy(data_addr->ipv6_addr,
483 &s6->sin6_addr,
484 sizeof(data_addr->ipv6_addr));
485 data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
486 data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
487 data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
488 data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
489 strlcpy(data_addr->iface_name, ifr.ifr_name, sizeof(data_addr->iface_name));
490 IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, if name:%s, ipv6 addr:0x%x:%x:%x:%x\n",
491 data_addr->if_index,
492 data_addr->iface_name,
493 data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
494
495 evt_data.event = IPA_ADDR_ADD_EVENT;
496 evt_data.evt_data = data_addr;
497 IPACM_EvtDispatcher::PostEvt(&evt_data);
498 break;
499 }
500
501 default:
502 continue;
503 }
504 }
505 }
506 freeifaddrs(myaddrs);
507 return ;
508 }
509
510 /*Query the IPA endpoint property */
query_iface_property(void)511 int IPACM_Iface::query_iface_property(void)
512 {
513 int res = IPACM_SUCCESS, fd = 0;
514 uint32_t cnt=0;
515
516 fd = open(DEVICE_NAME, O_RDWR);
517 IPACMDBG("iface query-property \n");
518 if (0 == fd)
519 {
520 IPACMERR("Failed opening %s.\n", DEVICE_NAME);
521 return IPACM_FAILURE;
522 }
523
524 iface_query = (struct ipa_ioc_query_intf *)
525 calloc(1, sizeof(struct ipa_ioc_query_intf));
526 if(iface_query == NULL)
527 {
528 IPACMERR("Unable to allocate iface_query memory.\n");
529 close(fd);
530 return IPACM_FAILURE;
531 }
532 IPACMDBG_H("iface name %s\n", dev_name);
533 memcpy(iface_query->name, dev_name, sizeof(dev_name));
534
535 if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0)
536 {
537 PERROR("ioctl IPA_IOC_QUERY_INTF failed\n");
538 /* iface_query memory will free when iface-down*/
539 res = IPACM_FAILURE;
540 }
541
542 if(iface_query->num_tx_props > 0)
543 {
544 tx_prop = (struct ipa_ioc_query_intf_tx_props *)
545 calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) +
546 iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop));
547 if(tx_prop == NULL)
548 {
549 IPACMERR("Unable to allocate tx_prop memory.\n");
550 close(fd);
551 return IPACM_FAILURE;
552 }
553 memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
554 tx_prop->num_tx_props = iface_query->num_tx_props;
555
556 if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0)
557 {
558 PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n");
559 /* tx_prop memory will free when iface-down*/
560 res = IPACM_FAILURE;
561 }
562
563 if (res != IPACM_FAILURE)
564 {
565 for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
566 {
567 IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n",
568 cnt, tx_prop->tx[cnt].attrib.attrib_mask,
569 tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe,
570 tx_prop->tx[cnt].alt_dst_pipe,
571 tx_prop->tx[cnt].hdr_name);
572
573 if (tx_prop->tx[cnt].dst_pipe == 0)
574 {
575 IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt);
576 close(fd);
577 return IPACM_FAILURE;
578 }
579 if (tx_prop->tx[cnt].alt_dst_pipe == 0 &&
580 ((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) ||
581 (memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0)))
582 {
583 IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt);
584 close(fd);
585 return IPACM_FAILURE;
586 }
587
588 }
589 }
590
591 }
592
593 if (iface_query->num_rx_props > 0)
594 {
595 rx_prop = (struct ipa_ioc_query_intf_rx_props *)
596 calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) +
597 iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop));
598 if(rx_prop == NULL)
599 {
600 IPACMERR("Unable to allocate rx_prop memory.\n");
601 close(fd);
602 return IPACM_FAILURE;
603 }
604 memcpy(rx_prop->name, dev_name,
605 sizeof(rx_prop->name));
606 rx_prop->num_rx_props = iface_query->num_rx_props;
607
608 if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0)
609 {
610 PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n");
611 /* rx_prop memory will free when iface-down*/
612 res = IPACM_FAILURE;
613 }
614
615 if (res != IPACM_FAILURE)
616 {
617 for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
618 {
619 IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n",
620 cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe);
621 }
622 }
623 }
624
625 close(fd);
626 return res;
627 }
628
629 /*Configure the initial filter rules */
init_fl_rule(ipa_ip_type iptype)630 int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
631 {
632
633 int res = IPACM_SUCCESS, len = 0;
634 struct ipa_flt_rule_add flt_rule_entry;
635 ipa_ioc_add_flt_rule *m_pFilteringTable;
636
637 /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/
638 const char *dev_wlan0="wlan0";
639 const char *dev_wlan1="wlan1";
640 const char *dev_ecm0="ecm0";
641
642 /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
643 if((IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== WAN_IF) || (IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat== EMBMS_IF))
644 {
645 IPACMDBG_H(" NOT add producer dependency on dev %s with registered rx-prop cat:%d \n", dev_name, IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].if_cat);
646 }
647 else
648 {
649 if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0)
650 {
651 if(rx_prop != NULL)
652 {
653 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
654 IPACMDBG_H("depend Got pipe %d rm index : %d \n", rx_prop->rx[0].src_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe]);
655 IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
656 }
657 else
658 {
659 /* only wlan may take software-path, not register Rx-property*/
660 if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
661 {
662 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
663 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
664 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
665 }
666 if(strcmp(dev_name,dev_ecm0) == 0)
667 {
668 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
669 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
670 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
671 }
672 }
673 }
674 }
675 if (rx_prop == NULL)
676 {
677 IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
678 return IPACM_SUCCESS;
679 }
680
681 /* construct ipa_ioc_add_flt_rule with default filter rules */
682 if (iptype == IPA_IP_v4)
683 {
684 len = sizeof(struct ipa_ioc_add_flt_rule) +
685 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
686
687 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
688 if (!m_pFilteringTable)
689 {
690 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
691 return IPACM_FAILURE;
692 }
693
694 m_pFilteringTable->commit = 1;
695 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
696 m_pFilteringTable->global = false;
697 m_pFilteringTable->ip = iptype;
698 m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
699
700 /* Configuring Fragment Filtering Rule */
701 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
702
703 flt_rule_entry.rule.retain_hdr = 1;
704 flt_rule_entry.at_rear = true;
705 flt_rule_entry.flt_rule_hdl = -1;
706 flt_rule_entry.status = -1;
707 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
708 #ifdef FEATURE_IPA_V3
709 flt_rule_entry.at_rear = false;
710 flt_rule_entry.rule.hashable = false;
711 #endif
712 IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
713 memcpy(&flt_rule_entry.rule.attrib,
714 &rx_prop->rx[0].attrib,
715 sizeof(flt_rule_entry.rule.attrib));
716
717 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
718 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
719
720 /* Configuring Multicast Filtering Rule */
721 memcpy(&flt_rule_entry.rule.attrib,
722 &rx_prop->rx[0].attrib,
723 sizeof(flt_rule_entry.rule.attrib));
724 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
725 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
726 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
727 #ifdef FEATURE_IPA_V3
728 flt_rule_entry.at_rear = true;
729 flt_rule_entry.rule.hashable = true;
730 #endif
731 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
732
733 /* Configuring Broadcast Filtering Rule */
734 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
735 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
736 #ifdef FEATURE_IPA_V3
737 flt_rule_entry.at_rear = true;
738 flt_rule_entry.rule.hashable = true;
739 #endif
740 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
741
742 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
743 {
744 IPACMERR("Error Adding Filtering rule, aborting...\n");
745 res = IPACM_FAILURE;
746 goto fail;
747 }
748 else
749 {
750 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
751 /* copy filter hdls */
752 for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
753 {
754 if (m_pFilteringTable->rules[i].status == 0)
755 {
756 dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
757 IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
758 }
759 else
760 {
761 IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
762 }
763 }
764 }
765 }
766 else
767 {
768 len = sizeof(struct ipa_ioc_add_flt_rule) +
769 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
770
771 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
772 if (!m_pFilteringTable)
773 {
774 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
775 return IPACM_FAILURE;
776 }
777
778 m_pFilteringTable->commit = 1;
779 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
780 m_pFilteringTable->global = false;
781 m_pFilteringTable->ip = iptype;
782 m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
783
784 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
785
786 flt_rule_entry.rule.retain_hdr = 1;
787 flt_rule_entry.at_rear = true;
788 flt_rule_entry.flt_rule_hdl = -1;
789 flt_rule_entry.status = -1;
790 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
791 /* Configuring Multicast Filtering Rule */
792 memcpy(&flt_rule_entry.rule.attrib,
793 &rx_prop->rx[0].attrib,
794 sizeof(flt_rule_entry.rule.attrib));
795 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
796 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
797 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
798 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
799 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
800 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
801 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
802 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
803 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
804 #ifdef FEATURE_IPA_V3
805 flt_rule_entry.at_rear = true;
806 flt_rule_entry.rule.hashable = true;
807 #endif
808 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
809
810 /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
811 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
812 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
813 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
814 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
815 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
816 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
817 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
818 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
819 #ifdef FEATURE_IPA_V3
820 flt_rule_entry.at_rear = true;
821 flt_rule_entry.rule.hashable = true;
822 #endif
823 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
824
825 /* Configuring fec0::/10 Reserved by IETF Filtering Rule */
826 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
827 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
828 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
829 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
830 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
831 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
832 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
833 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
834 #ifdef FEATURE_IPA_V3
835 flt_rule_entry.at_rear = true;
836 flt_rule_entry.rule.hashable = true;
837 #endif
838 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
839
840 /* Configuring fd00::/8 Unique Local Ipv6 Address */
841 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
842 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
843 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
844 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
845 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000;
846 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
847 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
848 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
849 #ifdef FEATURE_IPA_V3
850 flt_rule_entry.at_rear = true;
851 flt_rule_entry.rule.hashable = true;
852 #endif
853 memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
854
855 #ifdef FEATURE_IPA_ANDROID
856 /* Add the ipv6 tcp fragment filtering rule. */
857
858 IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
859
860 flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
861
862 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
863 flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
864
865 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
866
867 memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
868 sizeof(struct ipa_flt_rule_add));
869
870 IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
871 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
872
873 flt_rule_entry.at_rear = true;
874 flt_rule_entry.flt_rule_hdl = -1;
875 flt_rule_entry.status = -1;
876
877 flt_rule_entry.rule.retain_hdr = 1;
878 flt_rule_entry.rule.to_uc = 0;
879 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
880 flt_rule_entry.rule.eq_attrib_type = 1;
881 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
882
883 if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
884 {
885 #ifdef FEATURE_IPA_V3
886 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
887 #else
888 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
889 #endif
890 flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
891 flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
892 flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
893 flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
894 }
895
896 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
897 flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
898 flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
899
900 #ifdef FEATURE_IPA_V3
901 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
902 #else
903 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
904 #endif
905 flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
906 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
907
908 /* add TCP FIN rule*/
909 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
910 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
911 memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
912
913 /* add TCP SYN rule*/
914 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
915 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
916 memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
917
918 /* add TCP RST rule*/
919 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
920 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
921 memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
922
923 #endif
924 if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
925 {
926 IPACMERR("Error Adding Filtering rule, aborting...\n");
927 res = IPACM_FAILURE;
928 goto fail;
929 }
930 else
931 {
932 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
933 /* copy filter hdls */
934 for (int i = 0;
935 i < IPV6_DEFAULT_FILTERTING_RULES;
936 i++)
937 {
938 if (m_pFilteringTable->rules[i].status == 0)
939 {
940 dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
941 IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
942 }
943 else
944 {
945 IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
946 }
947 }
948 }
949 }
950
951 /* Add Natting iface to IPACM_Config if there is Rx/Tx property */
952 if (rx_prop != NULL || tx_prop != NULL)
953 {
954 IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, iptype);
955 IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
956 }
957
958 fail:
959 free(m_pFilteringTable);
960
961 return res;
962 }
963
964 /* get ipa interface name */
ipa_get_if_index(char * if_name,int * if_index)965 int IPACM_Iface::ipa_get_if_index
966 (
967 char * if_name,
968 int * if_index
969 )
970 {
971 int fd;
972 struct ifreq ifr;
973
974 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
975 {
976 IPACMERR("get interface index socket create failed \n");
977 return IPACM_FAILURE;
978 }
979
980 if(strlen(if_name) >= sizeof(ifr.ifr_name))
981 {
982 IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
983 close(fd);
984 return IPACM_FAILURE;
985 }
986
987 memset(&ifr, 0, sizeof(struct ifreq));
988 (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
989 IPACMDBG_H("interface name (%s)\n", if_name);
990
991 if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
992 {
993 IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
994 close(fd);
995 return IPACM_FAILURE;
996 }
997
998 *if_index = ifr.ifr_ifindex;
999 IPACMDBG_H("Interface index %d\n", *if_index);
1000 close(fd);
1001 return IPACM_SUCCESS;
1002 }
1003
config_ip_type(ipa_ip_type iptype)1004 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
1005 {
1006 /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
1007 if (iptype == IPA_IP_v4)
1008 {
1009 if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
1010 {
1011 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1012 return;
1013 }
1014
1015 if (ip_type == IPA_IP_v6)
1016 {
1017 ip_type = IPA_IP_MAX;
1018 }
1019 else
1020 {
1021 ip_type = IPA_IP_v4;
1022 }
1023 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1024 }
1025 else
1026 {
1027 if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
1028 {
1029 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1030 return;
1031 }
1032
1033 if (ip_type == IPA_IP_v4)
1034 {
1035 ip_type = IPA_IP_MAX;
1036 }
1037 else
1038 {
1039 ip_type = IPA_IP_v6;
1040 }
1041
1042 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1043 }
1044
1045 return;
1046 }
1047
delete_iface(void)1048 void IPACM_Iface::delete_iface(void)
1049 {
1050 IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n",
1051 IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
1052 delete this;
1053 }
1054