1 /*
2 Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 #include "IPACM_Conntrack_NATApp.h"
30 #include "IPACM_ConntrackClient.h"
31 #include "IPACM_ConntrackListener.h"
32 #ifdef FEATURE_IPACM_HAL
33 #include "IPACM_OffloadManager.h"
34 #endif
35 #include "IPACM_Iface.h"
36
37 #define INVALID_IP_ADDR 0x0
38
39 #define HDR_METADATA_MUX_ID_BMASK 0x00FF0000
40 #define HDR_METADATA_MUX_ID_SHFT 0x10
41
42 /* NatApp class Implementation */
43 NatApp *NatApp::pInstance = NULL;
NatApp()44 NatApp::NatApp()
45 {
46 max_entries = 0;
47 cache = NULL;
48
49 nat_table_hdl = 0;
50 pub_ip_addr = 0;
51 pub_mux_id = 0;
52
53 curCnt = 0;
54
55 pALGPorts = NULL;
56 nALGPort = 0;
57
58 ct = NULL;
59 ct_hdl = NULL;
60
61 memset(temp, 0, sizeof(temp));
62 m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR);
63 if(m_fd_ipa < 0)
64 {
65 IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME);
66 }
67 }
68
~NatApp()69 NatApp::~NatApp()
70 {
71 if (m_fd_ipa) {
72 close(m_fd_ipa);
73 }
74 }
75
Init(void)76 int NatApp::Init(void)
77 {
78 IPACM_Config *pConfig;
79 int size = 0;
80
81 pConfig = IPACM_Config::GetInstance();
82 if(pConfig == NULL)
83 {
84 IPACMERR("Unable to get Config instance\n");
85 return -1;
86 }
87
88 max_entries = pConfig->GetNatMaxEntries();
89
90 size = (sizeof(nat_table_entry) * max_entries);
91 cache = (nat_table_entry *)malloc(size);
92 if(cache == NULL)
93 {
94 IPACMERR("Unable to allocate memory for cache\n");
95 goto fail;
96 }
97 IPACMDBG("Allocated %d bytes for config manager nat cache\n", size);
98 memset(cache, 0, size);
99
100 nALGPort = pConfig->GetAlgPortCnt();
101 if(nALGPort > 0)
102 {
103 pALGPorts = (ipacm_alg *)malloc(sizeof(ipacm_alg) * nALGPort);
104 if(pALGPorts == NULL)
105 {
106 IPACMERR("Unable to allocate memory for alg prots\n");
107 goto fail;
108 }
109 memset(pALGPorts, 0, sizeof(ipacm_alg) * nALGPort);
110
111 pConfig->GetAlgPorts(nALGPort, pALGPorts);
112
113 IPACMDBG("Printing %d alg ports information\n", nALGPort);
114 for(int cnt=0; cnt<nALGPort; cnt++)
115 {
116 IPACMDBG("%d: Proto[%d], port[%d]\n", cnt, pALGPorts[cnt].protocol, pALGPorts[cnt].port);
117 }
118 }
119 else
120 {
121 IPACMERR("Unable to retrieve ALG prot count\n");
122 goto fail;
123 }
124
125 return 0;
126
127 fail:
128 if(cache != NULL)
129 {
130 free(cache);
131 }
132 if(pALGPorts != NULL)
133 {
134 free(pALGPorts);
135 }
136 return -1;
137 }
138
GetInstance()139 NatApp* NatApp::GetInstance()
140 {
141 if(pInstance == NULL)
142 {
143 pInstance = new NatApp();
144
145 if(pInstance->Init())
146 {
147 delete pInstance;
148 return NULL;
149 }
150 }
151
152 return pInstance;
153 }
154
GenerateMetdata(uint8_t mux_id)155 uint32_t NatApp::GenerateMetdata(uint8_t mux_id)
156 {
157 return (mux_id << HDR_METADATA_MUX_ID_SHFT) & HDR_METADATA_MUX_ID_BMASK;
158 }
159
160 /* NAT APP related object function definitions */
161
AddTable(uint32_t pub_ip,uint8_t mux_id)162 int NatApp::AddTable(uint32_t pub_ip, uint8_t mux_id)
163 {
164 int ret;
165 int cnt = 0;
166 ipa_nat_ipv4_rule nat_rule;
167 IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__);
168
169 /* Not reset the cache wait it timeout by destroy event */
170 #if 0
171 if (pub_ip != pub_ip_addr_pre)
172 {
173 IPACMDBG("Reset the cache because NAT-ipv4 different\n");
174 memset(cache, 0, sizeof(nat_table_entry) * max_entries);
175 curCnt = 0;
176 }
177 #endif
178 ret = ipa_nat_add_ipv4_tbl(pub_ip, max_entries, &nat_table_hdl);
179 if(ret)
180 {
181 IPACMERR("unable to create nat table Error:%d\n", ret);
182 return ret;
183 }
184 if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_v4_0) {
185 /* modify PDN 0 so it will hold the mux ID in the src metadata field */
186 ipa_nat_pdn_entry entry;
187
188 entry.dst_metadata = 0;
189 entry.src_metadata = GenerateMetdata(mux_id);
190 entry.public_ip = pub_ip;
191 ret = ipa_nat_modify_pdn(nat_table_hdl, 0, &entry);
192 if(ret)
193 {
194 IPACMERR("unable to modify PDN 0 entry Error:%d INIT_HDR_METADATA register values will be used!\n", ret);
195 }
196 }
197
198 /* Add back the cached NAT-entry */
199 if (pub_ip == pub_ip_addr_pre)
200 {
201 IPACMDBG("Restore the cache to ipa NAT-table\n");
202 for(cnt = 0; cnt < max_entries; cnt++)
203 {
204 if(cache[cnt].private_ip !=0)
205 {
206 memset(&nat_rule, 0 , sizeof(nat_rule));
207 nat_rule.private_ip = cache[cnt].private_ip;
208 nat_rule.target_ip = cache[cnt].target_ip;
209 nat_rule.target_port = cache[cnt].target_port;
210 nat_rule.private_port = cache[cnt].private_port;
211 nat_rule.public_port = cache[cnt].public_port;
212 nat_rule.protocol = cache[cnt].protocol;
213
214 if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0)
215 {
216 IPACMERR("unable to add the rule delete from cache\n");
217 memset(&cache[cnt], 0, sizeof(cache[cnt]));
218 curCnt--;
219 continue;
220 }
221 cache[cnt].enabled = true;
222 /* send connections info to pcie modem only with DL direction */
223 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP))
224 {
225 ret = AddConnection(&cache[cnt]);
226 if(ret > 0)
227 {
228 /* save the rule id for deletion */
229 cache[cnt].rule_id = ret;
230 IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id);
231 }
232 else
233 {
234 IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret);
235 cache[cnt].rule_id = 0;
236 }
237 }
238
239 IPACMDBG("On wan-iface reset added below rule successfully\n");
240 iptodot("Private IP", nat_rule.private_ip);
241 iptodot("Target IP", nat_rule.target_ip);
242 IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port);
243 IPACMDBG("Public Port:%d\n", nat_rule.public_port);
244 IPACMDBG("protocol: %d\n", nat_rule.protocol);
245 }
246 }
247 }
248
249 pub_ip_addr = pub_ip;
250 pub_mux_id = mux_id;
251 IPACMDBG(" Set pub_mux_id: %d\t", pub_mux_id);
252 return 0;
253 }
254
Reset()255 void NatApp::Reset()
256 {
257 nat_table_hdl = 0;
258 pub_ip_addr = 0;
259 pub_mux_id = 0;
260 }
261
DeleteTable(uint32_t pub_ip)262 int NatApp::DeleteTable(uint32_t pub_ip)
263 {
264 int cnt = 0;
265 int ret;
266 IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__);
267
268 CHK_TBL_HDL();
269
270 if(pub_ip_addr != pub_ip)
271 {
272 IPACMDBG("Public ip address is not matching\n");
273 IPACMERR("unable to delete the nat table\n");
274 return -1;
275 }
276
277 /* NAT tbl deleted, reset enabled bit */
278 for(cnt = 0; cnt < max_entries; cnt++)
279 {
280 cache[cnt].enabled = false;
281 /* send connections del info to pcie modem first */
282 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0))
283
284 {
285 ret = DelConnection(cache[cnt].rule_id);
286 if(ret)
287 {
288 IPACMERR("unable to del Connection to pcie modem: %d\n", ret);
289 }
290 else
291 {
292 /* save the rule id for deletion */
293 cache[cnt].rule_id = 0;
294 }
295 }
296 }
297
298 ret = ipa_nat_del_ipv4_tbl(nat_table_hdl);
299 if(ret)
300 {
301 IPACMERR("unable to delete nat table Error: %d\n", ret);;
302 return ret;
303 }
304
305 pub_ip_addr_pre = pub_ip_addr;
306 Reset();
307 return 0;
308 }
309
310 /* Check for duplicate entries */
ChkForDup(const nat_table_entry * rule)311 bool NatApp::ChkForDup(const nat_table_entry *rule)
312 {
313 int cnt = 0;
314 IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
315
316 for(; cnt < max_entries; cnt++)
317 {
318 if(cache[cnt].private_ip == rule->private_ip &&
319 cache[cnt].target_ip == rule->target_ip &&
320 cache[cnt].private_port == rule->private_port &&
321 cache[cnt].target_port == rule->target_port &&
322 cache[cnt].protocol == rule->protocol)
323 {
324 log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\
325 rule->target_port,"Duplicate Rule\n");
326 return true;
327 }
328 }
329
330 return false;
331 }
332
333 /* Delete the entry from Nat table on connection close */
DeleteEntry(const nat_table_entry * rule)334 int NatApp::DeleteEntry(const nat_table_entry *rule)
335 {
336 int cnt = 0;
337 int ret = 0;
338 IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
339
340 log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\
341 rule->target_port,"for deletion\n");
342
343
344 for(; cnt < max_entries; cnt++)
345 {
346 if(cache[cnt].private_ip == rule->private_ip &&
347 cache[cnt].target_ip == rule->target_ip &&
348 cache[cnt].private_port == rule->private_port &&
349 cache[cnt].target_port == rule->target_port &&
350 cache[cnt].protocol == rule->protocol)
351 {
352
353 if(cache[cnt].enabled == true)
354 {
355 /* send connections del info to pcie modem first */
356 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0))
357 {
358 ret = DelConnection(cache[cnt].rule_id);
359 if(ret)
360 {
361 IPACMERR("unable to del Connection to pcie modem: %d\n", ret);
362 }
363 else
364 {
365 /* save the rule id for deletion */
366 cache[cnt].rule_id = 0;
367 }
368 }
369
370 if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
371 {
372 IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__);
373 }
374
375 IPACMDBG_H("Deleted Nat entry(%d) Successfully\n", cnt);
376 }
377 else
378 {
379 IPACMDBG_H("Deleted Nat entry(%d) only from cache\n", cnt);
380 }
381
382 memset(&cache[cnt], 0, sizeof(cache[cnt]));
383 curCnt--;
384 break;
385 }
386 }
387
388 return 0;
389 }
390
391 /* Add new entry to the nat table on new connection */
AddEntry(const nat_table_entry * rule)392 int NatApp::AddEntry(const nat_table_entry *rule)
393 {
394 int cnt = 0;
395 ipa_nat_ipv4_rule nat_rule;
396 int ret = 0;
397
398 IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__);
399
400 CHK_TBL_HDL();
401 log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\
402 rule->target_port,"for addition\n");
403 if(isAlgPort(rule->protocol, rule->private_port) ||
404 isAlgPort(rule->protocol, rule->target_port))
405 {
406 IPACMERR("connection using ALG Port, ignore\n");
407 return -1;
408 }
409
410 if(rule->private_ip == 0 ||
411 rule->target_ip == 0 ||
412 rule->private_port == 0 ||
413 rule->target_port == 0 ||
414 rule->protocol == 0)
415 {
416 IPACMERR("Invalid Connection, ignoring it\n");
417 return 0;
418 }
419
420 if(!ChkForDup(rule))
421 {
422 for(; cnt < max_entries; cnt++)
423 {
424 if(cache[cnt].private_ip == 0 &&
425 cache[cnt].target_ip == 0 &&
426 cache[cnt].private_port == 0 &&
427 cache[cnt].target_port == 0 &&
428 cache[cnt].protocol == 0)
429 {
430 break;
431 }
432 }
433
434 if(max_entries == cnt)
435 {
436 IPACMERR("Error: Unable to add, reached maximum rules\n");
437 return -1;
438 }
439 else
440 {
441 memset(&nat_rule, 0, sizeof(nat_rule));
442 nat_rule.private_ip = rule->private_ip;
443 nat_rule.target_ip = rule->target_ip;
444 nat_rule.target_port = rule->target_port;
445 nat_rule.private_port = rule->private_port;
446 nat_rule.public_port = rule->public_port;
447 nat_rule.protocol = rule->protocol;
448
449 if(isPwrSaveIf(rule->private_ip) ||
450 isPwrSaveIf(rule->target_ip))
451 {
452 IPACMDBG("Device is Power Save mode: Dont insert into nat table but cache\n");
453 cache[cnt].enabled = false;
454 cache[cnt].rule_hdl = 0;
455 }
456 else
457 {
458
459 if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0)
460 {
461 IPACMERR("unable to add the rule\n");
462 return -1;
463 }
464
465 cache[cnt].enabled = true;
466 /* send connections info to pcie modem only with DL direction */
467 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (rule->dst_nat == true || rule->protocol == IPPROTO_TCP))
468 {
469 ret = AddConnection(rule);
470 if(ret > 0)
471 {
472 /* save the rule id for deletion */
473 cache[cnt].rule_id = ret;
474 IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id);
475 }
476 else
477 {
478 IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret);
479 cache[cnt].rule_id = 0;
480 }
481 }
482 }
483 cache[cnt].private_ip = rule->private_ip;
484 cache[cnt].target_ip = rule->target_ip;
485 cache[cnt].target_port = rule->target_port;
486 cache[cnt].private_port = rule->private_port;
487 cache[cnt].protocol = rule->protocol;
488 cache[cnt].timestamp = 0;
489 cache[cnt].public_port = rule->public_port;
490 cache[cnt].dst_nat = rule->dst_nat;
491 curCnt++;
492 }
493
494 }
495 else
496 {
497 IPACMERR("Duplicate rule. Ignore it\n");
498 return -1;
499 }
500
501 if(cache[cnt].enabled == true)
502 {
503 IPACMDBG_H("Added rule(%d) successfully\n", cnt);
504 }
505 else
506 {
507 IPACMDBG_H("Cached rule(%d) successfully\n", cnt);
508 }
509
510 return 0;
511 }
512
513 /* Add new entry to the nat table on new connection, return rule-id */
AddConnection(const nat_table_entry * rule)514 int NatApp::AddConnection(const nat_table_entry *rule)
515 {
516 int len, res = IPACM_SUCCESS;
517 ipa_ioc_add_flt_rule *pFilteringTable = NULL;
518
519 /* contruct filter rules to pcie modem */
520 struct ipa_flt_rule_add flt_rule_entry;
521 ipa_ioc_generate_flt_eq flt_eq;
522
523 IPACMDBG("\n");
524 len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add);
525 pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len);
526 if (pFilteringTable == NULL)
527 {
528 IPACMERR("Error Locate ipa_flt_rule_add memory...\n");
529 return IPACM_FAILURE;
530 }
531 memset(pFilteringTable, 0, len);
532
533
534 pFilteringTable->commit = 1;
535 pFilteringTable->global = false;
536 pFilteringTable->ip = IPA_IP_v4;
537 pFilteringTable->num_rules = (uint8_t)1;
538
539 /* Configuring Software-Routing Filtering Rule */
540 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add));
541 flt_rule_entry.at_rear = true;
542 flt_rule_entry.flt_rule_hdl = -1;
543 flt_rule_entry.status = -1;
544
545 flt_rule_entry.rule.retain_hdr = 1;
546 flt_rule_entry.rule.to_uc = 0;
547 flt_rule_entry.rule.eq_attrib_type = 1;
548 flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING;
549 if (IPACM_Iface::ipacmcfg->isIPAv3Supported())
550 flt_rule_entry.rule.hashable = true;
551 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT;
552 flt_rule_entry.rule.attrib.src_port = rule->target_port;
553 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT;
554 flt_rule_entry.rule.attrib.dst_port = rule->public_port;
555 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL;
556 flt_rule_entry.rule.attrib.u.v4.protocol = rule->protocol;
557 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR;
558 flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF;
559 flt_rule_entry.rule.attrib.u.v4.dst_addr = rule->public_ip;
560 flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR;
561 flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF;
562 flt_rule_entry.rule.attrib.u.v4.src_addr = rule->target_ip;
563 IPACMDBG_H("src(0x%x) port(%d)->dst(0x%x) port(%d), protocol(%d) pub_mux_id (%d)\n",
564 rule->target_ip, rule->target_port, rule->public_ip, rule->public_port,
565 rule->protocol, pub_mux_id);
566
567 memset(&flt_eq, 0, sizeof(flt_eq));
568 memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib));
569 flt_eq.ip = IPA_IP_v4;
570 if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq))
571 {
572 IPACMERR("Failed to get eq_attrib\n");
573 res = IPACM_FAILURE;
574 goto fail;
575 }
576 memcpy(&flt_rule_entry.rule.eq_attrib,
577 &flt_eq.eq_attrib,
578 sizeof(flt_rule_entry.rule.eq_attrib));
579 memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add));
580
581 if(false == IPACM_Iface::m_filtering.AddOffloadFilteringRule(pFilteringTable, pub_mux_id, 0))
582 {
583 IPACMERR("Failed to install WAN DL filtering table.\n");
584 res = IPACM_FAILURE;
585 goto fail;
586 }
587
588 /* get rule-id */
589 res = pFilteringTable->rules[0].flt_rule_hdl;
590
591 fail:
592 if(pFilteringTable != NULL)
593 {
594 free(pFilteringTable);
595 }
596 return res;
597 }
598
DelConnection(const uint32_t rule_id)599 int NatApp::DelConnection(const uint32_t rule_id)
600 {
601 int len, res = IPACM_SUCCESS;
602 ipa_ioc_del_flt_rule *pFilteringTable = NULL;
603
604
605 struct ipa_flt_rule_del flt_rule_entry;
606
607 IPACMDBG("\n");
608 len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del);
609 pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len);
610 if (pFilteringTable == NULL)
611 {
612 IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n");
613 return IPACM_FAILURE;
614 }
615 memset(pFilteringTable, 0, len);
616
617
618 pFilteringTable->commit = 1;
619 pFilteringTable->ip = IPA_IP_v4;
620 pFilteringTable->num_hdls = (uint8_t)1;
621
622 /* Configuring Software-Routing Filtering Rule */
623 memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del));
624 flt_rule_entry.hdl = rule_id;
625
626 memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del));
627
628 if(false == IPACM_Iface::m_filtering.DelOffloadFilteringRule(pFilteringTable))
629 {
630 IPACMERR("Failed to install WAN DL filtering table.\n");
631 res = IPACM_FAILURE;
632 goto fail;
633 }
634
635 fail:
636 if(pFilteringTable != NULL)
637 {
638 free(pFilteringTable);
639 }
640 return res;
641 }
642
UpdateCTUdpTs(nat_table_entry * rule,uint32_t new_ts)643 void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts)
644 {
645 #ifdef FEATURE_IPACM_HAL
646 IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t entry;
647 IPACM_OffloadManager* OffloadMng;
648 #endif
649 iptodot("Private IP:", rule->private_ip);
650 iptodot("Target IP:", rule->target_ip);
651 IPACMDBG("Private Port: %d, Target Port: %d\n", rule->private_port, rule->target_port);
652
653 #ifndef FEATURE_IPACM_HAL
654 int ret;
655 if(!ct_hdl)
656 {
657 ct_hdl = nfct_open(CONNTRACK, 0);
658 if(!ct_hdl)
659 {
660 PERROR("nfct_open");
661 return;
662 }
663 }
664
665 if(!ct)
666 {
667 ct = nfct_new();
668 if(!ct)
669 {
670 PERROR("nfct_new");
671 return;
672 }
673 }
674
675 nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
676 if(rule->protocol == IPPROTO_UDP)
677 {
678 nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol);
679 nfct_set_attr_u32(ct, ATTR_TIMEOUT, udp_timeout);
680 }
681 else
682 {
683 nfct_set_attr_u8(ct, ATTR_L4PROTO, rule->protocol);
684 nfct_set_attr_u32(ct, ATTR_TIMEOUT, tcp_timeout);
685 }
686
687 if(rule->dst_nat == false)
688 {
689 nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->private_ip));
690 nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->private_port));
691
692 nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(rule->target_ip));
693 nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->target_port));
694
695 IPACMDBG("dst nat is not set\n");
696 }
697 else
698 {
699 nfct_set_attr_u32(ct, ATTR_IPV4_SRC, htonl(rule->target_ip));
700 nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(rule->target_port));
701
702 nfct_set_attr_u32(ct, ATTR_IPV4_DST, htonl(pub_ip_addr));
703 nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(rule->public_port));
704
705 IPACMDBG("dst nat is set\n");
706 }
707
708 iptodot("Source IP:", nfct_get_attr_u32(ct, ATTR_IPV4_SRC));
709 iptodot("Destination IP:", nfct_get_attr_u32(ct, ATTR_IPV4_DST));
710 IPACMDBG("Source Port: %d, Destination Port: %d\n",
711 nfct_get_attr_u16(ct, ATTR_PORT_SRC), nfct_get_attr_u16(ct, ATTR_PORT_DST));
712
713 IPACMDBG("updating %d connection with time: %d\n",
714 rule->protocol, nfct_get_attr_u32(ct, ATTR_TIMEOUT));
715
716 ret = nfct_query(ct_hdl, NFCT_Q_UPDATE, ct);
717 if(ret == -1)
718 {
719 IPACMERR("unable to update time stamp");
720 DeleteEntry(rule);
721 }
722 else
723 {
724 rule->timestamp = new_ts;
725 IPACMDBG("Updated time stamp successfully\n");
726 }
727 #else
728 if(rule->protocol == IPPROTO_UDP)
729 {
730 entry.proto = IOffloadManager::ConntrackTimeoutUpdater::UDP;;
731 }
732 else
733 {
734 entry.proto = IOffloadManager::ConntrackTimeoutUpdater::TCP;
735 }
736
737 if(rule->dst_nat == false)
738 {
739 entry.src.ipAddr = htonl(rule->private_ip);
740 entry.src.port = rule->private_port;
741 entry.dst.ipAddr = htonl(rule->target_ip);
742 entry.dst.port = rule->target_port;
743 IPACMDBG("dst nat is not set\n");
744 }
745 else
746 {
747 entry.src.ipAddr = htonl(rule->target_ip);
748 entry.src.port = rule->target_port;
749 entry.dst.ipAddr = htonl(pub_ip_addr);
750 entry.dst.port = rule->public_port;
751 IPACMDBG("dst nat is set\n");
752 }
753
754 iptodot("Source IP:", entry.src.ipAddr);
755 iptodot("Destination IP:", entry.dst.ipAddr);
756 IPACMDBG("Source Port: %d, Destination Port: %d\n",
757 entry.src.port, entry.dst.port);
758
759 OffloadMng = IPACM_OffloadManager::GetInstance();
760 if (OffloadMng->touInstance == NULL) {
761 IPACMERR("OffloadMng->touInstance is NULL, can't forward to framework!\n");
762 } else {
763 OffloadMng->touInstance->updateTimeout(entry);
764 IPACMDBG("Updated time stamp successfully\n");
765 rule->timestamp = new_ts;
766 }
767 #endif
768 return;
769 }
770
UpdateUDPTimeStamp()771 void NatApp::UpdateUDPTimeStamp()
772 {
773 int cnt;
774 uint32_t ts;
775 bool read_to = false;
776
777 for(cnt = 0; cnt < max_entries; cnt++)
778 {
779 ts = 0;
780 if(cache[cnt].enabled == true &&
781 (cache[cnt].private_ip != cache[cnt].public_ip))
782 {
783 IPACMDBG("\n");
784 if(ipa_nat_query_timestamp(nat_table_hdl, cache[cnt].rule_hdl, &ts) < 0)
785 {
786 IPACMERR("unable to retrieve timeout for rule hanle: %d\n", cache[cnt].rule_hdl);
787 continue;
788 }
789
790 if(cache[cnt].timestamp == ts)
791 {
792 IPACMDBG("No Change in Time Stamp: cahce:%d, ipahw:%d\n",
793 cache[cnt].timestamp, ts);
794 continue;
795 }
796
797 if (read_to == false) {
798 read_to = true;
799 Read_TcpUdp_Timeout();
800 }
801
802 UpdateCTUdpTs(&cache[cnt], ts);
803 } /* end of outer if */
804
805 } /* end of for loop */
806
807 }
808
isAlgPort(uint8_t proto,uint16_t port)809 bool NatApp::isAlgPort(uint8_t proto, uint16_t port)
810 {
811 int cnt;
812 for(cnt = 0; cnt < nALGPort; cnt++)
813 {
814 if(proto == pALGPorts[cnt].protocol &&
815 port == pALGPorts[cnt].port)
816 {
817 return true;
818 }
819 }
820
821 return false;
822 }
823
isPwrSaveIf(uint32_t ip_addr)824 bool NatApp::isPwrSaveIf(uint32_t ip_addr)
825 {
826 int cnt;
827
828 for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
829 {
830 if(0 != PwrSaveIfs[cnt] &&
831 ip_addr == PwrSaveIfs[cnt])
832 {
833 return true;
834 }
835 }
836
837 return false;
838 }
839
UpdatePwrSaveIf(uint32_t client_lan_ip)840 int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip)
841 {
842 int cnt, ret;
843 IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip);
844
845 if(client_lan_ip == INVALID_IP_ADDR)
846 {
847 IPACMERR("Invalid ip address received\n");
848 return -1;
849 }
850
851 /* check for duplicate events */
852 for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
853 {
854 if(PwrSaveIfs[cnt] == client_lan_ip)
855 {
856 IPACMDBG("The client 0x%x is already in power save\n", client_lan_ip);
857 return 0;
858 }
859 }
860
861 for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
862 {
863 if(PwrSaveIfs[cnt] == 0)
864 {
865 PwrSaveIfs[cnt] = client_lan_ip;
866 break;
867 }
868 }
869
870 for(cnt = 0; cnt < max_entries; cnt++)
871 {
872 if(cache[cnt].private_ip == client_lan_ip &&
873 cache[cnt].enabled == true)
874 {
875 /* send connections del info to pcie modem first */
876 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0))
877 {
878 ret = DelConnection(cache[cnt].rule_id);
879 if(ret)
880 {
881 IPACMERR("unable to del Connection to pcie modem: %d\n", ret);
882 }
883 else
884 {
885 /* save the rule id for deletion */
886 cache[cnt].rule_id = 0;
887 }
888 }
889
890 if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
891 {
892 IPACMERR("unable to delete the rule\n");
893 continue;
894 }
895
896 cache[cnt].enabled = false;
897 cache[cnt].rule_hdl = 0;
898 }
899 }
900
901 return 0;
902 }
903
ResetPwrSaveIf(uint32_t client_lan_ip)904 int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip)
905 {
906 int cnt, ret;
907 ipa_nat_ipv4_rule nat_rule;
908
909 IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip);
910
911 if(client_lan_ip == INVALID_IP_ADDR)
912 {
913 IPACMERR("Invalid ip address received\n");
914 return -1;
915 }
916
917 for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
918 {
919 if(PwrSaveIfs[cnt] == client_lan_ip)
920 {
921 PwrSaveIfs[cnt] = 0;
922 break;
923 }
924 }
925
926 for(cnt = 0; cnt < max_entries; cnt++)
927 {
928 IPACMDBG("cache (%d): enable %d, ip 0x%x\n", cnt, cache[cnt].enabled, cache[cnt].private_ip);
929
930 if(cache[cnt].private_ip == client_lan_ip &&
931 cache[cnt].enabled == false)
932 {
933 memset(&nat_rule, 0 , sizeof(nat_rule));
934 nat_rule.private_ip = cache[cnt].private_ip;
935 nat_rule.target_ip = cache[cnt].target_ip;
936 nat_rule.target_port = cache[cnt].target_port;
937 nat_rule.private_port = cache[cnt].private_port;
938 nat_rule.public_port = cache[cnt].public_port;
939 nat_rule.protocol = cache[cnt].protocol;
940
941 if(ipa_nat_add_ipv4_rule(nat_table_hdl, &nat_rule, &cache[cnt].rule_hdl) < 0)
942 {
943 IPACMERR("unable to add the rule delete from cache\n");
944 memset(&cache[cnt], 0, sizeof(cache[cnt]));
945 curCnt--;
946 continue;
947 }
948 cache[cnt].enabled = true;
949 /* send connections info to pcie modem only with DL direction */
950 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP))
951 {
952 ret = AddConnection(&cache[cnt]);
953 if(ret > 0)
954 {
955 /* save the rule id for deletion */
956 cache[cnt].rule_id = ret;
957 IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id);
958 }
959 else
960 {
961 IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret);
962 cache[cnt].rule_id = 0;
963 }
964 }
965
966 IPACMDBG("On power reset added below rule successfully\n");
967 iptodot("Private IP", nat_rule.private_ip);
968 iptodot("Target IP", nat_rule.target_ip);
969 IPACMDBG("Private Port:%d \t Target Port: %d\t", nat_rule.private_port, nat_rule.target_port);
970 IPACMDBG("Public Port:%d\n", nat_rule.public_port);
971 IPACMDBG("protocol: %d\n", nat_rule.protocol);
972
973 }
974 }
975
976 return -1;
977 }
978
GetTableHdl(uint32_t in_ip_addr)979 uint32_t NatApp::GetTableHdl(uint32_t in_ip_addr)
980 {
981 if(in_ip_addr == pub_ip_addr)
982 {
983 return nat_table_hdl;
984 }
985
986 return -1;
987 }
988
AddTempEntry(const nat_table_entry * new_entry)989 void NatApp::AddTempEntry(const nat_table_entry *new_entry)
990 {
991 int cnt;
992
993 IPACMDBG("Received below Temp Nat entry\n");
994 iptodot("Private IP", new_entry->private_ip);
995 iptodot("Target IP", new_entry->target_ip);
996 IPACMDBG("Private Port: %d\t Target Port: %d\t", new_entry->private_port, new_entry->target_port);
997 IPACMDBG("protocolcol: %d\n", new_entry->protocol);
998
999 if(isAlgPort(new_entry->protocol, new_entry->private_port) ||
1000 isAlgPort(new_entry->protocol, new_entry->target_port))
1001 {
1002 IPACMDBG("connection using ALG Port. Dont insert into nat cache\n");
1003 return;
1004 }
1005
1006 if(ChkForDup(new_entry))
1007 {
1008 return;
1009 }
1010
1011 for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++)
1012 {
1013 if(temp[cnt].private_ip == new_entry->private_ip &&
1014 temp[cnt].target_ip == new_entry->target_ip &&
1015 temp[cnt].private_port == new_entry->private_port &&
1016 temp[cnt].target_port == new_entry->target_port &&
1017 temp[cnt].protocol == new_entry->protocol)
1018 {
1019 IPACMDBG("Received duplicate Temp entry\n");
1020 return;
1021 }
1022 }
1023
1024 for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++)
1025 {
1026 if(temp[cnt].private_ip == 0 &&
1027 temp[cnt].target_ip == 0)
1028 {
1029 memcpy(&temp[cnt], new_entry, sizeof(nat_table_entry));
1030 IPACMDBG("Added Temp Entry\n");
1031 return;
1032 }
1033 }
1034
1035 IPACMDBG("Unable to add temp entry, cache full\n");
1036 return;
1037 }
1038
DeleteTempEntry(const nat_table_entry * entry)1039 void NatApp::DeleteTempEntry(const nat_table_entry *entry)
1040 {
1041 int cnt;
1042
1043 IPACMDBG("Received below nat entry\n");
1044 iptodot("Private IP", entry->private_ip);
1045 iptodot("Target IP", entry->target_ip);
1046 IPACMDBG("Private Port: %d\t Target Port: %d\n", entry->private_port, entry->target_port);
1047 IPACMDBG("protocol: %d\n", entry->protocol);
1048
1049 for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++)
1050 {
1051 if(temp[cnt].private_ip == entry->private_ip &&
1052 temp[cnt].target_ip == entry->target_ip &&
1053 temp[cnt].private_port == entry->private_port &&
1054 temp[cnt].target_port == entry->target_port &&
1055 temp[cnt].protocol == entry->protocol)
1056 {
1057 memset(&temp[cnt], 0, sizeof(nat_table_entry));
1058 IPACMDBG("Delete Temp Entry\n");
1059 return;
1060 }
1061 }
1062
1063 IPACMDBG("No Such Temp Entry exists\n");
1064 return;
1065 }
1066
FlushTempEntries(uint32_t ip_addr,bool isAdd,bool isDummy)1067 void NatApp::FlushTempEntries(uint32_t ip_addr, bool isAdd,
1068 bool isDummy)
1069 {
1070 int cnt;
1071 int ret;
1072
1073 IPACMDBG_H("Received below with isAdd:%d ", isAdd);
1074 iptodot("IP Address: ", ip_addr);
1075
1076 for(cnt=0; cnt<MAX_TEMP_ENTRIES; cnt++)
1077 {
1078 if(temp[cnt].private_ip == ip_addr ||
1079 temp[cnt].target_ip == ip_addr)
1080 {
1081 if(isAdd)
1082 {
1083 if(temp[cnt].public_ip == pub_ip_addr)
1084 {
1085 if (isDummy) {
1086 /* To avoild DL expections for non IPA path */
1087 temp[cnt].private_ip = temp[cnt].public_ip;
1088 temp[cnt].private_port = temp[cnt].public_port;
1089 IPACMDBG("Flushing dummy temp rule");
1090 iptodot("Private IP", temp[cnt].private_ip);
1091 }
1092
1093 ret = AddEntry(&temp[cnt]);
1094 if(ret)
1095 {
1096 IPACMERR("unable to add temp entry: %d\n", ret);
1097 continue;
1098 }
1099 }
1100 }
1101 memset(&temp[cnt], 0, sizeof(nat_table_entry));
1102 }
1103 }
1104
1105 return;
1106 }
1107
DelEntriesOnClntDiscon(uint32_t ip_addr)1108 int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr)
1109 {
1110 int cnt, tmp = 0, ret;
1111 IPACMDBG_H("Received IP address: 0x%x\n", ip_addr);
1112
1113 if(ip_addr == INVALID_IP_ADDR)
1114 {
1115 IPACMERR("Invalid ip address received\n");
1116 return -1;
1117 }
1118
1119 for(cnt = 0; cnt < IPA_MAX_NUM_WIFI_CLIENTS; cnt++)
1120 {
1121 if(PwrSaveIfs[cnt] == ip_addr)
1122 {
1123 PwrSaveIfs[cnt] = 0;
1124 IPACMDBG("Remove %d power save entry\n", cnt);
1125 break;
1126 }
1127 }
1128
1129 for(cnt = 0; cnt < max_entries; cnt++)
1130 {
1131 if(cache[cnt].private_ip == ip_addr)
1132 {
1133 if(cache[cnt].enabled == true)
1134 {
1135 /* send connections del info to pcie modem first */
1136 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0))
1137 {
1138 ret = DelConnection(cache[cnt].rule_id);
1139 if(ret)
1140 {
1141 IPACMERR("unable to del Connection to pcie modem: %d\n", ret);
1142 }
1143 else
1144 {
1145 /* save the rule id for deletion */
1146 cache[cnt].rule_id = 0;
1147 }
1148 }
1149
1150 if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
1151 {
1152 IPACMERR("unable to delete the rule\n");
1153 continue;
1154 }
1155 else
1156 {
1157 IPACMDBG("won't delete the rule\n");
1158 cache[cnt].enabled = false;
1159 tmp++;
1160 }
1161 }
1162 IPACMDBG("won't delete the rule for entry %d, enabled %d\n",cnt, cache[cnt].enabled);
1163 }
1164 }
1165
1166 IPACMDBG("Deleted (but cached) %d entries\n", tmp);
1167 return 0;
1168 }
1169
DelEntriesOnSTAClntDiscon(uint32_t ip_addr)1170 int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr)
1171 {
1172 int cnt, tmp = curCnt, ret;
1173 IPACMDBG_H("Received IP address: 0x%x\n", ip_addr);
1174
1175 if(ip_addr == INVALID_IP_ADDR)
1176 {
1177 IPACMERR("Invalid ip address received\n");
1178 return -1;
1179 }
1180
1181
1182 for(cnt = 0; cnt < max_entries; cnt++)
1183 {
1184 if(cache[cnt].target_ip == ip_addr)
1185 {
1186 if(cache[cnt].enabled == true)
1187 {
1188 /* send connections del info to pcie modem first */
1189 if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0))
1190 {
1191 ret = DelConnection(cache[cnt].rule_id);
1192 if(ret)
1193 {
1194 IPACMERR("unable to del Connection to pcie modem: %d\n", ret);
1195 }
1196 else
1197 {
1198 /* save the rule id for deletion */
1199 cache[cnt].rule_id = 0;
1200 }
1201 }
1202
1203 if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0)
1204 {
1205 IPACMERR("unable to delete the rule\n");
1206 continue;
1207 }
1208 }
1209
1210 memset(&cache[cnt], 0, sizeof(cache[cnt]));
1211 curCnt--;
1212 }
1213 }
1214
1215 IPACMDBG("Deleted %d entries\n", (tmp - curCnt));
1216 return 0;
1217 }
1218
CacheEntry(const nat_table_entry * rule)1219 void NatApp::CacheEntry(const nat_table_entry *rule)
1220 {
1221 int cnt;
1222
1223 if(rule->private_ip == 0 ||
1224 rule->target_ip == 0 ||
1225 rule->private_port == 0 ||
1226 rule->target_port == 0 ||
1227 rule->protocol == 0)
1228 {
1229 IPACMERR("Invalid Connection, ignoring it\n");
1230 return;
1231 }
1232
1233 if(!ChkForDup(rule))
1234 {
1235 for(cnt=0; cnt < max_entries; cnt++)
1236 {
1237 if(cache[cnt].private_ip == 0 &&
1238 cache[cnt].target_ip == 0 &&
1239 cache[cnt].private_port == 0 &&
1240 cache[cnt].target_port == 0 &&
1241 cache[cnt].protocol == 0)
1242 {
1243 break;
1244 }
1245 }
1246
1247 if(max_entries == cnt)
1248 {
1249 IPACMERR("Error: Unable to add, reached maximum rules\n");
1250 return;
1251 }
1252 else
1253 {
1254 cache[cnt].enabled = false;
1255 cache[cnt].rule_hdl = 0;
1256 cache[cnt].private_ip = rule->private_ip;
1257 cache[cnt].target_ip = rule->target_ip;
1258 cache[cnt].target_port = rule->target_port;
1259 cache[cnt].private_port = rule->private_port;
1260 cache[cnt].protocol = rule->protocol;
1261 cache[cnt].timestamp = 0;
1262 cache[cnt].public_port = rule->public_port;
1263 cache[cnt].public_ip = rule->public_ip;
1264 cache[cnt].dst_nat = rule->dst_nat;
1265 curCnt++;
1266 }
1267
1268 }
1269 else
1270 {
1271 IPACMERR("Duplicate rule. Ignore it\n");
1272 return;
1273 }
1274
1275 IPACMDBG("Cached rule(%d) successfully\n", cnt);
1276 return;
1277 }
1278
Read_TcpUdp_Timeout(void)1279 void NatApp::Read_TcpUdp_Timeout(void) {
1280 #ifdef FEATURE_IPACM_HAL
1281 tcp_timeout = 432000;
1282 udp_timeout = 180;
1283 IPACMDBG_H("udp timeout value: %d\n", udp_timeout);
1284 IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout);
1285 #else
1286 FILE *udp_fd = NULL, *tcp_fd = NULL;
1287 /* Read UDP timeout value */
1288 udp_fd = fopen(IPACM_UDP_FULL_FILE_NAME, "r");
1289 if (udp_fd == NULL) {
1290 IPACMERR("unable to open %s\n", IPACM_UDP_FULL_FILE_NAME);
1291 goto fail;
1292 }
1293
1294 if (fscanf(udp_fd, "%d", &udp_timeout) != 1) {
1295 IPACMERR("Error reading udp timeout\n");
1296 }
1297 IPACMDBG_H("udp timeout value: %d\n", udp_timeout);
1298
1299
1300 /* Read TCP timeout value */
1301 tcp_fd = fopen(IPACM_TCP_FULL_FILE_NAME, "r");
1302 if (tcp_fd == NULL) {
1303 IPACMERR("unable to open %s\n", IPACM_TCP_FULL_FILE_NAME);
1304 goto fail;
1305 }
1306
1307
1308 if (fscanf(tcp_fd, "%d", &tcp_timeout) != 1) {
1309 IPACMERR("Error reading tcp timeout\n");
1310 }
1311 IPACMDBG_H("tcp timeout value: %d\n", tcp_timeout);
1312
1313 fail:
1314 if (udp_fd) {
1315 fclose(udp_fd);
1316 }
1317 if (tcp_fd) {
1318 fclose(tcp_fd);
1319 }
1320 #endif
1321 return;
1322 }
1323