1 /*
2 Copyright (c) 2013-2016, 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
IPACM_ConntrackListener()39 IPACM_ConntrackListener::IPACM_ConntrackListener()
40 {
41 IPACMDBG("\n");
42
43 isNatThreadStart = false;
44 isCTReg = false;
45 WanUp = false;
46 nat_inst = NatApp::GetInstance();
47
48 NatIfaceCnt = 0;
49 StaClntCnt = 0;
50 pNatIfaces = NULL;
51 pConfig = IPACM_Config::GetInstance();;
52
53 memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr));
54 memset(nonnat_iface_ipv4_addr, 0, sizeof(nonnat_iface_ipv4_addr));
55 memset(sta_clnt_ipv4_addr, 0, sizeof(sta_clnt_ipv4_addr));
56
57 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, this);
58 IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, this);
59 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE, this);
60 IPACM_EvtDispatcher::registr(IPA_PROCESS_CT_MESSAGE_V6, this);
61 IPACM_EvtDispatcher::registr(IPA_HANDLE_WLAN_UP, this);
62 IPACM_EvtDispatcher::registr(IPA_HANDLE_LAN_UP, this);
63 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, this);
64 IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, this);
65
66 #ifdef CT_OPT
67 p_lan2lan = IPACM_LanToLan::getLan2LanInstance();
68 #endif
69 }
70
event_callback(ipa_cm_event_id evt,void * data)71 void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
72 void *data)
73 {
74 ipacm_event_iface_up *wan_down = NULL;
75
76 if(data == NULL)
77 {
78 IPACMERR("Invalid Data\n");
79 return;
80 }
81
82 switch(evt)
83 {
84 case IPA_PROCESS_CT_MESSAGE:
85 IPACMDBG("Received IPA_PROCESS_CT_MESSAGE event\n");
86 ProcessCTMessage(data);
87 break;
88
89 #ifdef CT_OPT
90 case IPA_PROCESS_CT_MESSAGE_V6:
91 IPACMDBG("Received IPA_PROCESS_CT_MESSAGE_V6 event\n");
92 ProcessCTV6Message(data);
93 break;
94 #endif
95
96 case IPA_HANDLE_WAN_UP:
97 IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
98 CreateConnTrackThreads();
99 TriggerWANUp(data);
100 break;
101
102 case IPA_HANDLE_WAN_DOWN:
103 IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
104 wan_down = (ipacm_event_iface_up *)data;
105 if(isWanUp())
106 {
107 TriggerWANDown(wan_down->ipv4_addr);
108 }
109 break;
110
111 /* if wlan or lan comes up after wan interface, modify
112 tcp/udp filters to ignore local wlan or lan connections */
113 case IPA_HANDLE_WLAN_UP:
114 case IPA_HANDLE_LAN_UP:
115 IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n",
116 evt, ((ipacm_event_iface_up *)data)->ifname,
117 ((ipacm_event_iface_up *)data)->ipv4_addr);
118 if(isWanUp())
119 {
120 CreateConnTrackThreads();
121 IPACM_ConntrackClient::UpdateUDPFilters(data, false);
122 IPACM_ConntrackClient::UpdateTCPFilters(data, false);
123 }
124 break;
125
126 case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
127 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT event\n");
128 HandleNonNatIPAddr(data, true);
129 break;
130
131 case IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT:
132 IPACMDBG("Received IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT event\n");
133 HandleNonNatIPAddr(data, false);
134 break;
135
136 default:
137 IPACMDBG("Ignore cmd %d\n", evt);
138 break;
139 }
140 }
141
CheckNatIface(ipacm_event_data_all * data,bool * NatIface)142 int IPACM_ConntrackListener::CheckNatIface(
143 ipacm_event_data_all *data, bool *NatIface)
144 {
145 int fd = 0, len = 0, cnt, i;
146 struct ifreq ifr;
147 *NatIface = false;
148
149 if (data->ipv4_addr == 0 || data->iptype != IPA_IP_v4)
150 {
151 IPACMDBG("Ignoring\n");
152 return IPACM_FAILURE;
153 }
154
155 IPACMDBG("Received interface index %d with ip type: %d", data->if_index, data->iptype);
156 iptodot(" and ipv4 address", data->ipv4_addr);
157
158 if (pConfig == NULL)
159 {
160 pConfig = IPACM_Config::GetInstance();
161 if (pConfig == NULL)
162 {
163 IPACMERR("Unable to get Config instance\n");
164 return IPACM_FAILURE;
165 }
166 }
167
168 cnt = pConfig->GetNatIfacesCnt();
169 NatIfaceCnt = cnt;
170 IPACMDBG("Total Nat ifaces: %d\n", NatIfaceCnt);
171 if (pNatIfaces != NULL)
172 {
173 free(pNatIfaces);
174 pNatIfaces = NULL;
175 }
176
177 len = (sizeof(NatIfaces) * NatIfaceCnt);
178 pNatIfaces = (NatIfaces *)malloc(len);
179 if (pNatIfaces == NULL)
180 {
181 IPACMERR("Unable to allocate memory for non nat ifaces\n");
182 return IPACM_FAILURE;
183 }
184
185 memset(pNatIfaces, 0, len);
186 if (pConfig->GetNatIfaces(NatIfaceCnt, pNatIfaces) != 0)
187 {
188 IPACMERR("Unable to retrieve non nat ifaces\n");
189 return IPACM_FAILURE;
190 }
191
192 /* Search/Configure linux interface-index and map it to IPA interface-index */
193 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
194 {
195 PERROR("get interface name socket create failed");
196 return IPACM_FAILURE;
197 }
198
199 memset(&ifr, 0, sizeof(struct ifreq));
200 ifr.ifr_ifindex = data->if_index;
201 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0)
202 {
203 PERROR("call_ioctl_on_dev: ioctl failed:");
204 close(fd);
205 return IPACM_FAILURE;
206 }
207 close(fd);
208
209 for (i = 0; i < NatIfaceCnt; i++)
210 {
211 if (strncmp(ifr.ifr_name,
212 pNatIfaces[i].iface_name,
213 sizeof(pNatIfaces[i].iface_name)) == 0)
214 {
215 IPACMDBG_H("Nat iface (%s), entry (%d), dont cache",
216 pNatIfaces[i].iface_name, i);
217 iptodot("with ipv4 address: ", nat_iface_ipv4_addr[i]);
218 *NatIface = true;
219 return IPACM_SUCCESS;
220 }
221 }
222
223 return IPACM_SUCCESS;
224 }
225
HandleNonNatIPAddr(void * inParam,bool AddOp)226 void IPACM_ConntrackListener::HandleNonNatIPAddr(
227 void *inParam, bool AddOp)
228 {
229 ipacm_event_data_all *data = (ipacm_event_data_all *)inParam;
230 bool NatIface = false;
231 int cnt, ret;
232
233 if (isStaMode)
234 {
235 IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n");
236 return;
237 }
238
239 /* Handle only non nat ifaces, NAT iface should be handle
240 separately to avoid race conditions between route/nat
241 rules add/delete operations */
242 if (AddOp)
243 {
244 ret = CheckNatIface(data, &NatIface);
245 if (!NatIface && ret == IPACM_SUCCESS)
246 {
247 /* Cache the non nat iface ip address */
248 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
249 {
250 if (nonnat_iface_ipv4_addr[cnt] == 0)
251 {
252 nonnat_iface_ipv4_addr[cnt] = data->ipv4_addr;
253 IPACMDBG("Add ip addr to non nat list (%d) ", cnt);
254 iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
255
256 /* Add dummy nat rule for non nat ifaces */
257 nat_inst->FlushTempEntries(data->ipv4_addr, true, true);
258 return;
259 }
260 }
261 }
262 }
263 else
264 {
265 /* for delete operation */
266 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
267 {
268 if (nonnat_iface_ipv4_addr[cnt] == data->ipv4_addr)
269 {
270 IPACMDBG("Reseting ct filters, entry (%d) ", cnt);
271 iptodot("with ipv4 address", nonnat_iface_ipv4_addr[cnt]);
272 nonnat_iface_ipv4_addr[cnt] = 0;
273 nat_inst->FlushTempEntries(data->ipv4_addr, false);
274 nat_inst->DelEntriesOnClntDiscon(data->ipv4_addr);
275 return;
276 }
277 }
278
279 }
280
281 return;
282 }
283
HandleNeighIpAddrAddEvt(ipacm_event_data_all * data)284 void IPACM_ConntrackListener::HandleNeighIpAddrAddEvt(
285 ipacm_event_data_all *data)
286 {
287 bool NatIface = false;
288 int j, ret;
289
290 ret = CheckNatIface(data, &NatIface);
291 if (NatIface && ret == IPACM_SUCCESS)
292 {
293 for (j = 0; j < MAX_IFACE_ADDRESS; j++)
294 {
295 /* check if duplicate NAT ip */
296 if (nat_iface_ipv4_addr[j] == data->ipv4_addr)
297 break;
298
299 /* Cache the new nat iface address */
300 if (nat_iface_ipv4_addr[j] == 0)
301 {
302 nat_iface_ipv4_addr[j] = data->ipv4_addr;
303 iptodot("Nating connections of addr: ", nat_iface_ipv4_addr[j]);
304 break;
305 }
306 }
307
308 /* Add the cached temp entries to NAT table */
309 if (j != MAX_IFACE_ADDRESS)
310 {
311 nat_inst->ResetPwrSaveIf(data->ipv4_addr);
312 nat_inst->FlushTempEntries(data->ipv4_addr, true);
313 }
314 }
315 return;
316 }
317
HandleNeighIpAddrDelEvt(uint32_t ipv4_addr)318 void IPACM_ConntrackListener::HandleNeighIpAddrDelEvt(
319 uint32_t ipv4_addr)
320 {
321 int cnt;
322
323 if(ipv4_addr == 0)
324 {
325 IPACMDBG("Ignoring\n");
326 return;
327 }
328
329 iptodot("HandleNeighIpAddrDelEvt(): Received ip addr", ipv4_addr);
330 for(cnt = 0; cnt<MAX_IFACE_ADDRESS; cnt++)
331 {
332 if (nat_iface_ipv4_addr[cnt] == ipv4_addr)
333 {
334 IPACMDBG("Reseting ct nat iface, entry (%d) ", cnt);
335 iptodot("with ipv4 address", nat_iface_ipv4_addr[cnt]);
336 nat_iface_ipv4_addr[cnt] = 0;
337 nat_inst->FlushTempEntries(ipv4_addr, false);
338 nat_inst->DelEntriesOnClntDiscon(ipv4_addr);
339 }
340 }
341
342 return;
343 }
344
TriggerWANUp(void * in_param)345 void IPACM_ConntrackListener::TriggerWANUp(void *in_param)
346 {
347 ipacm_event_iface_up *wanup_data = (ipacm_event_iface_up *)in_param;
348
349 IPACMDBG_H("Recevied below information during wanup,\n");
350 IPACMDBG_H("if_name:%s, ipv4_address:0x%x\n",
351 wanup_data->ifname, wanup_data->ipv4_addr);
352
353 if(wanup_data->ipv4_addr == 0)
354 {
355 IPACMERR("Invalid ipv4 address,ignoring IPA_HANDLE_WAN_UP event\n");
356 return;
357 }
358
359 if(isWanUp())
360 {
361 if (wan_ipaddr != wanup_data->ipv4_addr)
362 TriggerWANDown(wan_ipaddr);
363 else
364 return;
365 }
366
367 WanUp = true;
368 isStaMode = wanup_data->is_sta;
369 IPACMDBG("isStaMode: %d\n", isStaMode);
370
371 wan_ipaddr = wanup_data->ipv4_addr;
372 memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname));
373
374 if(nat_inst != NULL)
375 {
376 nat_inst->AddTable(wanup_data->ipv4_addr);
377 }
378
379 IPACMDBG("creating nat threads\n");
380 CreateNatThreads();
381 }
382
CreateConnTrackThreads(void)383 int IPACM_ConntrackListener::CreateConnTrackThreads(void)
384 {
385 int ret;
386 pthread_t tcp_thread = 0, udp_thread = 0;
387
388 if(isCTReg == false)
389 {
390 if(!tcp_thread)
391 {
392 ret = pthread_create(&tcp_thread, NULL, IPACM_ConntrackClient::TCPRegisterWithConnTrack, NULL);
393 if(0 != ret)
394 {
395 IPACMERR("unable to create TCP conntrack event listner thread\n");
396 PERROR("unable to create TCP conntrack\n");
397 return -1;
398 }
399
400 IPACMDBG("created TCP conntrack event listner thread\n");
401 if(pthread_setname_np(tcp_thread, "tcp ct listener") != 0)
402 {
403 IPACMERR("unable to set thread name\n");
404 }
405 }
406
407 if(!udp_thread)
408 {
409 ret = pthread_create(&udp_thread, NULL, IPACM_ConntrackClient::UDPRegisterWithConnTrack, NULL);
410 if(0 != ret)
411 {
412 IPACMERR("unable to create UDP conntrack event listner thread\n");
413 PERROR("unable to create UDP conntrack\n");
414 goto error;
415 }
416
417 IPACMDBG("created UDP conntrack event listner thread\n");
418 if(pthread_setname_np(udp_thread, "udp ct listener") != 0)
419 {
420 IPACMERR("unable to set thread name\n");
421 }
422 }
423
424 isCTReg = true;
425 }
426
427 return 0;
428
429 error:
430 return -1;
431 }
CreateNatThreads(void)432 int IPACM_ConntrackListener::CreateNatThreads(void)
433 {
434 int ret;
435 pthread_t udpcto_thread = 0;
436
437 if(isNatThreadStart == false)
438 {
439 if(!udpcto_thread)
440 {
441 ret = pthread_create(&udpcto_thread, NULL, IPACM_ConntrackClient::UDPConnTimeoutUpdate, NULL);
442 if(0 != ret)
443 {
444 IPACMERR("unable to create udp conn timeout thread\n");
445 PERROR("unable to create udp conn timeout\n");
446 goto error;
447 }
448
449 IPACMDBG("created upd conn timeout thread\n");
450 if(pthread_setname_np(udpcto_thread, "udp conn timeout") != 0)
451 {
452 IPACMERR("unable to set thread name\n");
453 }
454 }
455
456 isNatThreadStart = true;
457 }
458 return 0;
459
460 error:
461 return -1;
462 }
463
TriggerWANDown(uint32_t wan_addr)464 void IPACM_ConntrackListener::TriggerWANDown(uint32_t wan_addr)
465 {
466 int ret = 0;
467 IPACMDBG_H("Deleting ipv4 nat table with");
468 IPACMDBG_H(" public ip address(0x%x): %d.%d.%d.%d\n", wan_addr,
469 ((wan_addr>>24) & 0xFF), ((wan_addr>>16) & 0xFF),
470 ((wan_addr>>8) & 0xFF), (wan_addr & 0xFF));
471
472 if(nat_inst != NULL)
473 {
474 ret = nat_inst->DeleteTable(wan_addr);
475 if (ret)
476 return;
477
478 WanUp = false;
479 wan_ipaddr = 0;
480 }
481 }
482
483
ParseCTMessage(struct nf_conntrack * ct)484 void ParseCTMessage(struct nf_conntrack *ct)
485 {
486 uint32_t status, timeout;
487 IPACMDBG("Printing conntrack parameters\n");
488
489 iptodot("ATTR_IPV4_SRC = ATTR_ORIG_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC));
490 iptodot("ATTR_IPV4_DST = ATTR_ORIG_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST));
491 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
492 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
493
494 iptodot("ATTR_REPL_IPV4_SRC:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC));
495 iptodot("ATTR_REPL_IPV4_DST:", nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST));
496 IPACMDBG("ATTR_REPL_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC));
497 IPACMDBG("ATTR_REPL_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST));
498
499 iptodot("ATTR_SNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_SNAT_IPV4));
500 iptodot("ATTR_DNAT_IPV4:", nfct_get_attr_u32(ct, ATTR_DNAT_IPV4));
501 IPACMDBG("ATTR_SNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_SNAT_PORT));
502 IPACMDBG("ATTR_DNAT_PORT: 0x%x\n", nfct_get_attr_u16(ct, ATTR_DNAT_PORT));
503
504 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
505 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
506 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
507
508 status = nfct_get_attr_u32(ct, ATTR_STATUS);
509 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
510
511 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
512 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
513
514 if(IPS_SRC_NAT & status)
515 {
516 IPACMDBG("IPS_SRC_NAT set\n");
517 }
518
519 if(IPS_DST_NAT & status)
520 {
521 IPACMDBG("IPS_DST_NAT set\n");
522 }
523
524 if(IPS_SRC_NAT_DONE & status)
525 {
526 IPACMDBG("IPS_SRC_NAT_DONE set\n");
527 }
528
529 if(IPS_DST_NAT_DONE & status)
530 {
531 IPACMDBG(" IPS_DST_NAT_DONE set\n");
532 }
533
534 IPACMDBG("\n");
535 return;
536 }
537
ParseCTV6Message(struct nf_conntrack * ct)538 void ParseCTV6Message(struct nf_conntrack *ct)
539 {
540 uint32_t status, timeout;
541 struct nfct_attr_grp_ipv6 orig_params;
542 uint8_t l4proto, tcp_flags, tcp_state;
543
544 IPACMDBG("Printing conntrack parameters\n");
545
546 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
547 IPACMDBG("Orig src_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.src[0], orig_params.src[1],
548 orig_params.src[2], orig_params.src[3]);
549 IPACMDBG("Orig dst_v6_addr: 0x%08x%08x%08x%08x\n", orig_params.dst[0], orig_params.dst[1],
550 orig_params.dst[2], orig_params.dst[3]);
551
552 IPACMDBG("ATTR_PORT_SRC = ATTR_ORIG_PORT_SRC: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC));
553 IPACMDBG("ATTR_PORT_DST = ATTR_ORIG_PORT_DST: 0x%x\n", nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST));
554
555 IPACMDBG("ATTR_MARK: 0x%x\n", nfct_get_attr_u32(ct, ATTR_MARK));
556 IPACMDBG("ATTR_USE: 0x%x\n", nfct_get_attr_u32(ct, ATTR_USE));
557 IPACMDBG("ATTR_ID: 0x%x\n", nfct_get_attr_u32(ct, ATTR_ID));
558
559 timeout = nfct_get_attr_u32(ct, ATTR_TIMEOUT);
560 IPACMDBG("ATTR_TIMEOUT: 0x%x\n", timeout);
561
562 status = nfct_get_attr_u32(ct, ATTR_STATUS);
563 IPACMDBG("ATTR_STATUS: 0x%x\n", status);
564
565 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
566 IPACMDBG("ATTR_ORIG_L4PROTO: 0x%x\n", l4proto);
567 if(l4proto == IPPROTO_TCP)
568 {
569 tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE);
570 IPACMDBG("ATTR_TCP_STATE: 0x%x\n", tcp_state);
571
572 tcp_flags = nfct_get_attr_u8(ct, ATTR_TCP_FLAGS_ORIG);
573 IPACMDBG("ATTR_TCP_FLAGS_ORIG: 0x%x\n", tcp_flags);
574 }
575
576 IPACMDBG("\n");
577 return;
578 }
579
580 #ifdef CT_OPT
ProcessCTV6Message(void * param)581 void IPACM_ConntrackListener::ProcessCTV6Message(void *param)
582 {
583 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
584 u_int8_t l4proto = 0;
585 uint32_t status = 0;
586 struct nf_conntrack *ct = evt_data->ct;
587
588 #ifdef IPACM_DEBUG
589 char buf[1024];
590
591 /* Process message and generate ioctl call to kernel thread */
592 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
593 evt_data->type, NFCT_O_PLAIN, NFCT_OF_TIME);
594 IPACMDBG("%s\n", buf);
595 IPACMDBG("\n");
596 ParseCTV6Message(ct);
597 #endif
598
599 if(p_lan2lan == NULL)
600 {
601 IPACMERR("Lan2Lan Instance is null\n");
602 goto IGNORE;
603 }
604
605 status = nfct_get_attr_u32(ct, ATTR_STATUS);
606 if((IPS_DST_NAT & status) || (IPS_SRC_NAT & status))
607 {
608 IPACMDBG("Either Destination or Source nat flag Set\n");
609 goto IGNORE;
610 }
611
612 l4proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO);
613 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
614 {
615 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
616 goto IGNORE;
617 }
618
619 IPACMDBG("Neither Destination nor Source nat flag Set\n");
620 struct nfct_attr_grp_ipv6 orig_params;
621 nfct_get_attr_grp(ct, ATTR_GRP_ORIG_IPV6, (void *)&orig_params);
622
623 ipacm_event_connection lan2lan_conn;
624 lan2lan_conn.iptype = IPA_IP_v6;
625 memcpy(lan2lan_conn.src_ipv6_addr, orig_params.src,
626 sizeof(lan2lan_conn.src_ipv6_addr));
627 IPACMDBG("Before convert, src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
628 lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
629 for(int cnt=0; cnt<4; cnt++)
630 {
631 lan2lan_conn.src_ipv6_addr[cnt] = ntohl(lan2lan_conn.src_ipv6_addr[cnt]);
632 }
633 IPACMDBG("After convert src_v6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.src_ipv6_addr[0], lan2lan_conn.src_ipv6_addr[1],
634 lan2lan_conn.src_ipv6_addr[2], lan2lan_conn.src_ipv6_addr[3]);
635
636 memcpy(lan2lan_conn.dst_ipv6_addr, orig_params.dst,
637 sizeof(lan2lan_conn.dst_ipv6_addr));
638 IPACMDBG("Before convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
639 lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
640 for(int cnt=0; cnt<4; cnt++)
641 {
642 lan2lan_conn.dst_ipv6_addr[cnt] = ntohl(lan2lan_conn.dst_ipv6_addr[cnt]);
643 }
644 IPACMDBG("After convert, dst_ipv6_addr: 0x%08x%08x%08x%08x\n", lan2lan_conn.dst_ipv6_addr[0], lan2lan_conn.dst_ipv6_addr[1],
645 lan2lan_conn.dst_ipv6_addr[2], lan2lan_conn.dst_ipv6_addr[3]);
646
647 if(((IPPROTO_UDP == l4proto) && (NFCT_T_NEW == evt_data->type)) ||
648 ((IPPROTO_TCP == l4proto) &&
649 (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED))
650 )
651 {
652 p_lan2lan->handle_new_connection(&lan2lan_conn);
653 }
654 else if((IPPROTO_UDP == l4proto && NFCT_T_DESTROY == evt_data->type) ||
655 (IPPROTO_TCP == l4proto &&
656 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
657 {
658 p_lan2lan->handle_del_connection(&lan2lan_conn);
659 }
660
661 IGNORE:
662 /* Cleanup item that was allocated during the original CT callback */
663 nfct_destroy(ct);
664 return;
665 }
666 #endif
667
ProcessCTMessage(void * param)668 void IPACM_ConntrackListener::ProcessCTMessage(void *param)
669 {
670 ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param;
671 u_int8_t l4proto = 0;
672
673 #ifdef IPACM_DEBUG
674 char buf[1024];
675 unsigned int out_flags;
676
677 /* Process message and generate ioctl call to kernel thread */
678 out_flags = (NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIME | NFCT_OF_ID);
679 nfct_snprintf(buf, sizeof(buf), evt_data->ct,
680 evt_data->type, NFCT_O_PLAIN, out_flags);
681 IPACMDBG_H("%s\n", buf);
682
683 ParseCTMessage(evt_data->ct);
684 #endif
685
686 l4proto = nfct_get_attr_u8(evt_data->ct, ATTR_ORIG_L4PROTO);
687 if(IPPROTO_UDP != l4proto && IPPROTO_TCP != l4proto)
688 {
689 IPACMDBG("Received unexpected protocl %d conntrack message\n", l4proto);
690 }
691 else
692 {
693 ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto);
694 }
695
696 /* Cleanup item that was allocated during the original CT callback */
697 nfct_destroy(evt_data->ct);
698 return;
699 }
700
AddIface(nat_table_entry * rule,bool * isTempEntry)701 bool IPACM_ConntrackListener::AddIface(
702 nat_table_entry *rule, bool *isTempEntry)
703 {
704 int cnt;
705
706 *isTempEntry = false;
707
708 /* Special handling for Passthrough IP. */
709 if (IPACM_Iface::ipacmcfg->ipacm_ip_passthrough_mode)
710 {
711 if (rule->private_ip == IPACM_Wan::getWANIP())
712 {
713 IPACMDBG("In Passthrough mode and entry matched with Wan IP (0x%x)\n",
714 rule->private_ip);
715 return true;
716 }
717 }
718
719 /* check whether nat iface or not */
720 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
721 {
722 if (nat_iface_ipv4_addr[cnt] != 0)
723 {
724 if (rule->private_ip == nat_iface_ipv4_addr[cnt] ||
725 rule->target_ip == nat_iface_ipv4_addr[cnt])
726 {
727 IPACMDBG("matched nat_iface_ipv4_addr entry(%d)\n", cnt);
728 iptodot("AddIface(): Nat entry match with ip addr",
729 nat_iface_ipv4_addr[cnt]);
730 return true;
731 }
732 }
733 }
734
735 if (!isStaMode)
736 {
737 /* check whether non nat iface or not, on Non Nat iface
738 add dummy rule by copying public ip to private ip */
739 for (cnt = 0; cnt < MAX_IFACE_ADDRESS; cnt++)
740 {
741 if (nonnat_iface_ipv4_addr[cnt] != 0)
742 {
743 if (rule->private_ip == nonnat_iface_ipv4_addr[cnt] ||
744 rule->target_ip == nonnat_iface_ipv4_addr[cnt])
745 {
746 IPACMDBG("matched non_nat_iface_ipv4_addr entry(%d)\n", cnt);
747 iptodot("AddIface(): Non Nat entry match with ip addr",
748 nonnat_iface_ipv4_addr[cnt]);
749
750 rule->private_ip = rule->public_ip;
751 rule->private_port = rule->public_port;
752 return true;
753 }
754 }
755 }
756 IPACMDBG_H("Not mtaching with non-nat ifaces\n");
757 }
758 else
759 IPACMDBG("In STA mode, don't compare against non nat ifaces\n");
760
761 if(pConfig == NULL)
762 {
763 pConfig = IPACM_Config::GetInstance();
764 if(pConfig == NULL)
765 {
766 IPACMERR("Unable to get Config instance\n");
767 return false;
768 }
769 }
770
771 if (pConfig->isPrivateSubnet(rule->private_ip) ||
772 pConfig->isPrivateSubnet(rule->target_ip))
773 {
774 IPACMDBG("Matching with Private subnet\n");
775 *isTempEntry = true;
776 return true;
777 }
778
779 return false;
780 }
781
AddORDeleteNatEntry(const nat_entry_bundle * input)782 void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input)
783 {
784 u_int8_t tcp_state;
785
786 if (nat_inst == NULL)
787 {
788 IPACMERR("Nat instance is NULL, unable to add or delete\n");
789 return;
790 }
791
792 IPACMDBG_H("Below Nat Entry will either be added or deleted\n");
793 iptodot("AddORDeleteNatEntry(): target ip or dst ip",
794 input->rule->target_ip);
795 IPACMDBG("target port or dst port: 0x%x Decimal:%d\n",
796 input->rule->target_port, input->rule->target_port);
797 iptodot("AddORDeleteNatEntry(): private ip or src ip",
798 input->rule->private_ip);
799 IPACMDBG("private port or src port: 0x%x, Decimal:%d\n",
800 input->rule->private_port, input->rule->private_port);
801 IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n",
802 input->rule->public_port, input->rule->public_port);
803 IPACMDBG("Protocol: %d, destination nat flag: %d\n",
804 input->rule->protocol, input->rule->dst_nat);
805
806 if (IPPROTO_TCP == input->rule->protocol)
807 {
808 tcp_state = nfct_get_attr_u8(input->ct, ATTR_TCP_STATE);
809 if (TCP_CONNTRACK_ESTABLISHED == tcp_state)
810 {
811 IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED(%d)\n", tcp_state);
812 if (!CtList->isWanUp())
813 {
814 IPACMDBG("Wan is not up, cache connections\n");
815 nat_inst->CacheEntry(input->rule);
816 }
817 else if (input->isTempEntry)
818 {
819 nat_inst->AddTempEntry(input->rule);
820 }
821 else
822 {
823 nat_inst->AddEntry(input->rule);
824 }
825 }
826 else if (TCP_CONNTRACK_FIN_WAIT == tcp_state ||
827 input->type == NFCT_T_DESTROY)
828 {
829 IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) "
830 "or type NFCT_T_DESTROY(%d)\n", tcp_state, input->type);
831
832 nat_inst->DeleteEntry(input->rule);
833 nat_inst->DeleteTempEntry(input->rule);
834 }
835 else
836 {
837 IPACMDBG("Ignore tcp state: %d and type: %d\n",
838 tcp_state, input->type);
839 }
840
841 }
842 else if (IPPROTO_UDP == input->rule->protocol)
843 {
844 if (NFCT_T_NEW == input->type)
845 {
846 IPACMDBG("New UDP connection at time %ld\n", time(NULL));
847 if (!CtList->isWanUp())
848 {
849 IPACMDBG("Wan is not up, cache connections\n");
850 nat_inst->CacheEntry(input->rule);
851 }
852 else if (input->isTempEntry)
853 {
854 nat_inst->AddTempEntry(input->rule);
855 }
856 else
857 {
858 nat_inst->AddEntry(input->rule);
859 }
860 }
861 else if (NFCT_T_DESTROY == input->type)
862 {
863 IPACMDBG("UDP connection close at time %ld\n", time(NULL));
864 nat_inst->DeleteEntry(input->rule);
865 nat_inst->DeleteTempEntry(input->rule);
866 }
867 }
868
869 return;
870 }
871
PopulateTCPorUDPEntry(struct nf_conntrack * ct,uint32_t status,nat_table_entry * rule)872 void IPACM_ConntrackListener::PopulateTCPorUDPEntry(
873 struct nf_conntrack *ct,
874 uint32_t status,
875 nat_table_entry *rule)
876 {
877 if (IPS_DST_NAT == status)
878 {
879 IPACMDBG("Destination NAT\n");
880 rule->dst_nat = true;
881
882 IPACMDBG("Parse reply tuple\n");
883 rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
884 rule->target_ip = ntohl(rule->target_ip);
885 iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
886
887 /* Retriev target/dst port */
888 rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
889 rule->target_port = ntohs(rule->target_port);
890 if (0 == rule->target_port)
891 {
892 IPACMDBG("unable to retrieve target port\n");
893 }
894
895 rule->public_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
896 rule->public_port = ntohs(rule->public_port);
897
898 /* Retriev src/private ip address */
899 rule->private_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC);
900 rule->private_ip = ntohl(rule->private_ip);
901 iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
902 if (0 == rule->private_ip)
903 {
904 IPACMDBG("unable to retrieve private ip address\n");
905 }
906
907 /* Retriev src/private port */
908 rule->private_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC);
909 rule->private_port = ntohs(rule->private_port);
910 if (0 == rule->private_port)
911 {
912 IPACMDBG("unable to retrieve private port\n");
913 }
914 }
915 else if (IPS_SRC_NAT == status)
916 {
917 IPACMDBG("Source NAT\n");
918 rule->dst_nat = false;
919
920 /* Retriev target/dst ip address */
921 IPACMDBG("Parse source tuple\n");
922 rule->target_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
923 rule->target_ip = ntohl(rule->target_ip);
924 iptodot("PopulateTCPorUDPEntry(): target ip", rule->target_ip);
925 if (0 == rule->target_ip)
926 {
927 IPACMDBG("unable to retrieve target ip address\n");
928 }
929 /* Retriev target/dst port */
930 rule->target_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST);
931 rule->target_port = ntohs(rule->target_port);
932 if (0 == rule->target_port)
933 {
934 IPACMDBG("unable to retrieve target port\n");
935 }
936
937 /* Retriev public port */
938 rule->public_port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST);
939 rule->public_port = ntohs(rule->public_port);
940 if (0 == rule->public_port)
941 {
942 IPACMDBG("unable to retrieve public port\n");
943 }
944
945 /* Retriev src/private ip address */
946 rule->private_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
947 rule->private_ip = ntohl(rule->private_ip);
948 iptodot("PopulateTCPorUDPEntry(): private ip", rule->private_ip);
949 if (0 == rule->private_ip)
950 {
951 IPACMDBG("unable to retrieve private ip address\n");
952 }
953
954 /* Retriev src/private port */
955 rule->private_port = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC);
956 rule->private_port = ntohs(rule->private_port);
957 if (0 == rule->private_port)
958 {
959 IPACMDBG("unable to retrieve private port\n");
960 }
961 }
962
963 return;
964 }
965
966 #ifdef CT_OPT
HandleLan2Lan(struct nf_conntrack * ct,enum nf_conntrack_msg_type type,nat_table_entry * rule)967 void IPACM_ConntrackListener::HandleLan2Lan(struct nf_conntrack *ct,
968 enum nf_conntrack_msg_type type,
969 nat_table_entry *rule)
970 {
971 ipacm_event_connection lan2lan_conn = { 0 };
972
973 if (p_lan2lan == NULL)
974 {
975 IPACMERR("Lan2Lan Instance is null\n");
976 return;
977 }
978
979 lan2lan_conn.iptype = IPA_IP_v4;
980 lan2lan_conn.src_ipv4_addr = orig_src_ip;
981 lan2lan_conn.dst_ipv4_addr = orig_dst_ip;
982
983 if (((IPPROTO_UDP == rule->protocol) && (NFCT_T_NEW == type)) ||
984 ((IPPROTO_TCP == rule->protocol) && (nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_ESTABLISHED)))
985 {
986 p_lan2lan->handle_new_connection(&lan2lan_conn);
987 }
988 else if ((IPPROTO_UDP == rule->protocol && NFCT_T_DESTROY == type) ||
989 (IPPROTO_TCP == rule->protocol &&
990 nfct_get_attr_u8(ct, ATTR_TCP_STATE) == TCP_CONNTRACK_FIN_WAIT))
991 {
992 p_lan2lan->handle_del_connection(&lan2lan_conn);
993 }
994 }
995 #endif
996
CheckSTAClient(const nat_table_entry * rule,bool * isTempEntry)997 void IPACM_ConntrackListener::CheckSTAClient(
998 const nat_table_entry *rule, bool *isTempEntry)
999 {
1000 int nCnt;
1001
1002 /* Check whether target is in STA client list or not
1003 if not ignore the connection */
1004 if(!isStaMode || (StaClntCnt == 0))
1005 {
1006 return;
1007 }
1008
1009 if((sta_clnt_ipv4_addr[0] & STA_CLNT_SUBNET_MASK) !=
1010 (rule->target_ip & STA_CLNT_SUBNET_MASK))
1011 {
1012 IPACMDBG("STA client subnet mask not matching\n");
1013 return;
1014 }
1015
1016 IPACMDBG("StaClntCnt %d\n", StaClntCnt);
1017 for(nCnt = 0; nCnt < StaClntCnt; nCnt++)
1018 {
1019 IPACMDBG("Comparing trgt_ip 0x%x with sta clnt ip: 0x%x\n",
1020 rule->target_ip, sta_clnt_ipv4_addr[nCnt]);
1021 if(rule->target_ip == sta_clnt_ipv4_addr[nCnt])
1022 {
1023 IPACMDBG("Match index %d\n", nCnt);
1024 return;
1025 }
1026 }
1027
1028 IPACMDBG_H("Not matching with STA Clnt Ip Addrs 0x%x\n",
1029 rule->target_ip);
1030 *isTempEntry = true;
1031 }
1032
1033 /* 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)1034 void IPACM_ConntrackListener::ProcessTCPorUDPMsg(
1035 struct nf_conntrack *ct,
1036 enum nf_conntrack_msg_type type,
1037 u_int8_t l4proto)
1038 {
1039 nat_table_entry rule;
1040 uint32_t status = 0;
1041 uint32_t orig_src_ip, orig_dst_ip;
1042 bool isAdd = false;
1043
1044 nat_entry_bundle nat_entry;
1045 nat_entry.isTempEntry = false;
1046 nat_entry.ct = ct;
1047 nat_entry.type = type;
1048
1049 memset(&rule, 0, sizeof(rule));
1050 IPACMDBG("Received type:%d with proto:%d\n", type, l4proto);
1051 status = nfct_get_attr_u32(ct, ATTR_STATUS);
1052
1053 /* Retrieve Protocol */
1054 rule.protocol = nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO);
1055
1056 if(IPS_DST_NAT & status)
1057 {
1058 status = IPS_DST_NAT;
1059 }
1060 else if(IPS_SRC_NAT & status)
1061 {
1062 status = IPS_SRC_NAT;
1063 }
1064 else
1065 {
1066 IPACMDBG("Neither Destination nor Source nat flag Set\n");
1067 orig_src_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC);
1068 orig_src_ip = ntohl(orig_src_ip);
1069 if(orig_src_ip == 0)
1070 {
1071 IPACMERR("unable to retrieve orig src ip address\n");
1072 return;
1073 }
1074
1075 orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST);
1076 orig_dst_ip = ntohl(orig_dst_ip);
1077 if(orig_dst_ip == 0)
1078 {
1079 IPACMERR("unable to retrieve orig dst ip address\n");
1080 return;
1081 }
1082
1083 if(orig_src_ip == wan_ipaddr)
1084 {
1085 IPACMDBG("orig src ip:0x%x equal to wan ip\n",orig_src_ip);
1086 status = IPS_SRC_NAT;
1087 }
1088 else if(orig_dst_ip == wan_ipaddr)
1089 {
1090 IPACMDBG("orig Dst IP:0x%x equal to wan ip\n",orig_dst_ip);
1091 status = IPS_DST_NAT;
1092 }
1093 else
1094 {
1095 IPACMDBG_H("Neither orig src ip:0x%x Nor orig Dst IP:0x%x equal to wan ip:0x%x\n",
1096 orig_src_ip, orig_dst_ip, wan_ipaddr);
1097
1098 #ifdef CT_OPT
1099 HandleLan2Lan(ct, type, &rule);
1100 #endif
1101 return;
1102 }
1103 }
1104
1105 if(IPS_DST_NAT == status || IPS_SRC_NAT == status)
1106 {
1107 PopulateTCPorUDPEntry(ct, status, &rule);
1108 rule.public_ip = wan_ipaddr;
1109 }
1110 else
1111 {
1112 IPACMDBG("Neither source Nor destination nat\n");
1113 goto IGNORE;
1114 }
1115
1116 if (rule.private_ip != wan_ipaddr)
1117 {
1118 isAdd = AddIface(&rule, &nat_entry.isTempEntry);
1119 if (!isAdd)
1120 {
1121 goto IGNORE;
1122 }
1123 }
1124 else
1125 {
1126 if (isStaMode)
1127 {
1128 IPACMDBG("In STA mode, ignore connections destinated to STA interface\n");
1129 goto IGNORE;
1130 }
1131
1132 IPACMDBG("For embedded connections add dummy nat rule\n");
1133 IPACMDBG("Change private port %d to %d\n",
1134 rule.private_port, rule.public_port);
1135 rule.private_port = rule.public_port;
1136 }
1137
1138 CheckSTAClient(&rule, &nat_entry.isTempEntry);
1139 nat_entry.rule = &rule;
1140 AddORDeleteNatEntry(&nat_entry);
1141 return;
1142
1143 IGNORE:
1144 IPACMDBG_H("ignoring below Nat Entry\n");
1145 iptodot("ProcessTCPorUDPMsg(): target ip or dst ip", rule.target_ip);
1146 IPACMDBG("target port or dst port: 0x%x Decimal:%d\n", rule.target_port, rule.target_port);
1147 iptodot("ProcessTCPorUDPMsg(): private ip or src ip", rule.private_ip);
1148 IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port);
1149 IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port);
1150 IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat);
1151 return;
1152 }
1153
HandleSTAClientAddEvt(uint32_t clnt_ip_addr)1154 void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr)
1155 {
1156 int cnt;
1157 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1158
1159 if(StaClntCnt >= MAX_STA_CLNT_IFACES)
1160 {
1161 IPACMDBG("Max STA client reached, ignore 0x%x\n", clnt_ip_addr);
1162 return;
1163 }
1164
1165 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1166 {
1167 if(sta_clnt_ipv4_addr[cnt] != 0 &&
1168 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1169 {
1170 IPACMDBG("Ignoring duplicate one 0x%x\n", clnt_ip_addr);
1171 break;
1172 }
1173
1174 if(sta_clnt_ipv4_addr[cnt] == 0)
1175 {
1176 IPACMDBG("Adding STA client 0x%x at Index: %d\n",
1177 clnt_ip_addr, cnt);
1178 sta_clnt_ipv4_addr[cnt] = clnt_ip_addr;
1179 StaClntCnt++;
1180 IPACMDBG("STA client cnt %d\n", StaClntCnt);
1181 break;
1182 }
1183
1184 }
1185
1186 nat_inst->FlushTempEntries(clnt_ip_addr, true);
1187 return;
1188 }
1189
HandleSTAClientDelEvt(uint32_t clnt_ip_addr)1190 void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr)
1191 {
1192 int cnt;
1193 IPACMDBG_H("Received STA client 0x%x\n", clnt_ip_addr);
1194
1195 for(cnt=0; cnt<MAX_STA_CLNT_IFACES; cnt++)
1196 {
1197 if(sta_clnt_ipv4_addr[cnt] != 0 &&
1198 sta_clnt_ipv4_addr[cnt] == clnt_ip_addr)
1199 {
1200 IPACMDBG("Deleting STA client 0x%x at index: %d\n",
1201 clnt_ip_addr, cnt);
1202 sta_clnt_ipv4_addr[cnt] = 0;
1203 nat_inst->DelEntriesOnSTAClntDiscon(clnt_ip_addr);
1204 StaClntCnt--;
1205 IPACMDBG("STA client cnt %d\n", StaClntCnt);
1206 break;
1207 }
1208 }
1209
1210 nat_inst->FlushTempEntries(clnt_ip_addr, false);
1211 return;
1212 }
1213