/* * * Copyright (c) 2018 Huawei Technologies Co.,Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "nstack_rd_data.h" #include "nstack_rd.h" #include "nstack_rd_init.h" #include "nstack_rd_priv.h" #include "nstack_rd_ip.h" #include "nstack_log.h" #include "nstack_securec.h" #include "nstack_ip_addr.h" #define NSTACK_IP_MLSTACKID RD_LWIP #define PP_HTONL(x) ((((x) & 0xff) << 24) | \ (((x) & 0xff00) << 8) | \ (((x) & 0xff0000UL) >> 8) | \ (((x) & 0xff000000UL) >> 24)) #define rd_ismulticast(addr)(((unsigned int)(addr) & 0xf0000000UL) == 0xe0000000UL) int g_multi_stackid = -1; /*copy rd data*/ int nstack_rd_ipdata_cpy (void *destdata, void *srcdata) { rd_data_item *pitem = (rd_data_item *) destdata; rd_route_data *pdata = (rd_route_data *) srcdata; pitem->type = pdata->type; pitem->ipdata.addr = pdata->ipdata.addr; pitem->ipdata.masklen = pdata->ipdata.masklen; pitem->ipdata.resev[0] = pdata->ipdata.resev[0]; pitem->ipdata.resev[1] = pdata->ipdata.resev[1]; return NSTACK_RD_SUCCESS; } /* * Add an ip segment to the list and sort it in descending order of ip mask length * If the list already exists in the same list of ip side, then stack_id update *ip is local byteorder */ int nstack_rd_ip_item_insert (nstack_rd_list * hlist, void *rditem) { nstack_rd_node *pdatanode = NULL; nstack_rd_node *tempdata = NULL; struct hlist_node *tempnode = NULL; struct hlist_node *tem = NULL; unsigned int tempip_addr = 0; unsigned int tempip_masklen = 0; rd_data_item *pitem = (rd_data_item *) rditem; unsigned int ip_addr = pitem->ipdata.addr; unsigned int ip_masklen = pitem->ipdata.masklen; unsigned int ip_maskv = MASK_V (ip_addr, ip_masklen); ip_masklen = pitem->ipdata.masklen; NSSOC_LOGDBG ("stackid:%d, ipaddr:%u.%u.%u.%u masklen:0x%x was inserted", pitem->stack_id, ip4_addr4_16 (&pitem->ipdata.addr), ip4_addr3_16 (&pitem->ipdata.addr), ip4_addr2_16 (&pitem->ipdata.addr), ip4_addr1_16 (&pitem->ipdata.addr), pitem->ipdata.masklen); pdatanode = (nstack_rd_node *) malloc (sizeof (nstack_rd_node)); if (!pdatanode) { NSSOC_LOGERR ("nstack rd item malloc fail"); return NSTACK_RD_FAIL; } int retVal = MEMSET_S (pdatanode, sizeof (nstack_rd_node), 0, sizeof (nstack_rd_node)); if (EOK != retVal) { NSSOC_LOGERR ("MEMSET_S failed]retVal=%d", retVal); free (pdatanode); return NSTACK_RD_FAIL; } INIT_HLIST_NODE (&pdatanode->rdnode); NSTACK_RD_IP_ITEM_COPY (&(pdatanode->item), pitem); if (hlist_empty (&(hlist->headlist))) { hlist_add_head (&(pdatanode->rdnode), &(hlist->headlist)); return NSTACK_RD_SUCCESS; } hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) { tem = tempnode; tempip_addr = tempdata->item.ipdata.addr; tempip_masklen = tempdata->item.ipdata.masklen; if (ip_masklen < tempip_masklen) { continue; } /*if already exist, just return success */ if (ip_maskv == MASK_V (tempip_addr, tempip_masklen)) { NSSOC_LOGDBG ("insert ip:%u.%u.%u.%u, mask:0x%x, stack_id:%d, exist orgid:%d", ip4_addr4_16 (&pitem->ipdata.addr), ip4_addr3_16 (&pitem->ipdata.addr), ip4_addr2_16 (&pitem->ipdata.addr), ip4_addr1_16 (&pitem->ipdata.addr), pitem->ipdata.masklen, pitem->stack_id, tempdata->item.stack_id); tempdata->item.stack_id = pitem->stack_id; tempdata->item.agetime = NSTACK_RD_AGETIME_MAX; free (pdatanode); return NSTACK_RD_SUCCESS; } hlist_add_before (&(pdatanode->rdnode), tempnode); return NSTACK_RD_SUCCESS; } hlist_add_after (tem, &(pdatanode->rdnode)); return NSTACK_RD_SUCCESS; } /* *find stackid by ip *input ip must netorder */ int nstack_rd_ip_item_find (nstack_rd_list * hlist, void *rdkey, void *outitem) { struct hlist_node *tempnode = NULL; nstack_rd_node *tempdata = NULL; unsigned int tempip_addr = 0; unsigned int tempip_masklen = 0; nstack_rd_key *key = (nstack_rd_key *) rdkey; rd_data_item *pitem = (rd_data_item *) outitem; unsigned int ip_addr = 0; /*need to convert to local order */ ip_addr = ntohl (key->ip_addr); hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) { tempip_addr = tempdata->item.ipdata.addr; tempip_masklen = tempdata->item.ipdata.masklen; /*if already exist, just return success */ if (MASK_V (ip_addr, tempip_masklen) == MASK_V (tempip_addr, tempip_masklen)) { NSTACK_RD_IP_ITEM_COPY (pitem, &(tempdata->item)); return NSTACK_RD_SUCCESS; } } NSSOC_LOGDBG ("ip=%u.%u.%u.%u item not found", ip4_addr4_16 (&ip_addr), ip4_addr3_16 (&ip_addr), ip4_addr2_16 (&ip_addr), ip4_addr1_16 (&ip_addr)); return NSTACK_RD_FAIL; } /***************************************************************************** * Prototype : nstack_rd_ip_item_age * Description : delete the ip item that have not been add again for one time * Input : nstack_rd_list *hlist * Output : None * Return Value : int * Calls : * Called By : *****************************************************************************/ int nstack_rd_ip_item_age (nstack_rd_list * hlist) { struct hlist_node *tempnode = NULL; nstack_rd_node *tempdata = NULL; nstack_rd_node *prevdata = NULL; struct hlist_node *prevnode = NULL; NSSOC_LOGINF ("nstack rd ip age begin"); hlist_for_each_entry (tempdata, tempnode, &(hlist->headlist), rdnode) { /*if agetime equal 0, remove it */ if (tempdata->item.agetime <= 0) { if (prevdata) { NSSOC_LOGDBG ("stackid:%d, addrip:%u.%u.%u.%u, masklen:0x%x was aged", tempdata->item.stack_id, ip4_addr4_16 (&tempdata->item.ipdata.addr), ip4_addr3_16 (&tempdata->item.ipdata.addr), ip4_addr2_16 (&tempdata->item.ipdata.addr), ip4_addr1_16 (&tempdata->item.ipdata.addr), tempdata->item.ipdata.masklen); hlist_del_init (prevnode); free (prevdata); } prevdata = tempdata; prevnode = tempnode; } else { tempdata->item.agetime--; } } if (prevdata) { if (tempdata) { NSSOC_LOGDBG ("stackid:%d, addrip:%u.%u.%u.%u, masklen:0x%x was last aged", tempdata->item.stack_id, ip4_addr4_16 (&tempdata->item.ipdata.addr), ip4_addr3_16 (&tempdata->item.ipdata.addr), ip4_addr2_16 (&tempdata->item.ipdata.addr), ip4_addr1_16 (&tempdata->item.ipdata.addr), tempdata->item.ipdata.masklen); } hlist_del_init (prevnode); free (prevdata); } NSSOC_LOGINF ("nstack rd ip age end"); return NSTACK_RD_SUCCESS; } /* *find stackid by spec ip(multicast ip) *input ip must netorder */ int nstack_rd_ip_spec (void *rdkey) { nstack_rd_key *key = (nstack_rd_key *) rdkey; unsigned int ip_addr = 0; ip_addr = ntohl (key->ip_addr); if (rd_ismulticast (ip_addr)) { if (-1 == g_multi_stackid) { g_multi_stackid = nstack_get_stackid_byname (NSTACK_IP_MLSTACKID); } return g_multi_stackid; } return -1; } int nstack_rd_ip_default (void *rdkey) { return NSTACK_GET_STACK (0); }