1 /*
2 Copyright (c) 2013, 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 data_addr->iptype = IPA_IP_v4;
452 data_addr->if_index = interface_index;
453 data_addr->ipv4_addr = iface_ipv4.s_addr;
454 data_addr->ipv4_addr = ntohl(data_addr->ipv4_addr);
455 IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv4 addr:0x%x\n",
456 data_addr->if_index,
457 data_addr->ipv4_addr);
458
459 evt_data.event = IPA_ADDR_ADD_EVENT;
460 evt_data.evt_data = data_addr;
461 IPACM_EvtDispatcher::PostEvt(&evt_data);
462 break;
463 }
464
465 case AF_INET6:
466 {
467 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
468 /* post new_addr event to command queue */
469 data_addr = (ipacm_event_data_addr *)malloc(sizeof(ipacm_event_data_addr));
470 if(data_addr == NULL)
471 {
472 IPACMERR("unable to allocate memory for event data_addr\n");
473 freeifaddrs(myaddrs);
474 return ;
475 }
476 data_addr->iptype = IPA_IP_v6;
477 data_addr->if_index = interface_index;
478 memcpy(data_addr->ipv6_addr,
479 &s6->sin6_addr,
480 sizeof(data_addr->ipv6_addr));
481 data_addr->ipv6_addr[0] = ntohl(data_addr->ipv6_addr[0]);
482 data_addr->ipv6_addr[1] = ntohl(data_addr->ipv6_addr[1]);
483 data_addr->ipv6_addr[2] = ntohl(data_addr->ipv6_addr[2]);
484 data_addr->ipv6_addr[3] = ntohl(data_addr->ipv6_addr[3]);
485 IPACMDBG_H("Posting IPA_ADDR_ADD_EVENT with if index:%d, ipv6 addr:0x%x:%x:%x:%x\n",
486 data_addr->if_index,
487 data_addr->ipv6_addr[0], data_addr->ipv6_addr[1], data_addr->ipv6_addr[2], data_addr->ipv6_addr[3]);
488
489 evt_data.event = IPA_ADDR_ADD_EVENT;
490 evt_data.evt_data = data_addr;
491 IPACM_EvtDispatcher::PostEvt(&evt_data);
492 break;
493 }
494
495 default:
496 continue;
497 }
498 }
499 }
500 freeifaddrs(myaddrs);
501 return ;
502 }
503
504 /*Query the IPA endpoint property */
query_iface_property(void)505 int IPACM_Iface::query_iface_property(void)
506 {
507 int res = IPACM_SUCCESS, fd = 0;
508 uint32_t cnt=0;
509
510 fd = open(DEVICE_NAME, O_RDWR);
511 IPACMDBG("iface query-property \n");
512 if (0 == fd)
513 {
514 IPACMERR("Failed opening %s.\n", DEVICE_NAME);
515 return IPACM_FAILURE;
516 }
517
518 iface_query = (struct ipa_ioc_query_intf *)
519 calloc(1, sizeof(struct ipa_ioc_query_intf));
520 if(iface_query == NULL)
521 {
522 IPACMERR("Unable to allocate iface_query memory.\n");
523 close(fd);
524 return IPACM_FAILURE;
525 }
526 IPACMDBG_H("iface name %s\n", dev_name);
527 memcpy(iface_query->name, dev_name, sizeof(dev_name));
528
529 if (ioctl(fd, IPA_IOC_QUERY_INTF, iface_query) < 0)
530 {
531 PERROR("ioctl IPA_IOC_QUERY_INTF failed\n");
532 /* iface_query memory will free when iface-down*/
533 res = IPACM_FAILURE;
534 }
535
536 if(iface_query->num_tx_props > 0)
537 {
538 tx_prop = (struct ipa_ioc_query_intf_tx_props *)
539 calloc(1, sizeof(struct ipa_ioc_query_intf_tx_props) +
540 iface_query->num_tx_props * sizeof(struct ipa_ioc_tx_intf_prop));
541 if(tx_prop == NULL)
542 {
543 IPACMERR("Unable to allocate tx_prop memory.\n");
544 close(fd);
545 return IPACM_FAILURE;
546 }
547 memcpy(tx_prop->name, dev_name, sizeof(tx_prop->name));
548 tx_prop->num_tx_props = iface_query->num_tx_props;
549
550 if (ioctl(fd, IPA_IOC_QUERY_INTF_TX_PROPS, tx_prop) < 0)
551 {
552 PERROR("ioctl IPA_IOC_QUERY_INTF_TX_PROPS failed\n");
553 /* tx_prop memory will free when iface-down*/
554 res = IPACM_FAILURE;
555 }
556
557 if (res != IPACM_FAILURE)
558 {
559 for (cnt = 0; cnt < tx_prop->num_tx_props; cnt++)
560 {
561 IPACMDBG_H("Tx(%d):attrib-mask:0x%x, ip-type: %d, dst_pipe: %d, alt_dst_pipe: %d, header: %s\n",
562 cnt, tx_prop->tx[cnt].attrib.attrib_mask,
563 tx_prop->tx[cnt].ip, tx_prop->tx[cnt].dst_pipe,
564 tx_prop->tx[cnt].alt_dst_pipe,
565 tx_prop->tx[cnt].hdr_name);
566
567 if (tx_prop->tx[cnt].dst_pipe == 0)
568 {
569 IPACMERR("Tx(%d): wrong tx property: dst_pipe: 0.\n", cnt);
570 close(fd);
571 return IPACM_FAILURE;
572 }
573 if (tx_prop->tx[cnt].alt_dst_pipe == 0 &&
574 ((memcmp(dev_name, "wlan0", sizeof("wlan0")) == 0) ||
575 (memcmp(dev_name, "wlan1", sizeof("wlan1")) == 0)))
576 {
577 IPACMERR("Tx(%d): wrong tx property: alt_dst_pipe: 0. \n", cnt);
578 close(fd);
579 return IPACM_FAILURE;
580 }
581
582 }
583 }
584
585 }
586
587 if (iface_query->num_rx_props > 0)
588 {
589 rx_prop = (struct ipa_ioc_query_intf_rx_props *)
590 calloc(1, sizeof(struct ipa_ioc_query_intf_rx_props) +
591 iface_query->num_rx_props * sizeof(struct ipa_ioc_rx_intf_prop));
592 if(rx_prop == NULL)
593 {
594 IPACMERR("Unable to allocate rx_prop memory.\n");
595 close(fd);
596 return IPACM_FAILURE;
597 }
598 memcpy(rx_prop->name, dev_name,
599 sizeof(rx_prop->name));
600 rx_prop->num_rx_props = iface_query->num_rx_props;
601
602 if (ioctl(fd, IPA_IOC_QUERY_INTF_RX_PROPS, rx_prop) < 0)
603 {
604 PERROR("ioctl IPA_IOC_QUERY_INTF_RX_PROPS failed\n");
605 /* rx_prop memory will free when iface-down*/
606 res = IPACM_FAILURE;
607 }
608
609 if (res != IPACM_FAILURE)
610 {
611 for (cnt = 0; cnt < rx_prop->num_rx_props; cnt++)
612 {
613 IPACMDBG_H("Rx(%d):attrib-mask:0x%x, ip-type: %d, src_pipe: %d\n",
614 cnt, rx_prop->rx[cnt].attrib.attrib_mask, rx_prop->rx[cnt].ip, rx_prop->rx[cnt].src_pipe);
615 }
616 }
617 }
618
619 /* Add Natting iface to IPACM_Config if there is Rx/Tx property */
620 if (rx_prop != NULL || tx_prop != NULL)
621 {
622 IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING \n", dev_name);
623 IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name);
624 }
625
626 close(fd);
627 return res;
628 }
629
630 /*Configure the initial filter rules */
init_fl_rule(ipa_ip_type iptype)631 int IPACM_Iface::init_fl_rule(ipa_ip_type iptype)
632 {
633
634 int res = IPACM_SUCCESS, len = 0;
635 struct ipa_flt_rule_add flt_rule_entry;
636 ipa_ioc_add_flt_rule *m_pFilteringTable;
637
638 /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/
639 const char *dev_wlan0="wlan0";
640 const char *dev_wlan1="wlan1";
641 const char *dev_ecm0="ecm0";
642
643 /* ADD corresponding ipa_rm_resource_name of RX-endpoint before adding all IPV4V6 FT-rules */
644 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))
645 {
646 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);
647 }
648 else
649 {
650 if(rx_prop != NULL)
651 {
652 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
653 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]);
654 IPACM_Iface::ipacmcfg->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[rx_prop->rx[0].src_pipe],false);
655 }
656 else
657 {
658 /* only wlan may take software-path, not register Rx-property*/
659 if(strcmp(dev_name,dev_wlan0) == 0 || strcmp(dev_name,dev_wlan1) == 0)
660 {
661 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
662 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_HSIC_PROD);
663 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_HSIC_PROD,true);
664 }
665 if(strcmp(dev_name,dev_ecm0) == 0)
666 {
667 IPACMDBG_H("dev %s add producer dependency\n", dev_name);
668 IPACMDBG_H("depend Got piperm index : %d \n", IPA_RM_RESOURCE_USB_PROD);
669 IPACM_Iface::ipacmcfg->AddRmDepend(IPA_RM_RESOURCE_USB_PROD,true);
670 }
671 }
672 }
673 if (rx_prop == NULL)
674 {
675 IPACMDBG_H("No rx properties registered for iface %s\n", dev_name);
676 return IPACM_SUCCESS;
677 }
678
679 /* construct ipa_ioc_add_flt_rule with default filter rules */
680 if (iptype == IPA_IP_v4)
681 {
682 len = sizeof(struct ipa_ioc_add_flt_rule) +
683 (IPV4_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
684
685 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
686 if (!m_pFilteringTable)
687 {
688 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
689 return IPACM_FAILURE;
690 }
691
692 m_pFilteringTable->commit = 1;
693 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
694 m_pFilteringTable->global = false;
695 m_pFilteringTable->ip = iptype;
696 m_pFilteringTable->num_rules = (uint8_t)IPV4_DEFAULT_FILTERTING_RULES;
697
698 /* Configuring Fragment Filtering Rule */
699 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
700
701 flt_rule_entry.rule.retain_hdr = 1;
702 flt_rule_entry.at_rear = true;
703 flt_rule_entry.flt_rule_hdl = -1;
704 flt_rule_entry.status = -1;
705 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
706 #ifdef FEATURE_IPA_V3
707 flt_rule_entry.at_rear = false;
708 flt_rule_entry.rule.hashable = false;
709 #endif
710 IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask);
711 memcpy(&flt_rule_entry.rule.attrib,
712 &rx_prop->rx[0].attrib,
713 sizeof(flt_rule_entry.rule.attrib));
714
715 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT;
716 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
717
718 /* Configuring Multicast Filtering Rule */
719 memcpy(&flt_rule_entry.rule.attrib,
720 &rx_prop->rx[0].attrib,
721 sizeof(flt_rule_entry.rule.attrib));
722 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
723 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xF0000000;
724 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xE0000000;
725 #ifdef FEATURE_IPA_V3
726 flt_rule_entry.at_rear = true;
727 flt_rule_entry.rule.hashable = true;
728 #endif
729 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
730
731 /* Configuring Broadcast Filtering Rule */
732 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
733 flt_rule_entry.rule.attrib.u.v4.dst_addr = 0xFFFFFFFF;
734 #ifdef FEATURE_IPA_V3
735 flt_rule_entry.at_rear = true;
736 flt_rule_entry.rule.hashable = true;
737 #endif
738 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
739
740 if (false == m_filtering.AddFilteringRule(m_pFilteringTable))
741 {
742 IPACMERR("Error Adding Filtering rule, aborting...\n");
743 res = IPACM_FAILURE;
744 goto fail;
745 }
746 else
747 {
748 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES);
749 /* copy filter hdls */
750 for (int i = 0; i < IPV4_DEFAULT_FILTERTING_RULES; i++)
751 {
752 if (m_pFilteringTable->rules[i].status == 0)
753 {
754 dft_v4fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
755 IPACMDBG_H("Default v4 filter Rule %d HDL:0x%x\n", i, dft_v4fl_rule_hdl[i]);
756 }
757 else
758 {
759 IPACMERR("Failed adding default v4 Filtering rule %d\n", i);
760 }
761 }
762 }
763 }
764 else
765 {
766 len = sizeof(struct ipa_ioc_add_flt_rule) +
767 (IPV6_DEFAULT_FILTERTING_RULES * sizeof(struct ipa_flt_rule_add));
768
769 m_pFilteringTable = (struct ipa_ioc_add_flt_rule *)calloc(1, len);
770 if (!m_pFilteringTable)
771 {
772 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
773 return IPACM_FAILURE;
774 }
775
776 m_pFilteringTable->commit = 1;
777 m_pFilteringTable->ep = rx_prop->rx[0].src_pipe;
778 m_pFilteringTable->global = false;
779 m_pFilteringTable->ip = iptype;
780 m_pFilteringTable->num_rules = (uint8_t)IPV6_DEFAULT_FILTERTING_RULES;
781
782 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
783
784 flt_rule_entry.rule.retain_hdr = 1;
785 flt_rule_entry.at_rear = true;
786 flt_rule_entry.flt_rule_hdl = -1;
787 flt_rule_entry.status = -1;
788 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
789 /* Configuring Multicast Filtering Rule */
790 memcpy(&flt_rule_entry.rule.attrib,
791 &rx_prop->rx[0].attrib,
792 sizeof(flt_rule_entry.rule.attrib));
793 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
794 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFF000000;
795 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
796 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
797 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
798 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0XFF000000;
799 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
800 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
801 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
802 #ifdef FEATURE_IPA_V3
803 flt_rule_entry.at_rear = true;
804 flt_rule_entry.rule.hashable = true;
805 #endif
806 memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
807
808 /* Configuring fe80::/10 Link-Scoped Unicast Filtering Rule */
809 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
810 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
811 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
812 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
813 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFE800000;
814 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
815 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
816 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
817 #ifdef FEATURE_IPA_V3
818 flt_rule_entry.at_rear = true;
819 flt_rule_entry.rule.hashable = true;
820 #endif
821 memcpy(&(m_pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
822
823 /* Configuring fec0::/10 Reserved by IETF Filtering Rule */
824 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0XFFC00000;
825 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0x00000000;
826 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x00000000;
827 flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x00000000;
828 flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = 0xFEC00000;
829 flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000;
830 flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
831 flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
832 #ifdef FEATURE_IPA_V3
833 flt_rule_entry.at_rear = true;
834 flt_rule_entry.rule.hashable = true;
835 #endif
836 memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
837
838 #ifdef FEATURE_IPA_ANDROID
839 IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES);
840 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
841
842 flt_rule_entry.at_rear = true;
843 flt_rule_entry.flt_rule_hdl = -1;
844 flt_rule_entry.status = -1;
845
846 flt_rule_entry.rule.retain_hdr = 1;
847 flt_rule_entry.rule.to_uc = 0;
848 flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION;
849 flt_rule_entry.rule.eq_attrib_type = 1;
850 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0;
851
852 if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA)
853 {
854 #ifdef FEATURE_IPA_V3
855 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9);
856 #else
857 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14);
858 #endif
859 flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1;
860 flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0;
861 flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data;
862 flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask;
863 }
864
865 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1);
866 flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1;
867 flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP;
868
869 #ifdef FEATURE_IPA_V3
870 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7);
871 #else
872 flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8);
873 #endif
874 flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1;
875 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12;
876
877 /* add TCP FIN rule*/
878 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT);
879 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT);
880 memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
881
882 /* add TCP SYN rule*/
883 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT);
884 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT);
885 memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
886
887 /* add TCP RST rule*/
888 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT);
889 flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT);
890 memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
891 #endif
892 if (m_filtering.AddFilteringRule(m_pFilteringTable) == false)
893 {
894 IPACMERR("Error Adding Filtering rule, aborting...\n");
895 res = IPACM_FAILURE;
896 goto fail;
897 }
898 else
899 {
900 IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES);
901 /* copy filter hdls */
902 for (int i = 0;
903 i < IPV6_DEFAULT_FILTERTING_RULES;
904 i++)
905 {
906 if (m_pFilteringTable->rules[i].status == 0)
907 {
908 dft_v6fl_rule_hdl[i] = m_pFilteringTable->rules[i].flt_rule_hdl;
909 IPACMDBG_H("Default v6 Filter Rule %d HDL:0x%x\n", i, dft_v6fl_rule_hdl[i]);
910 }
911 else
912 {
913 IPACMERR("Failing adding v6 default IPV6 rule %d\n", i);
914 }
915 }
916 }
917 }
918
919
920 fail:
921 free(m_pFilteringTable);
922
923 return res;
924 }
925
926 /* get ipa interface name */
ipa_get_if_index(char * if_name,int * if_index)927 int IPACM_Iface::ipa_get_if_index
928 (
929 char * if_name,
930 int * if_index
931 )
932 {
933 int fd;
934 struct ifreq ifr;
935
936 if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
937 {
938 IPACMERR("get interface index socket create failed \n");
939 return IPACM_FAILURE;
940 }
941
942 if(strlen(if_name) >= sizeof(ifr.ifr_name))
943 {
944 IPACMERR("interface name overflows: len %zu\n", strlen(if_name));
945 close(fd);
946 return IPACM_FAILURE;
947 }
948
949 memset(&ifr, 0, sizeof(struct ifreq));
950 (void)strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
951 IPACMDBG_H("interface name (%s)\n", if_name);
952
953 if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
954 {
955 IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
956 close(fd);
957 return IPACM_FAILURE;
958 }
959
960 *if_index = ifr.ifr_ifindex;
961 IPACMDBG_H("Interface index %d\n", *if_index);
962 close(fd);
963 return IPACM_SUCCESS;
964 }
965
config_ip_type(ipa_ip_type iptype)966 void IPACM_Iface::config_ip_type(ipa_ip_type iptype)
967 {
968 /* update the iface ip-type to be IPA_IP_v4, IPA_IP_v6 or both*/
969 if (iptype == IPA_IP_v4)
970 {
971 if ((ip_type == IPA_IP_v4) || (ip_type == IPA_IP_MAX))
972 {
973 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
974 return;
975 }
976
977 if (ip_type == IPA_IP_v6)
978 {
979 ip_type = IPA_IP_MAX;
980 }
981 else
982 {
983 ip_type = IPA_IP_v4;
984 }
985 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
986 }
987 else
988 {
989 if ((ip_type == IPA_IP_v6) || (ip_type == IPA_IP_MAX))
990 {
991 IPACMDBG_H(" interface(%s:%d) already in ip-type %d\n", dev_name, ipa_if_num, ip_type);
992 return;
993 }
994
995 if (ip_type == IPA_IP_v4)
996 {
997 ip_type = IPA_IP_MAX;
998 }
999 else
1000 {
1001 ip_type = IPA_IP_v6;
1002 }
1003
1004 IPACMDBG_H(" interface(%s:%d) now ip-type is %d\n", dev_name, ipa_if_num, ip_type);
1005 }
1006
1007 return;
1008 }
1009