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