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 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 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 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 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 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 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 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 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 } 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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