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.
28 */
29
30 #include <sys/ioctl.h>
31 #include <net/if.h>
32
33 #include "IPACM_ConntrackListener.h"
34 #include "IPACM_ConntrackClient.h"
35 #include "IPACM_EvtDispatcher.h"
36 #include "IPACM_Iface.h"
37 #include "IPACM_Wan.h"
38 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
39
IPACM_ConntrackListener()40 IPACM_ConntrackListener::IPACM_ConntrackListener()
41 {
42 IPACMDBG("\n");
43 isNatThreadStart = false;
44 isCTReg = false;
45 WanUp = false;
46 isReadCTDone = false;
47 isProcessCTDone = false;
48 nat_inst = NatApp::GetInstance();
49
50 NatIfaceCnt = 0;
51 StaClntCnt = 0;
52 pNatIfaces = NULL;
53 ct_entries = NULL;
54 pConfig = IPACM_Config::GetInstance();;
55
56 memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
57 memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
58 memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr));
59
60 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
61 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
62 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this);
63 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
64 IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
65 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
66 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
67 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
68
69 #ifdef CT_OPT
70 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
71 #endif
72
73 /* Initialize the CT cache. */
74 memset(ct_cache, 0, sizeof(ct_cache));
75 }
76
event_callback(ipa_cm_event_id evt,void * data)77 void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
78 void *data)
79 {
80 ipacm_event_iface_up *wan_down = NULL;
81
82 if(data == NULL)
83 {
84 IPACMERR("Invalid Data\n");
85 return;
86 }
87
88 switch(evt)
89 {
90 case IPA_PROCESS_CT_MESSAGE:
91 IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n");
92 ProcessCTMessage(data);
93 break;
94
95 #ifdef CT_OPT
96 case IPA_PROCESS_CT_MESSAGE_V6:
97 IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n");
98 ProcessCTV6Message(data);
99 break;
100 #endif
101
102 case IPA_HANDLE_WAN_UP:
103 IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
104 CreateConnTrackThreads();
105 TriggerWANUp(data);
106 if(isReadCTDone && !isProcessCTDone)
107 {
108 processConntrack();
109 }
110 /* Process the cached entries. */
111 processCacheConntrack();
112 break;
113
114 case IPA_HANDLE_WAN_DOWN:
115 IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
116 wan_down = (ipacm_event_iface_up *)data;
117 if(isWanUp())
118 {
119 TriggerWANDown(wan_down->ipv4_addr);
120 }
121 break;
122
123 /* if wlan or lan comes up after wan interface, modify
124 tcp/udp filters to ignore local wlan or lan connections */
125 case IPA_HANDLE_WLAN_UP:
126 case IPA_HANDLE_LAN_UP:
127 IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n",
128 evt, ((ipacm_event_iface_up *)data)->ifname,
129 ((ipacm_event_iface_up *)data)->ipv4_addr);
130 if(isWanUp())
131 {
132 CreateConnTrackThreads();
133 IPACM_ConntrackClient::UpdateUDPFilters(data, false);
134 IPACM_ConntrackClient::UpdateTCPFilters(data, false);
135 }
136 break;
137
138 case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
139 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
140 HandleNonNatIPAddr(data, true);
141 break;
142
143 case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
144 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
145 HandleNonNatIPAddr(data, false);
146 break;
147
148 default:
149 IPACMDBG("Ignore cmd %d\n", evt);
150 break;
151 }
152 }
153
CheckNatIface(ipacm_event_data_all * data,bool * NatIface)154 int IPACM_ConntrackListener::CheckNatIface(
155 ipacm_event_data_all *data, bool *NatIface)
156 {
157 int fd = 0, len = 0, cnt, i;
158 struct ifreq ifr;
159 *NatIface = false;
160
161 if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
162 {
163 IPACMDBG("Ignoring\n");
164 return IPACM_FAILURE;
165 }
166
167 IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
168 iptodot(" and ipv4 address", data->ipv4_addr);
169
170 if (pConfig == NULL)
171 {
172 pConfig = IPACM_Config::GetInstance();
173 if (pConfig == NULL)
174 {
175 IPACMERR("Unable to get Config instance\n");
176 return IPACM_FAILURE;
177 }
178 }
179
180 cnt = pConfig->GetNatIfacesCnt();
181 NatIfaceCnt = cnt;
182 IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt);
183 if (pNatIfaces != NULL)
184 {
185 free(pNatIfaces);
186 pNatIfaces = NULL;
187 }
188
189 len = (sizeof(NatIfaces) * NatIfaceCnt);
190 pNatIfaces = (NatIfaces *)malloc(len);
191 if (pNatIfaces == NULL)
192 {
193 IPACMERR("Unable to allocate memory for non nat ifaces\n");
194 return IPACM_FAILURE;
195 }
196
197 memset(pNatIfaces, 0, len);
198 if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
199 {
200 IPACMERR("Unable to retrieve non nat ifaces\n");
201 return IPACM_FAILURE;
202 }
203
204 /* Search/Configure linux interface-index and map it to IPA interface-index */
205 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
206 {
207 PERROR("get interface name socket create failed");
208 return IPACM_FAILURE;
209 }
210
211 memset(&ifr, 0, sizeof(struct ifreq));
212 ifr.ifr_ifindex = data->if_index;
213 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
214 {
215 PERROR("call_ioctl_on_dev: ioctl failed:");
216 close(fd);
217 return IPACM_FAILURE;
218 }
219 close(fd);
220
221 for (i = 0; i < NatIfaceCnt; i++)
222 {
223 if (strncmp(ifr.ifr_name,
224 pNatIfaces[i].iface_name,
225 sizeof(pNatIfaces[i].iface_name)) == 0)
226 {
227 IPACMDBG_H("Nat iface (%s), entry (%d), dont cache",
228 pNatIfaces[i].iface_name, i);
229 iptodot("with ipv4 address: ", nat_iface_ipv4_addr[i]);
230 *NatIface = true;
231 return IPACM_SUCCESS;
232 }
233 }
234
235 return IPACM_SUCCESS;
236 }
237
HandleNonNatIPAddr(void * inParam,bool AddOp)238 void IPACM_ConntrackListener::HandleNonNatIPAddr(
239 void *inParam, bool AddOp)
240 {
241 ipacm_event_data_all *data = (ipacm_event_data_all *)inParam;
242 bool NatIface = false;
243 int cnt, ret;
244
245 if (backhaul_mode != Q6_WAN)
246 {
247 IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n");
248 return;
249 }
250
251 /* Handle only non nat ifaces, NAT iface should be handle
252 separately to avoid race conditions between route/nat
253 rules add/delete operations */
254 if (AddOp)
255 {
256 ret = CheckNatIface(data, &NatIface);
257 if (!NatIface && ret == IPACM_SUCCESS)
258 {
259 /* Cache the non nat iface ip address */
260 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
261 {
262 if (nonnat_iface_ipv4_addr[cnt] == 0)
263 {
264 nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr;
265 IPACMDBG("Add ip addr to non nat list (%d) ", cnt);
266 iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
267
268 /* Add dummy nat rule for non nat ifaces */
269 nat_inst->FlushTempEntries(data->ipv4_addr, true, true);
270 return;
271 }
272 }
273 }
274 }
275 else
276 {
277 /* for delete operation */
278 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
279 {
280 if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
281 {
282 IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
283 iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
284 nonnat_iface_ipv4_addr[cnt] = 0;
285 nat_inst->FlushTempEntries(data->ipv4_addr, false);
286 nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr);
287 return;
288 }
289 }
290
291 }
292
293 return;
294 }
295
HandleNeighIpAddrAddEvt(ipacm_event_data_all * data)296 void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(
297 ipacm_event_data_all *data)
298 {
299 bool NatIface = false;
300 int j, ret;
301
302 ret = CheckNatIface(data, &NatIface);
303 if (NatIface && ret == IPACM_SUCCESS)
304 {
305 for (j = 0; j < MAX_IFACE_ADDRESS; j++)
306 {
307 /* check if duplicate NAT ip */
308 if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
309 break;
310
311 /* Cache the new nat iface address */
312 if (nat_iface_ipv4_addr[j] == 0)
313 {
314 nat_iface_ipv4_addr[j] = data->ipv4_addr;
315 iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]);
316 break;
317 }
318 }
319
320 /* Add the cached temp entries to NAT table */
321 if (j != MAX_IFACE_ADDRESS)
322 {
323 nat_inst->ResetPwrSaveIf(data->ipv4_addr);
324 nat_inst->FlushTempEntries(data->ipv4_addr, true);
325 }
326 }
327 return;
328 }
329
HandleNeighIpAddrDelEvt(uint32_t ipv4_addr)330 void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(
331 uint32_t ipv4_addr)
332 {
333 int cnt;
334
335 if(ipv4_addr == 0)
336 {
337 IPACMDBG("Ignoring\n");
338 return;
339 }
340
341 iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr);
342 for(cnt = 0; cnt<MAX_IFACE_ADDRESS; cnt++)
343 {
344 if (nat_iface_ipv4_addr[cnt] == ipv4_addr)
345 {
346 IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
347 iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
348 nat_iface_ipv4_addr[cnt] = 0;
349 nat_inst->FlushTempEntries(ipv4_addr, false);
350 nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
351 }
352 }
353
354 return;
355 }
356
TriggerWANUp(void * in_param)357 void IPACM_ConntrackListener::TriggerWANUp(void *in_param)
358 {
359 ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param;
360 uint8_t mux_id;
361
362 IPACMDBG_H("Recevied below information during wanup,\n");
363 IPACMDBG_H("if_name:%s, ipv4_address:0x%x mux_id:%d, xlat_mux_id:%d\n",
364 wanup_data->ifname, wanup_data->ipv4_addr,
365 wanup_data->mux_id,
366 wanup_data->xlat_mux_id);
367
368 if(wanup_data->ipv4_addr == 0)
369 {
370 IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n");
371 return;
372 }
373
374 if(isWanUp())
375 {
376 if (wan_ipaddr != wanup_data->ipv4_addr)
377 TriggerWANDown(wan_ipaddr);
378 else
379 return;
380 }
381
382 WanUp = true;
383 backhaul_mode = wanup_data->backhaul_type;
384 IPACMDBG("backhaul_mode: %d\n", backhaul_mode);
385
386 wan_ipaddr = wanup_data->ipv4_addr;
387 memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname));
388
389 if(nat_inst != NULL)
390 {
391 if (wanup_data->mux_id == 0)
392 mux_id = wanup_data->xlat_mux_id;
393 else
394 mux_id = wanup_data->mux_id;
395 nat_inst->AddTable(wanup_data->ipv4_addr, mux_id);
396 }
397
398 IPACMDBG("creating nat threads\n");
399 CreateNatThreads();
400 }
401
CreateConnTrackThreads(void)402 int IPACM_ConntrackListener::CreateConnTrackThreads(void)
403 {
404 int ret;
405 pthread_t tcp_thread = 0, udp_thread = 0;
406
407 if(isCTReg == false)
408 {
409 ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL);
410 if(0 != ret)
411 {
412 IPACMERR("unable to create TCP conntrack event listner thread\n");
413 PERROR("unable to create TCP conntrack\n");
414 goto error;
415 }
416
417 IPACMDBG("created TCP conntrack event listner thread\n");
418 if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0)
419 {
420 IPACMERR("unable to set thread name\n");
421 }
422
423 ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL);
424 if(0 != ret)
425 {
426 IPACMERR("unable to create UDP conntrack event listner thread\n");
427 PERROR("unable to create UDP conntrack\n");
428 goto error;
429 }
430
431 IPACMDBG("created UDP conntrack event listner thread\n");
432 if(pthread_setname_np(udp_thread, "udp ct listener") != 0)
433 {
434 IPACMERR("unable to set thread name\n");
435 }
436
437 isCTReg = true;
438 }
439
440 return 0;
441
442 error:
443 return -1;
444 }
CreateNatThreads(void)445 int IPACM_ConntrackListener::CreateNatThreads(void)
446 {
447 int ret;
448 pthread_t udpcto_thread = 0;
449
450 if(isNatThreadStart == false)
451 {
452 ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL);
453 if(0 != ret)
454 {
455 IPACMERR("unable to create udp conn timeout thread\n");
456 PERROR("unable to create udp conn timeout\n");
457 goto error;
458 }
459
460 IPACMDBG("created upd conn timeout thread\n");
461 if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0)
462 {
463 IPACMERR("unable to set thread name\n");
464 }
465
466 isNatThreadStart = true;
467 }
468 return 0;
469
470 error:
471 return -1;
472 }
473
TriggerWANDown(uint32_t wan_addr)474 void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr)
475 {
476 int ret = 0;
477 IPACMDBG_H("Deleting ipv4 nat table with");
478 IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr,
479 ((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF),
480 ((wan_addr>>8) & 0xFF), (wan_addr & 0xFF));
481
482 if(nat_inst != NULL)
483 {
484 ret = nat_inst->DeleteTable(wan_addr);
485 if (ret)
486 return;
487
488 WanUp = false;
489 wan_ipaddr = 0;
490 }
491 }
492
493
ParseCTMessage(struct nf_conntrack * ct)494 void ParseCTMessage(struct nf_conntrack *ct)
495 {
496 uint32_t status, timeout;
497 IPACMDBG("Printing conntrack parameters\n");
498
499 iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC));
500 iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST));
501 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
502 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
503
504 iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC));
505 iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST));
506 IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
507 IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
508
509 iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4));
510 iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4));
511 IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT));
512 IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT));
513
514 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
515 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
516 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
517
518 status = nfct_get_attr_u32(ct, ATTR_STATUS);
519 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
520
521 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
522 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
523
524 if(IPS_SRC_NAT & status)
525 {
526 IPACMDBG("IPS_SRC_NAT set\n");
527 }
528
529 if(IPS_DST_NAT & status)
530 {
531 IPACMDBG("IPS_DST_NAT set\n");
532 }
533
534 if(IPS_SRC_NAT_DONE & status)
535 {
536 IPACMDBG("IPS_SRC_NAT_DONE set\n");
537 }
538
539 if(IPS_DST_NAT_DONE & status)
540 {
541 IPACMDBG(" IPS_DST_NAT_DONE set\n");
542 }
543
544 IPACMDBG("\n");
545 return;
546 }
547
ParseCTV6Message(struct nf_conntrack * ct)548 void ParseCTV6Message(struct nf_conntrack *ct)
549 {
550 uint32_t status, timeout;
551 struct nfct_attr_grp_ipv6 orig_params;
552 uint8_t l4proto, tcp_flags, tcp_state;
553
554 IPACMDBG("Printing conntrack parameters\n");
555
556 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
557 IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1],
558 orig_params.src[2], orig_params.src[3]);
559 IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1],
560 orig_params.dst[2], orig_params.dst[3]);
561
562 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
563 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
564
565 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
566 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
567 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
568
569 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
570 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
571
572 status = nfct_get_attr_u32(ct, ATTR_STATUS);
573 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
574
575 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
576 IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto);
577 if(l4proto == IPPROTO_TCP)
578 {
579 tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
580 IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state);
581
582 tcp_flags = nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG);
583 IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags);
584 }
585
586 IPACMDBG("\n");
587 return;
588 }
589
590 #ifdef CT_OPT
ProcessCTV6Message(void * param)591 void IPACM_ConntrackListener::ProcessCTV6Message(void *param)
592 {
593 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
594 u_int8_t l4proto = 0;
595 uint32_t status = 0;
596 struct nf_conntrack *ct = evt_data->ct;
597
598 #ifdef IPACM_DEBUG
599 char buf[1024];
600
601 /* Process message and generate ioctl call to kernel thread */
602 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
603 evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME);
604 IPACMDBG("%s\n", buf);
605 IPACMDBG("\n");
606 ParseCTV6Message(ct);
607 #endif
608
609 if(p_lan2lan == NULL)
610 {
611 IPACMERR("Lan2Lan Instance is null\n");
612 goto IGNORE;
613 }
614
615 status = nfct_get_attr_u32(ct, ATTR_STATUS);
616 if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status))
617 {
618 IPACMDBG("Either Destination or Source nat flag Set\n");
619 goto IGNORE;
620 }
621
622 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
623 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
624 {
625 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
626 goto IGNORE;
627 }
628
629 IPACMDBG("Neither Destination nor Source nat flag Set\n");
630 struct nfct_attr_grp_ipv6 orig_params;
631 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
632
633 ipacm_event_connection lan2lan_conn;
634 lan2lan_conn.iptype = IPA_IP_v6;
635 memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src,
636 sizeof(lan2lan_conn.src_ipv6_addr));
637 IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
638 lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
639 for(int cnt=0; cnt<4; cnt++)
640 {
641 lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]);
642 }
643 IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
644 lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
645
646 memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst,
647 sizeof(lan2lan_conn.dst_ipv6_addr));
648 IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
649 lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
650 for(int cnt=0; cnt<4; cnt++)
651 {
652 lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]);
653 }
654 IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
655 lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
656
657 if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) ||
658 ((IPPROTO_TCP == l4proto) &&
659 (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))
660 )
661 {
662 p_lan2lan->handle_new_connection(&lan2lan_conn);
663 }
664 else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) ||
665 (IPPROTO_TCP == l4proto &&
666 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
667 {
668 p_lan2lan->handle_del_connection(&lan2lan_conn);
669 }
670
671 IGNORE:
672 /* Cleanup item that was allocated during the original CT callback */
673 nfct_destroy(ct);
674 return;
675 }
676 #endif
677
ProcessCTMessage(void * param)678 void IPACM_ConntrackListener::ProcessCTMessage(void *param)
679 {
680 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
681 u_int8_t l4proto = 0;
682 bool cache_ct = false;
683
684 #ifdef IPACM_DEBUG
685 char buf[1024];
686 unsigned int out_flags;
687
688 /* Process message and generate ioctl call to kernel thread */
689 out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID);
690 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
691 evt_data->type, NFCT_O_PLAIN, out_flags);
692 IPACMDBG_H("%s\n", buf);
693
694 ParseCTMessage(evt_data->ct);
695 #endif
696
697 l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO);
698 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
699 {
700 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
701 }
702 else
703 {
704 cache_ct = ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto);
705 }
706
707 /* Cleanup item that was allocated during the original CT callback */
708 if (!cache_ct)
709 nfct_destroy(evt_data->ct);
710 else
711 CacheORDeleteConntrack(evt_data->ct, evt_data->type, l4proto);
712 return;
713 }
714
AddIface(nat_table_entry * rule,bool * isTempEntry)715 bool IPACM_ConntrackListener::AddIface(
716 nat_table_entry *rule, bool *isTempEntry)
717 {
718 int cnt;
719
720 *isTempEntry = false;
721
722 /* Special handling for Passthrough IP. */
723 if (IPACM_Iface::ipacmcfg->ipacm_ip_passthrough_mode)
724 {
725 if (rule->private_ip == IPACM_Wan::getWANIP())
726 {
727 IPACMDBG("In Passthrough mode and entry matched with Wan IP (0x%x)\n",
728 rule->private_ip);
729 return true;
730 }
731 }
732
733 /* check whether nat iface or not */
734 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
735 {
736 if (nat_iface_ipv4_addr[cnt] != 0)
737 {
738 if (rule->private_ip == nat_iface_ipv4_addr[cnt] ||
739 rule->target_ip == nat_iface_ipv4_addr[cnt])
740 {
741 IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
742 iptodot("AddIface(): Nat entry match with ip addr",
743 nat_iface_ipv4_addr[cnt]);
744 return true;
745 }
746 }
747 }
748
749 if (backhaul_mode == Q6_WAN)
750 {
751 /* check whether non nat iface or not, on Non Nat iface
752 add dummy rule by copying public ip to private ip */
753 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
754 {
755 if (nonnat_iface_ipv4_addr[cnt] != 0)
756 {
757 if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] ||
758 rule->target_ip == nonnat_iface_ipv4_addr[cnt])
759 {
760 IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt);
761 iptodot("AddIface(): Non Nat entry match with ip addr",
762 nonnat_iface_ipv4_addr[cnt]);
763
764 rule->private_ip = rule->public_ip;
765 rule->private_port = rule->public_port;
766 return true;
767 }
768 }
769 }
770 IPACMDBG_H("Not mtaching with non-nat ifaces\n");
771 }
772 else
773 IPACMDBG("In STA mode, don't compare against non nat ifaces\n");
774
775 if(pConfig == NULL)
776 {
777 pConfig = IPACM_Config::GetInstance();
778 if(pConfig == NULL)
779 {
780 IPACMERR("Unable to get Config instance\n");
781 return false;
782 }
783 }
784
785 if (pConfig->isPrivateSubnet(rule->private_ip) ||
786 pConfig->isPrivateSubnet(rule->target_ip))
787 {
788 IPACMDBG("Matching with Private subnet\n");
789 *isTempEntry = true;
790 return true;
791 }
792
793 return false;
794 }
795
AddORDeleteNatEntry(const nat_entry_bundle * input)796 void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input)
797 {
798 u_int8_t tcp_state;
799
800 if (nat_inst == NULL)
801 {
802 IPACMERR("Nat instance is NULL, unable to add or delete\n");
803 return;
804 }
805
806 IPACMDBG_H("Below Nat Entry will either be added or deleted\n");
807 iptodot("AddORDeleteNatEntry(): target ip or dst ip",
808 input->rule->target_ip);
809 IPACMDBG("target port or dst port: 0x%x Decimal:%d\n",
810 input->rule->target_port, input->rule->target_port);
811 iptodot("AddORDeleteNatEntry(): private ip or src ip",
812 input->rule->private_ip);
813 IPACMDBG("private port or src port: 0x%x, Decimal:%d\n",
814 input->rule->private_port, input->rule->private_port);
815 IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n",
816 input->rule->public_port, input->rule->public_port);
817 IPACMDBG("Protocol: %d, destination nat flag: %d\n",
818 input->rule->protocol, input->rule->dst_nat);
819
820 if (IPPROTO_TCP == input->rule->protocol)
821 {
822 tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE);
823 if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
824 {
825 IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
826 if (!CtList->isWanUp())
827 {
828 IPACMDBG("Wan is not up, cache connections\n");
829 nat_inst->CacheEntry(input->rule);
830 }
831 else if (input->isTempEntry)
832 {
833 nat_inst->AddTempEntry(input->rule);
834 }
835 else
836 {
837 nat_inst->AddEntry(input->rule);
838 }
839 }
840 else if (TCP_CONNTRACK_FIN_WAIT == tcp_state ||
841 input->type == NFCT_T_DESTROY)
842 {
843 IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
844 "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type);
845
846 nat_inst->DeleteEntry(input->rule);
847 nat_inst->DeleteTempEntry(input->rule);
848 }
849 else
850 {
851 IPACMDBG("Ignore tcp state: %d and type: %d\n",
852 tcp_state, input->type);
853 }
854
855 }
856 else if (IPPROTO_UDP == input->rule->protocol)
857 {
858 if (NFCT_T_NEW == input->type || NFCT_T_UPDATE == input->type)
859 {
860 IPACMDBG("New UDP connection at time %ld\n", time(NULL));
861 if (!CtList->isWanUp())
862 {
863 IPACMDBG("Wan is not up, cache connections\n");
864 nat_inst->CacheEntry(input->rule);
865 }
866 else if (input->isTempEntry)
867 {
868 nat_inst->AddTempEntry(input->rule);
869 }
870 else
871 {
872 nat_inst->AddEntry(input->rule);
873 }
874 }
875 else if (NFCT_T_DESTROY == input->type)
876 {
877 IPACMDBG("UDP connection close at time %ld\n", time(NULL));
878 nat_inst->DeleteEntry(input->rule);
879 nat_inst->DeleteTempEntry(input->rule);
880 }
881 }
882
883 return;
884 }
885
PopulateTCPorUDPEntry(struct nf_conntrack * ct,uint32_t status,nat_table_entry * rule)886 void IPACM_ConntrackListener::PopulateTCPorUDPEntry(
887 struct nf_conntrack *ct,
888 uint32_t status,
889 nat_table_entry *rule)
890 {
891 uint32_t repl_dst_ip;
892
893 if (IPS_DST_NAT == status)
894 {
895 IPACMDBG("Destination NAT\n");
896 rule->dst_nat = true;
897
898 IPACMDBG("Parse reply tuple\n");
899 rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
900 rule->target_ip = ntohl(rule->target_ip);
901 iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
902
903 /* Retriev target/dst port */
904 rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
905 rule->target_port = ntohs(rule->target_port);
906 if (0 == rule->target_port)
907 {
908 IPACMDBG("unable to retrieve target port\n");
909 }
910
911 rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
912 rule->public_port = ntohs(rule->public_port);
913
914 /* Retriev src/private ip address */
915 rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
916 rule->private_ip = ntohl(rule->private_ip);
917 iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
918 if (0 == rule->private_ip)
919 {
920 IPACMDBG("unable to retrieve private ip address\n");
921 }
922
923 /* Retriev src/private port */
924 rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
925 rule->private_port = ntohs(rule->private_port);
926 if (0 == rule->private_port)
927 {
928 IPACMDBG("unable to retrieve private port\n");
929 }
930 }
931 else if (IPS_SRC_NAT == status)
932 {
933 IPACMDBG("Source NAT\n");
934 rule->dst_nat = false;
935
936 /* Retriev target/dst ip address */
937 IPACMDBG("Parse source tuple\n");
938 rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
939 rule->target_ip = ntohl(rule->target_ip);
940 iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
941 if (0 == rule->target_ip)
942 {
943 IPACMDBG("unable to retrieve target ip address\n");
944 }
945 /* Retriev target/dst port */
946 rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
947 rule->target_port = ntohs(rule->target_port);
948 if (0 == rule->target_port)
949 {
950 IPACMDBG("unable to retrieve target port\n");
951 }
952
953 /* Retriev public port */
954 rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
955 rule->public_port = ntohs(rule->public_port);
956 if (0 == rule->public_port)
957 {
958 IPACMDBG("unable to retrieve public port\n");
959 }
960
961 /* Retriev src/private ip address */
962 rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
963 rule->private_ip = ntohl(rule->private_ip);
964 iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
965 if (0 == rule->private_ip)
966 {
967 IPACMDBG("unable to retrieve private ip address\n");
968 }
969
970 /* Retriev src/private port */
971 rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
972 rule->private_port = ntohs(rule->private_port);
973 if (0 == rule->private_port)
974 {
975 IPACMDBG("unable to retrieve private port\n");
976 }
977
978 /* If Reply destination IP is not Public IP, install dummy NAT rule. */
979 repl_dst_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST);
980 repl_dst_ip = ntohl(repl_dst_ip);
981 if(repl_dst_ip != rule->public_ip)
982 {
983 IPACMDBG_H("Reply dst IP:0x%x not equal to wan ip:0x%x\n",repl_dst_ip, rule->public_ip);
984 rule->private_ip = rule->public_ip;
985 }
986 }
987
988 return;
989 }
990
991 #ifdef CT_OPT
HandleLan2Lan(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,nat_table_entry * rule)992 void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct,
993 enum nf_conntrack_msg_type type,
994 nat_table_entry *rule)
995 {
996 ipacm_event_connection lan2lan_conn = { 0 };
997
998 if (p_lan2lan == NULL)
999 {
1000 IPACMERR("Lan2Lan Instance is null\n");
1001 return;
1002 }
1003
1004 lan2lan_conn.iptype = IPA_IP_v4;
1005 lan2lan_conn.src_ipv4_addr = orig_src_ip;
1006 lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
1007
1008 if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) ||
1009 ((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
1010 {
1011 p_lan2lan->handle_new_connection(&lan2lan_conn);
1012 }
1013 else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) ||
1014 (IPPROTO_TCP == rule->protocol &&
1015 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
1016 {
1017 p_lan2lan->handle_del_connection(&lan2lan_conn);
1018 }
1019 }
1020 #endif
1021
CheckSTAClient(const nat_table_entry * rule,bool * isTempEntry)1022 void IPACM_ConntrackListener::CheckSTAClient(
1023 const nat_table_entry *rule, bool *isTempEntry)
1024 {
1025 int nCnt;
1026
1027 /* Check whether target is in STA client list or not
1028 if not ignore the connection */
1029 if((backhaul_mode == Q6_WAN) || (StaClntCnt == 0))
1030 {
1031 return;
1032 }
1033
1034 if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) !=
1035 (rule->target_ip & STA_CLNT_SUBNET_MASK))
1036 {
1037 IPACMDBG("STA client subnet mask not matching\n");
1038 return;
1039 }
1040
1041 IPACMDBG("StaClntCnt %d\n", StaClntCnt);
1042 for(nCnt = 0; nCnt < StaClntCnt; nCnt++)
1043 {
1044 IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n",
1045 rule->target_ip, sta_clnt_ipv4_addr[nCnt]);
1046 if(rule->target_ip == sta_clnt_ipv4_addr[nCnt])
1047 {
1048 IPACMDBG("Match index %d\n", nCnt);
1049 return;
1050 }
1051 }
1052
1053 IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
1054 rule->target_ip);
1055 *isTempEntry = true;
1056 }
1057
1058 /* conntrack send in host order and ipa expects in host order */
ProcessTCPorUDPMsg(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,u_int8_t l4proto)1059 bool IPACM_ConntrackListener::ProcessTCPorUDPMsg(
1060 struct nf_conntrack *ct,
1061 enum nf_conntrack_msg_type type,
1062 u_int8_t l4proto)
1063 {
1064 nat_table_entry rule;
1065 uint32_t status = 0;
1066 uint32_t orig_src_ip, orig_dst_ip;
1067 bool isAdd = false;
1068 bool cache_ct = false;
1069
1070 nat_entry_bundle nat_entry;
1071 nat_entry.isTempEntry = false;
1072 nat_entry.ct = ct;
1073 nat_entry.type = type;
1074
1075 memset(&rule, 0, sizeof(rule));
1076 IPACMDBG("Received type:%d with proto:%d\n", type, l4proto);
1077 status = nfct_get_attr_u32(ct, ATTR_STATUS);
1078
1079 /* Retrieve Protocol */
1080 rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO);
1081
1082 if(IPS_DST_NAT & status)
1083 {
1084 status = IPS_DST_NAT;
1085 }
1086 else if(IPS_SRC_NAT & status)
1087 {
1088 status = IPS_SRC_NAT;
1089 }
1090 else
1091 {
1092 IPACMDBG("Neither Destination nor Source nat flag Set\n");
1093 orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
1094 orig_src_ip = ntohl(orig_src_ip);
1095 if(orig_src_ip == 0)
1096 {
1097 IPACMERR("unable to retrieve orig src ip address\n");
1098 return cache_ct;
1099 }
1100
1101 orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
1102 orig_dst_ip = ntohl(orig_dst_ip);
1103 if(orig_dst_ip == 0)
1104 {
1105 IPACMERR("unable to retrieve orig dst ip address\n");
1106 return cache_ct;
1107 }
1108
1109 if(orig_src_ip == wan_ipaddr)
1110 {
1111 IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip);
1112 status = IPS_SRC_NAT;
1113 }
1114 else if(orig_dst_ip == wan_ipaddr)
1115 {
1116 IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip);
1117 status = IPS_DST_NAT;
1118 }
1119 else
1120 {
1121 IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n",
1122 orig_src_ip, orig_dst_ip, wan_ipaddr);
1123
1124 #ifdef CT_OPT
1125 HandleLan2Lan(ct, type, &rule);
1126 #endif
1127 IPACMDBG("Neither source Nor destination nat.\n");
1128 /* If WAN is not up, cache the event. */
1129 if(!CtList->isWanUp())
1130 cache_ct = true;
1131 goto IGNORE;
1132 }
1133 }
1134
1135 rule.public_ip = wan_ipaddr;
1136 PopulateTCPorUDPEntry(ct, status, &rule);
1137
1138 if (rule.private_ip != wan_ipaddr)
1139 {
1140 isAdd = AddIface(&rule, &nat_entry.isTempEntry);
1141 if (!isAdd)
1142 {
1143 goto IGNORE;
1144 }
1145 }
1146 else
1147 {
1148 if (backhaul_mode != Q6_WAN)
1149 {
1150 IPACMDBG("In STA mode, ignore connections destinated to STA interface\n");
1151 goto IGNORE;
1152 }
1153
1154 IPACMDBG("For embedded connections add dummy nat rule\n");
1155 IPACMDBG("Change private port %d to %d\n",
1156 rule.private_port, rule.public_port);
1157 rule.private_port = rule.public_port;
1158 }
1159
1160 CheckSTAClient(&rule, &nat_entry.isTempEntry);
1161 nat_entry.rule = &rule;
1162 AddORDeleteNatEntry(&nat_entry);
1163 return cache_ct;
1164
1165 IGNORE:
1166 IPACMDBG_H("ignoring below Nat Entry\n");
1167 iptodot("ProcessTCPorUDPMsg(): target ip or dst ip", rule.target_ip);
1168 IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port);
1169 iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip);
1170 IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
1171 IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
1172 IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
1173 return cache_ct;
1174 }
1175
HandleSTAClientAddEvt(uint32_t clnt_ip_addr)1176 void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr)
1177 {
1178 int cnt;
1179 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1180
1181 if(StaClntCnt >= MAX_STA_CLNT_IFACES)
1182 {
1183 IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr);
1184 return;
1185 }
1186
1187 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1188 {
1189 if(sta_clnt_ipv4_addr[cnt] != 0 &&
1190 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1191 {
1192 IPACMDBG("Ignoring duplicate one 0x%x\n", clnt_ip_addr);
1193 break;
1194 }
1195
1196 if(sta_clnt_ipv4_addr[cnt] == 0)
1197 {
1198 IPACMDBG("Adding STA client 0x%x at Index: %d\n",
1199 clnt_ip_addr, cnt);
1200 sta_clnt_ipv4_addr[cnt] = clnt_ip_addr;
1201 StaClntCnt++;
1202 IPACMDBG("STA client cnt %d\n", StaClntCnt);
1203 break;
1204 }
1205
1206 }
1207
1208 nat_inst->FlushTempEntries(clnt_ip_addr, true);
1209 return;
1210 }
1211
HandleSTAClientDelEvt(uint32_t clnt_ip_addr)1212 void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr)
1213 {
1214 int cnt;
1215 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1216
1217 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1218 {
1219 if(sta_clnt_ipv4_addr[cnt] != 0 &&
1220 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1221 {
1222 IPACMDBG("Deleting STA client 0x%x at index: %d\n",
1223 clnt_ip_addr, cnt);
1224 sta_clnt_ipv4_addr[cnt] = 0;
1225 nat_inst->DelEntriesOnSTAClntDiscon(clnt_ip_addr);
1226 StaClntCnt--;
1227 IPACMDBG("STA client cnt %d\n", StaClntCnt);
1228 break;
1229 }
1230 }
1231
1232 nat_inst->FlushTempEntries(clnt_ip_addr, false);
1233 return;
1234 }
1235
isLocalHostAddr(uint32_t src_ip_addr,uint32_t dst_ip_addr)1236 bool isLocalHostAddr(uint32_t src_ip_addr, uint32_t dst_ip_addr) {
1237
1238 src_ip_addr = ntohl(src_ip_addr);
1239 dst_ip_addr = ntohl(dst_ip_addr);
1240 if ((src_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR || (dst_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR) /* (loopback) */
1241 return true;
1242 return false;
1243 }
1244
readConntrack(int fd)1245 void IPACM_ConntrackListener::readConntrack(int fd) {
1246
1247 int recv_bytes = -1, index = 0, len =0;
1248 char buffer[CT_ENTRIES_BUFFER_SIZE];
1249 struct nf_conntrack *ct;
1250 struct nlmsghdr *nl_header;
1251 struct iovec iov = {
1252 .iov_base = buffer,
1253 .iov_len = CT_ENTRIES_BUFFER_SIZE,
1254 };
1255 struct sockaddr_nl addr;
1256 struct msghdr msg = {
1257 .msg_name = &addr,
1258 .msg_namelen = sizeof(struct sockaddr_nl),
1259 .msg_iov = &iov,
1260 .msg_iovlen = 1,
1261 .msg_control = NULL,
1262 .msg_controllen = 0,
1263 .msg_flags = 0,
1264 };
1265
1266 len = MAX_CONNTRACK_ENTRIES * sizeof(ct_entry);
1267
1268 ct_entries = (ct_entry *) malloc(len);
1269 if(ct_entries == NULL)
1270 {
1271 IPACMERR("unable to allocate ct_entries memory \n");
1272 return;
1273 }
1274 memset(ct_entries, 0, len);
1275
1276 if( fd < 0)
1277 {
1278 IPACMDBG_H("Invalid fd %d \n",fd);
1279 free(ct_entries);
1280 return;
1281 }
1282 IPACMDBG_H("receiving conntrack entries started.\n");
1283 len = CT_ENTRIES_BUFFER_SIZE;
1284 while (len > 0)
1285 {
1286 memset(buffer, 0, CT_ENTRIES_BUFFER_SIZE);
1287 recv_bytes = recvmsg(fd, &msg, 0);
1288 if(recv_bytes < 0)
1289 {
1290 IPACMDBG_H("error in receiving conntrack entries %d%s\n",errno, strerror(errno));
1291 break;
1292 }
1293 else
1294 {
1295 len -= recv_bytes;
1296 nl_header = (struct nlmsghdr *)buffer;
1297 IPACMDBG_H("Number of bytes:%d to parse\n", recv_bytes);
1298 while(NLMSG_OK(nl_header, recv_bytes) && (index < MAX_CONNTRACK_ENTRIES))
1299 {
1300 if (nl_header->nlmsg_type == NLMSG_ERROR)
1301 {
1302 IPACMDBG_H("Error, recv_bytes is %d\n",recv_bytes);
1303 break;
1304 }
1305 ct = nfct_new();
1306 if (ct != NULL)
1307 {
1308 int parseResult = nfct_parse_conntrack((nf_conntrack_msg_type) NFCT_T_ALL,nl_header, ct);
1309 if(parseResult != NFCT_T_ERROR && parseResult != 0)
1310 {
1311 ct_entries[index].ct = ct;
1312 ct_entries[index++].type = (nf_conntrack_msg_type)parseResult;
1313 }
1314 else
1315 {
1316 IPACMDBG_H("error in parsing %d%s \n", errno, strerror(errno));
1317 nfct_destroy(ct);
1318 }
1319 }
1320 else
1321 {
1322 IPACMDBG_H("ct allocation failed\n");
1323 }
1324 if (nl_header->nlmsg_type == NLMSG_DONE)
1325 {
1326 IPACMDBG_H("Message is done.\n");
1327 break;
1328 }
1329 nl_header = NLMSG_NEXT(nl_header, recv_bytes);
1330 }
1331 }
1332 }
1333
1334 isReadCTDone = true;
1335 IPACMDBG_H("receiving conntrack entries ended. No of entries: %d\n", index);
1336 if(isWanUp() && !isProcessCTDone)
1337 {
1338 IPACMDBG_H("wan is up, process ct entries \n");
1339 processConntrack();
1340 }
1341
1342 return ;
1343 }
1344
processConntrack()1345 void IPACM_ConntrackListener::processConntrack() {
1346
1347 uint8_t ip_type;
1348 int index = 0;
1349 ipacm_ct_evt_data *ct_data;
1350 IPACMDBG_H("process conntrack started \n");
1351 if(ct_entries != NULL)
1352 {
1353 while(ct_entries[index].ct != NULL)
1354 {
1355 ip_type = nfct_get_attr_u8(ct_entries[index].ct, ATTR_REPL_L3PROTO);
1356 if((AF_INET == ip_type) && isLocalHostAddr(nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_SRC),
1357 nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_DST)))
1358 {
1359 IPACMDBG_H(" loopback entry \n");
1360 goto IGNORE;
1361 }
1362
1363 #ifndef CT_OPT
1364 if(AF_INET6 == ip_type)
1365 {
1366 IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type);
1367 goto IGNORE;
1368 }
1369 #endif
1370
1371 ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data));
1372 if(ct_data == NULL)
1373 {
1374 IPACMERR("unable to allocate memory \n");
1375 goto IGNORE;
1376 }
1377
1378 ct_data->ct = ct_entries[index].ct;
1379 ct_data->type = ct_entries[index].type;
1380
1381 #ifdef CT_OPT
1382 if(AF_INET6 == ip_type)
1383 {
1384 ProcessCTV6Message(ct_data);
1385 }
1386 #else
1387 ProcessCTMessage(ct_data);
1388 #endif
1389 index++;
1390 free(ct_data);
1391 continue;
1392 IGNORE:
1393 nfct_destroy(ct_entries[index].ct);
1394 index++;
1395 }
1396 }
1397 else
1398 {
1399 IPACMDBG_H("ct entry is null\n");
1400 return ;
1401 }
1402 isProcessCTDone = true;
1403 free(ct_entries);
1404 ct_entries = NULL;
1405 IPACMDBG_H("process conntrack ended. Number of entries:%d \n", index);
1406 return;
1407 }
1408
CacheORDeleteConntrack(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,u_int8_t protocol)1409 void IPACM_ConntrackListener::CacheORDeleteConntrack
1410 (
1411 struct nf_conntrack *ct,
1412 enum nf_conntrack_msg_type type,
1413 u_int8_t protocol
1414 )
1415 {
1416 u_int8_t tcp_state;
1417 int i = 0, free_idx = -1;
1418
1419 IPACMDBG("CT entry, type (%d), protocol(%d)\n", type, protocol);
1420 /* Check for duplicate entry and in parallel find first free index. */
1421 for(; i < MAX_CONNTRACK_ENTRIES; i++)
1422 {
1423 if (ct_cache[i].ct != NULL)
1424 {
1425 if (nfct_cmp(ct_cache[i].ct, ct, NFCT_CMP_ORIG | NFCT_CMP_REPL))
1426 {
1427 /* Duplicate entry. */
1428 IPACMDBG("Duplicate CT entry, type (%d), protocol(%d)\n",
1429 type, protocol);
1430 break;
1431 }
1432 }
1433 else if ((ct_cache[i].ct == NULL) && (free_idx == -1))
1434 {
1435 /* Cache the first free index. */
1436 free_idx = i;
1437 }
1438 }
1439
1440 /* Duplicate entry handling. */
1441 if (i < MAX_CONNTRACK_ENTRIES)
1442 {
1443 if (IPPROTO_TCP == protocol)
1444 {
1445 tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
1446 if (TCP_CONNTRACK_FIN_WAIT == tcp_state || type == NFCT_T_DESTROY)
1447 {
1448 IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
1449 "or type NFCT_T_DESTROY\n", tcp_state);
1450 nfct_destroy(ct_cache[i].ct);
1451 nfct_destroy(ct);
1452 memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1453 return ;
1454 }
1455 }
1456 if ((IPPROTO_UDP == protocol) && (type == NFCT_T_DESTROY))
1457 {
1458 IPACMDBG("UDP type NFCT_T_DESTROY\n");
1459 nfct_destroy(ct_cache[i].ct);
1460 nfct_destroy(ct);
1461 memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1462 return;
1463 }
1464 }
1465 else if ((i == MAX_CONNTRACK_ENTRIES) &&
1466 (type != NFCT_T_DESTROY) && (free_idx != -1))
1467 {
1468 if (IPPROTO_TCP == protocol)
1469 {
1470 tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
1471 if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
1472 {
1473 IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED\n");
1474 /* Cache the entry. */
1475 ct_cache[free_idx].ct = ct;
1476 ct_cache[free_idx].protocol = protocol;
1477 ct_cache[free_idx].type = type;
1478 return;
1479 }
1480 }
1481 if (IPPROTO_UDP == protocol)
1482 {
1483 if (NFCT_T_NEW == type)
1484 {
1485 IPACMDBG("New UDP connection\n");
1486 /* Cache the entry. */
1487 ct_cache[free_idx].ct = ct;
1488 ct_cache[free_idx].protocol = protocol;
1489 ct_cache[free_idx].type = type;
1490 return;
1491 }
1492 }
1493 }
1494 /* In all other cases, free the conntracy entry. */
1495 nfct_destroy(ct);
1496 return ;
1497 }
processCacheConntrack(void)1498 void IPACM_ConntrackListener::processCacheConntrack(void)
1499 {
1500 int i = 0;
1501
1502 IPACMDBG("Entry:\n");
1503 for(; i < MAX_CONNTRACK_ENTRIES; i++)
1504 {
1505 if (ct_cache[i].ct != NULL)
1506 {
1507 ProcessTCPorUDPMsg(ct_cache[i].ct, ct_cache[i].type, ct_cache[i].protocol);
1508 nfct_destroy(ct_cache[i].ct);
1509 memset(&ct_cache[i], 0, sizeof(ct_cache[i]));
1510 }
1511 }
1512 IPACMDBG("Exit:\n");
1513 }
1514
1515