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(rx_prop != NULL)
650 {
651 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
652 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]);
653 IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
654 }
655 else
656 {
657 /* only wlan may take software-path, not register Rx-property*/
658 if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
659 {
660 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
661 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
662 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
663 }
664 if(strcmp(dev_name,dev_ecm0) == 0)
665 {
666 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
667 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
668 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
669 }
670 }
671 }
672 if (rx_prop == NULL)
673 {
674 IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
675 return IPACM_SUCCESS;
676 }
677
678 /* construct ipa_ioc_add_flt_rule with default filter rules */
679 if (iptype == IPA_IP_v4)
680 {
681 len = sizeof(struct ipa_ioc_add_flt_rule) +
682 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
683
684 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
685 if (!m_pFilteringTable)
686 {
687 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
688 return IPACM_FAILURE;
689 }
690
691 m_pFilteringTable->commit = 1;
692 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
693 m_pFilteringTable->global = false;
694 m_pFilteringTable->ip = iptype;
695 m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
696
697 /* Configuring Fragment Filtering Rule */
698 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
699
700 flt_rule_entry.rule.retain_hdr = 1;
701 flt_rule_entry.at_rear = true;
702 flt_rule_entry.flt_rule_hdl = -1;
703 flt_rule_entry.status = -1;
704 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
705 #ifdef FEATURE_IPA_V3
706 flt_rule_entry.at_rear = false;
707 flt_rule_entry.rule.hashable = false;
708 #endif
709 IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
710 memcpy(&flt_rule_entry.rule.attrib,
711 &rx_prop->rx[0].attrib,
712 sizeof(flt_rule_entry.rule.attrib));
713
714 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
715 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
716
717 /* Configuring Multicast Filtering Rule */
718 memcpy(&flt_rule_entry.rule.attrib,
719 &rx_prop->rx[0].attrib,
720 sizeof(flt_rule_entry.rule.attrib));
721 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
722 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
723 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
724 #ifdef FEATURE_IPA_V3
725 flt_rule_entry.at_rear = true;
726 flt_rule_entry.rule.hashable = true;
727 #endif
728 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
729
730 /* Configuring Broadcast Filtering Rule */
731 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
732 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
733 #ifdef FEATURE_IPA_V3
734 flt_rule_entry.at_rear = true;
735 flt_rule_entry.rule.hashable = true;
736 #endif
737 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
738
739 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
740 {
741 IPACMERR("Error Adding Filtering rule, aborting...\n");
742 res = IPACM_FAILURE;
743 goto fail;
744 }
745 else
746 {
747 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
748 /* copy filter hdls */
749 for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
750 {
751 if (m_pFilteringTable->rules[i].status == 0)
752 {
753 dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
754 IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
755 }
756 else
757 {
758 IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
759 }
760 }
761 }
762 }
763 else
764 {
765 len = sizeof(struct ipa_ioc_add_flt_rule) +
766 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
767
768 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
769 if (!m_pFilteringTable)
770 {
771 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
772 return IPACM_FAILURE;
773 }
774
775 m_pFilteringTable->commit = 1;
776 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
777 m_pFilteringTable->global = false;
778 m_pFilteringTable->ip = iptype;
779 m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
780
781 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
782
783 flt_rule_entry.rule.retain_hdr = 1;
784 flt_rule_entry.at_rear = true;
785 flt_rule_entry.flt_rule_hdl = -1;
786 flt_rule_entry.status = -1;
787 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
788 /* Configuring Multicast Filtering Rule */
789 memcpy(&flt_rule_entry.rule.attrib,
790 &rx_prop->rx[0].attrib,
791 sizeof(flt_rule_entry.rule.attrib));
792 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
793 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
794 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
795 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
796 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
797 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
798 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
799 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
800 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
801 #ifdef FEATURE_IPA_V3
802 flt_rule_entry.at_rear = true;
803 flt_rule_entry.rule.hashable = true;
804 #endif
805 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
806
807 /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
808 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
809 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
810 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
811 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
812 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
813 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
814 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
815 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
816 #ifdef FEATURE_IPA_V3
817 flt_rule_entry.at_rear = true;
818 flt_rule_entry.rule.hashable = true;
819 #endif
820 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
821
822 /* Configuring fec0::/10 Reserved by IETF Filtering Rule */
823 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
824 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
825 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
826 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
827 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
828 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
829 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
830 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
831 #ifdef FEATURE_IPA_V3
832 flt_rule_entry.at_rear = true;
833 flt_rule_entry.rule.hashable = true;
834 #endif
835 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
836
837 /* Configuring fd00::/8 Unique Local Ipv6 Address */
838 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
839 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
840 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
841 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
842 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFD000000;
843 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
844 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
845 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
846 #ifdef FEATURE_IPA_V3
847 flt_rule_entry.at_rear = true;
848 flt_rule_entry.rule.hashable = true;
849 #endif
850 memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
851
852 #ifdef FEATURE_IPA_ANDROID
853 /* Add the ipv6 tcp fragment filtering rule. */
854
855 IPACMDBG_H("Adding IPv6 TCP fragment filter rule\n");
856
857 flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_DST_ADDR);
858
859 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR;
860 flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP;
861
862 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
863
864 memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry,
865 sizeof(struct ipa_flt_rule_add));
866
867 IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
868 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
869
870 flt_rule_entry.at_rear = true;
871 flt_rule_entry.flt_rule_hdl = -1;
872 flt_rule_entry.status = -1;
873
874 flt_rule_entry.rule.retain_hdr = 1;
875 flt_rule_entry.rule.to_uc = 0;
876 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
877 flt_rule_entry.rule.eq_attrib_type = 1;
878 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
879
880 if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
881 {
882 #ifdef FEATURE_IPA_V3
883 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
884 #else
885 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
886 #endif
887 flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
888 flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
889 flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
890 flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
891 }
892
893 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
894 flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
895 flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
896
897 #ifdef FEATURE_IPA_V3
898 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
899 #else
900 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
901 #endif
902 flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
903 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
904
905 /* add TCP FIN rule*/
906 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
907 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
908 memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
909
910 /* add TCP SYN rule*/
911 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
912 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
913 memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
914
915 /* add TCP RST rule*/
916 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
917 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
918 memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
919
920 #endif
921 if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
922 {
923 IPACMERR("Error Adding Filtering rule, aborting...\n");
924 res = IPACM_FAILURE;
925 goto fail;
926 }
927 else
928 {
929 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
930 /* copy filter hdls */
931 for (int i = 0;
932 i < IPV6_DEFAULT_FILTERTING_RULES;
933 i++)
934 {
935 if (m_pFilteringTable->rules[i].status == 0)
936 {
937 dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
938 IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
939 }
940 else
941 {
942 IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
943 }
944 }
945 }
946 }
947
948 /* Add Natting iface to IPACM_Config if there is Rx/Tx property */
949 if (rx_prop != NULL || tx_prop != NULL)
950 {
951 IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, iptype);
952 IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, iptype);
953 }
954
955 fail:
956 free(m_pFilteringTable);
957
958 return res;
959 }
960
961 /* get ipa interface name */
ipa_get_if_index(char * if_name,int * if_index)962 int IPACM_Iface::ipa_get_if_index
963 (
964 char * if_name,
965 int * if_index
966 )
967 {
968 int fd;
969 struct ifreq ifr;
970
971 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
972 {
973 IPACMERR("get interface index socket create failed \n");
974 return IPACM_FAILURE;
975 }
976
977 if(strlen(if_name) >= sizeof(ifr.ifr_name))
978 {
979 IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
980 close(fd);
981 return IPACM_FAILURE;
982 }
983
984 memset(&ifr, 0, sizeof(struct ifreq));
985 (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
986 IPACMDBG_H("interface name (%s)\n", if_name);
987
988 if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
989 {
990 IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
991 close(fd);
992 return IPACM_FAILURE;
993 }
994
995 *if_index = ifr.ifr_ifindex;
996 IPACMDBG_H("Interface index %d\n", *if_index);
997 close(fd);
998 return IPACM_SUCCESS;
999 }
1000
config_ip_type(ipa_ip_type iptype)1001 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
1002 {
1003 /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
1004 if (iptype == IPA_IP_v4)
1005 {
1006 if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
1007 {
1008 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1009 return;
1010 }
1011
1012 if (ip_type == IPA_IP_v6)
1013 {
1014 ip_type = IPA_IP_MAX;
1015 }
1016 else
1017 {
1018 ip_type = IPA_IP_v4;
1019 }
1020 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1021 }
1022 else
1023 {
1024 if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
1025 {
1026 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
1027 return;
1028 }
1029
1030 if (ip_type == IPA_IP_v4)
1031 {
1032 ip_type = IPA_IP_MAX;
1033 }
1034 else
1035 {
1036 ip_type = IPA_IP_v6;
1037 }
1038
1039 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1040 }
1041
1042 return;
1043 }
1044
delete_iface(void)1045 void IPACM_Iface::delete_iface(void)
1046 {
1047 IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n",
1048 IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name, ipa_if_num);
1049 delete this;
1050 }
1051