summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/ip_module/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'stacks/lwip_stack/lwip_src/ip_module/network.c')
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/network.c1093
1 files changed, 1093 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/ip_module/network.c b/stacks/lwip_stack/lwip_src/ip_module/network.c
new file mode 100644
index 0000000..d34c6a9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/network.c
@@ -0,0 +1,1093 @@
+/*
+*
+* 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 <stdio.h>
+#include <sys/socket.h>
+#include <string.h>
+#include "json.h"
+#include "trp_rb_tree.h"
+#include "network.h"
+#include "nstack_log.h"
+#include "config_common.h"
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+#include "sharedmemory.h"
+#include "nstack_securec.h"
+#include "spl_hal.h"
+#include "inet.h"
+
+struct network_list g_network_list = { 0 };
+
+extern struct stackx_port_zone *p_stackx_port_zone;
+extern u32 spl_hal_is_nic_exist(const char *name);
+
+static bool_t is_phy_net_ok(struct phy_net *pst_phy_net)
+{
+ if (!pst_phy_net || !pst_phy_net->header)
+ {
+ NSOPR_LOGERR("phy_net is not ok");
+ return 0;
+ }
+
+ return 1;
+}
+
+static bool_t
+is_network_configuration_ok(struct network_configuration *network)
+{
+ while (network)
+ {
+ if (!is_phy_net_ok(network->phy_net))
+ {
+ return 0;
+ }
+
+ network = network->next;
+ }
+
+ return 1;
+}
+
+static void
+add_ref_nic(struct phy_net *pst_phy_net, struct ref_nic *pst_ref_nic)
+{
+ pst_ref_nic->next = pst_phy_net->header;
+ pst_phy_net->header = pst_ref_nic;
+}
+
+static void free_ref_nic(struct ref_nic *pst_ref_nic)
+{
+ struct ref_nic *nic = pst_ref_nic;
+ struct ref_nic *tmp = NULL;
+
+ while (nic)
+ {
+ tmp = nic;
+ nic = tmp->next;
+ free(tmp);
+ }
+}
+
+static void free_phy_net(struct phy_net *pst_phy_net)
+{
+ if (pst_phy_net)
+ {
+ free_ref_nic(pst_phy_net->header);
+ free(pst_phy_net);
+ }
+}
+
+static void free_ip_subnet(struct ip_subnet *subnet, bool_t only_free)
+{
+ struct ip_subnet *tmp = NULL;
+
+ while (subnet)
+ {
+ tmp = subnet;
+ subnet = subnet->next;
+ free(tmp);
+ }
+}
+
+void
+free_network_configuration(struct network_configuration *network,
+ bool_t only_free)
+{
+ if (network)
+ {
+ free_ip_subnet(network->ip_subnet, only_free);
+ free_phy_net(network->phy_net);
+
+ if (network->buffer)
+ {
+ free_network_buffer(network->buffer);
+ network->buffer = NULL;
+ }
+
+ free(network);
+ }
+}
+
+inline int is_in_subnet(unsigned int ip, struct ip_subnet *subnet)
+{
+ unsigned int mask = ~0;
+ unsigned int seg_ip, seg;
+
+ mask = mask << (IP_MODULE_SUBNET_MASK_LEN - subnet->mask_len);
+
+ seg_ip = ip & mask;
+ seg = subnet->subnet & mask;
+
+ return seg_ip != seg ? 1 : 0;
+}
+
+inline struct network_configuration *get_network_by_ip_with_tree(unsigned int
+ ip)
+{
+ unsigned int h_ip = spl_ntohl(ip);
+ struct network_configuration *p = g_network_list.header;
+
+ while (p)
+ {
+ if (!is_in_subnet(h_ip, p->ip_subnet))
+ {
+ return p;
+ }
+
+ p = p->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *get_network_by_name(char *name)
+{
+ struct network_configuration *network = g_network_list.header;
+
+ while (network)
+ {
+ if (strcasecmp(name, network->network_name) == 0)
+ {
+ return network;
+ }
+
+ network = network->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *get_network_by_nic_name(char *name)
+{
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ struct ref_nic *refnic = NULL;
+ struct phy_net *phynet = NULL;
+ struct network_configuration *network = g_network_list.header;
+ while (network)
+ {
+ phynet = network->phy_net;
+ if (phynet)
+ {
+ if ((phynet->bond_mode != -1)
+ && strcmp(name, phynet->bond_name) == 0)
+ {
+ return network;
+ }
+
+ refnic = phynet->header;
+ while (refnic)
+ {
+ if (strcmp(name, refnic->nic_name) == 0)
+ {
+ return network;
+ }
+
+ refnic = refnic->next;
+ }
+ }
+
+ network = network->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *get_network_by_name_from_json(struct
+ network_configuration
+ *network)
+{
+ char *name = network->network_name;
+ struct network_configuration *tmp = network->next;
+
+ while (tmp)
+ {
+ if (strcasecmp(name, tmp->network_name) == 0)
+ {
+ return tmp;
+ }
+
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
+
+NSTACK_STATIC inline int get_network_count()
+{
+ int count = 0;
+ struct network_configuration *network = g_network_list.header;
+
+ while (network)
+ {
+ count++;
+ network = network->next;
+ }
+
+ return count;
+}
+
+int get_network_all(char *jsonBuf, size_t size)
+{
+ if (NULL == jsonBuf)
+ {
+ return NSCRTL_ERR;
+ }
+
+ if (size < 2)
+ {
+ NSOPR_LOGERR("get all ip cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ int retVal;
+ char bfirstData = 1;
+ *jsonBuf = '[';
+ jsonBuf = jsonBuf + 1;
+
+ size_t len = size - 2; // strlen("[]")
+ size_t strsize = 0;
+ struct network_configuration *network = g_network_list.header;
+ while (network)
+ {
+ if (NULL == network->buffer)
+ {
+ network = network->next;
+ continue;
+ }
+
+ if (bfirstData)
+ {
+ bfirstData = 0;
+ }
+ else
+ {
+ *jsonBuf = ',';
+ jsonBuf = jsonBuf + 1;
+ len = len - 1;
+ }
+
+ strsize = strlen(get_network_json(network)) + 1;
+ if ((strsize > 0) && (strsize < len))
+ {
+ retVal = strcpy_s(jsonBuf, len, get_network_json(network));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal);
+ return NSCRTL_STATUS_ERR;
+ }
+
+ len = len - strlen(get_network_json(network));
+ jsonBuf = jsonBuf + strlen(get_network_json(network));
+ }
+ else
+ {
+ NSOPR_LOGERR("get all network cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ network = network->next;
+ }
+
+ *jsonBuf = ']';
+ return 0;
+}
+
+int nic_already_bind(const char *nic_name)
+{
+ struct ref_nic *pnic = NULL;
+ struct network_configuration *pnetwork = g_network_list.header;
+
+ while (pnetwork)
+ {
+ pnic = pnetwork->phy_net->header;
+ while (pnic)
+ {
+ if (0 == strcmp(pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+
+ pnic = pnic->next;
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+int nic_already_init(const char *nic_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < p_stackx_port_zone->port_num; i++)
+ {
+ if (0 ==
+ strcmp(p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name,
+ nic_name))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+extern struct stackx_port_info *head_used_port_list;
+int
+bonded_nic_already_bind(struct network_configuration *pnetwork,
+ const char *nic_name)
+{
+ struct stackx_port_info *p_port_list = head_used_port_list;
+
+ while (p_port_list)
+ {
+ if (0 == strcmp(p_port_list->linux_ip.if_name, nic_name))
+ {
+ return 1;
+ }
+
+ p_port_list = p_port_list->next_use_port;
+ }
+
+ struct ref_nic *pnic = NULL;
+
+ while (pnetwork)
+ {
+ if (pnetwork->phy_net->bond_mode == -1)
+ {
+ pnic = pnetwork->phy_net->header;
+ if (0 == strcmp(pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+extern struct bond_ports_info bond_ports_array;
+int
+nic_already_bond(struct network_configuration *pnetwork, const char *nic_name)
+{
+ u8_t i, j;
+ struct bond_set *s;
+
+ for (i = 0; i < bond_ports_array.cnt; i++)
+ {
+ s = &bond_ports_array.ports[i];
+ for (j = 0; j < s->slave_port_cnt; j++)
+ {
+ if (strcmp(s->slave_ports[j], nic_name) == 0)
+ {
+ return 1;
+ }
+ }
+ }
+
+ struct ref_nic *pnic = NULL;
+
+ while (pnetwork)
+ {
+ if (pnetwork->phy_net->bond_mode != -1)
+ {
+ pnic = pnetwork->phy_net->header;
+ while (pnic)
+ {
+ if (0 == strcmp(pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+
+ pnic = pnic->next;
+ }
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+/* add network to list in descending sort */
+void add_network_to_list(struct network_configuration *network)
+{
+ struct network_configuration *curr = g_network_list.header;
+ struct network_configuration *prev = NULL;
+
+ network->next = NULL;
+
+ while (curr)
+ {
+ if (network->ip_subnet->mask_len >= curr->ip_subnet->mask_len)
+ {
+ break;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (NULL == prev)
+ {
+ network->next = curr;
+ g_network_list.header = network;
+ }
+ else
+ {
+ network->next = prev->next;
+ prev->next = network;
+ }
+}
+
+int
+add_network_configuration(struct network_configuration
+ *pst_network_configuration)
+{
+ struct network_configuration *tmp = pst_network_configuration;
+ struct ref_nic *pheader;
+
+ if (tmp)
+ {
+ if (get_network_by_name(tmp->network_name)
+ || get_network_by_name_from_json(tmp))
+ {
+ NSOPR_LOGERR("network exists or duplicates]network_name=%s",
+ tmp->network_name);
+ free_network_configuration(pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_RD_EXIST;
+ }
+
+ if (strcasecmp("nstack-dpdk", tmp->type_name) != 0)
+ {
+ NSOPR_LOGWAR("illegal network type]type_name=%s", tmp->type_name);
+ }
+
+ /* control max network and ipaddress count */
+ if (get_network_count() >= MAX_NETWORK_COUNT)
+ {
+ NSOPR_LOGERR("network reach]max_count=%d", MAX_NETWORK_COUNT);
+ free_network_configuration(pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_NETWORK_COUNT_EXCEED;
+ }
+
+ /* If nic is not existed or not initiated, return error */
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (!spl_hal_is_nic_exist(pheader->nic_name)
+ && !nic_already_init(pheader->nic_name)
+ && strncmp(tmp->nic_type_name, "vhost", strlen("vhost")))
+ {
+ NSOPR_LOGERR("Invalid configuration %s not exist Error! ",
+ pheader->nic_name);
+ free_network_configuration(pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_RD_NOT_EXIST;
+ }
+
+ pheader = pheader->next;
+ }
+
+ /* if a bonded nic has been inited in a non-bond network, return error */
+ if (tmp->phy_net->bond_mode != -1)
+ {
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (bonded_nic_already_bind
+ (pst_network_configuration, pheader->nic_name))
+ {
+ NSOPR_LOGERR("Invalid configuration %s already bind! ",
+ pheader->nic_name);
+ free_network_configuration(pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_INPUT_ERR;
+ }
+
+ pheader = pheader->next;
+ }
+ }
+
+ /* if a non-bond nic has been inited in a bonded network, return error */
+ if (tmp->phy_net->bond_mode == -1)
+ {
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (nic_already_bond
+ (pst_network_configuration, pheader->nic_name))
+ {
+ NSOPR_LOGERR("Invalid configuration %s already bind! ",
+ pheader->nic_name);
+ free_network_configuration(pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_INPUT_ERR;
+ }
+
+ pheader = pheader->next;
+ }
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("Invalid network configuration!");
+ return NSCRTL_INPUT_ERR;
+ }
+
+ /*looping through each node has move to read_ipmoduleoperateadd_configuration */
+ ip_subnet_print(tmp->ip_subnet);
+ add_network_to_list(tmp);
+
+ return NSCRTL_OK;
+}
+
+struct network_configuration *parse_network_obj(struct json_object
+ *network_obj)
+{
+ int retVal;
+ struct network_configuration *pst_network_configuration = NULL;
+ struct json_object *network_name_obj = NULL, *args_obj = NULL, *phy_obj =
+ NULL, *type_name_obj = NULL;
+ struct json_object *ref_nic_list_obj = NULL, *bond_mode_obj =
+ NULL, *bond_name_obj = NULL, *ipam_obj = NULL;
+ struct json_object *subnet_obj = NULL, *nic_type_obj = NULL;
+
+ if (!network_obj)
+ {
+ NSOPR_LOGERR("network_obj is null");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration = malloc(sizeof(struct network_configuration));
+ if (NULL == pst_network_configuration)
+ {
+ NSOPR_LOGERR("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ memset_s(pst_network_configuration,
+ sizeof(struct network_configuration), 0,
+ sizeof(struct network_configuration));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(network_obj, "name", &network_name_obj);
+ if (network_name_obj)
+ {
+ const char *network_name = json_object_get_string(network_name_obj);
+ if ((NULL == network_name) || (network_name[0] == 0)
+ || (strlen(network_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR("network_name is not ok");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(pst_network_configuration->network_name,
+ sizeof(pst_network_configuration->network_name),
+ network_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("name is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(network_obj, "type", &type_name_obj);
+ if (type_name_obj)
+ {
+ const char *type_name = json_object_get_string(type_name_obj);
+ if ((NULL == type_name) || (type_name[0] == 0)
+ || (strlen(type_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR("type parse error");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(pst_network_configuration->type_name,
+ sizeof(pst_network_configuration->type_name), type_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRCPY_S failed]ret=%d", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("type is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(network_obj, "args", &args_obj);
+ if (args_obj)
+ {
+ json_object_object_get_ex(args_obj, "phynet", &phy_obj);
+ if (phy_obj)
+ {
+ struct phy_net *pst_phy_net = malloc(sizeof(struct phy_net));
+ if (NULL == pst_phy_net)
+ {
+ NSOPR_LOGERR("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ memset_s(pst_phy_net, sizeof(struct phy_net), 0,
+ sizeof(struct phy_net));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d", retVal);
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(phy_obj, "nic_type", &nic_type_obj); /*lint !e534 no need to check return value */
+ if (nic_type_obj)
+ {
+ const char *nic_type_name =
+ json_object_get_string(nic_type_obj);
+ if (strcmp(nic_type_name, "pci") != 0
+ && strcmp(nic_type_name, "vhost") != 0)
+ {
+ NSOPR_LOGERR("unsupported nic_type]nic_type=%s",
+ nic_type_name);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(pst_network_configuration->nic_type_name,
+ sizeof(pst_network_configuration->nic_type_name),
+ nic_type_name);
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGINF
+ ("nic_type not specified, use default type]defaul nic_type=pci");
+ retVal =
+ strcpy_s(pst_network_configuration->nic_type_name,
+ sizeof(pst_network_configuration->nic_type_name),
+ "pci");
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+
+ json_object_object_get_ex(phy_obj, "ref_nic", &ref_nic_list_obj);
+ if (ref_nic_list_obj)
+ {
+ int j;
+ int ref_nic_num = json_object_array_length(ref_nic_list_obj);
+ if (0 == ref_nic_num)
+ {
+ NSOPR_LOGERR("ref_nic is empty");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ for (j = ref_nic_num - 1; j >= 0; j--)
+ {
+ struct json_object *ref_nic_obj =
+ json_object_array_get_idx(ref_nic_list_obj, j);
+ if (ref_nic_obj)
+ {
+ const char *nic_name =
+ json_object_get_string(ref_nic_obj);
+ if ((NULL == nic_name) || (nic_name[0] == 0)
+ || (strlen(nic_name) >= HAL_MAX_NIC_NAME_LEN))
+ {
+ NSOPR_LOGERR("nic_name is not ok");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ struct ref_nic *pst_ref_nic =
+ malloc(sizeof(struct ref_nic));
+ if (NULL == pst_ref_nic)
+ {
+ NSOPR_LOGERR("malloc failed");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ memset_s(pst_ref_nic, sizeof(struct ref_nic), 0,
+ sizeof(struct ref_nic));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal);
+ free(pst_ref_nic);
+ pst_ref_nic = NULL;
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(pst_ref_nic->nic_name,
+ sizeof(pst_ref_nic->nic_name), nic_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal);
+ free(pst_ref_nic);
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ add_ref_nic(pst_phy_net, pst_ref_nic);
+ }
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("ref_nic is not ok");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(phy_obj, "bond_mode", &bond_mode_obj);
+ if (bond_mode_obj)
+ {
+ pst_phy_net->bond_mode = json_object_get_int(bond_mode_obj);
+ if (pst_phy_net->bond_mode != -1)
+ {
+ json_object_object_get_ex(phy_obj, "bond_name",
+ &bond_name_obj);
+ if (bond_name_obj)
+ {
+ const char *bond_name =
+ json_object_get_string(bond_name_obj);
+ if ((NULL == bond_name)
+ || (strlen(bond_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR("bond_name is not ok");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ memset_s(pst_phy_net->bond_name,
+ sizeof(pst_phy_net->bond_name), 0,
+ sizeof(pst_phy_net->bond_name));
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal);
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strncpy_s(pst_phy_net->bond_name,
+ sizeof(pst_phy_net->bond_name),
+ bond_name, strlen(bond_name));
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRNCPY_S failed]retVal=%d",
+ retVal);
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("bond_name is not ok");
+ free_phy_net(pst_phy_net);
+ goto RETURN_ERROR;
+ }
+ }
+ }
+ else
+ {
+ pst_phy_net->bond_mode = -1;
+ }
+
+ pst_network_configuration->phy_net = pst_phy_net;
+ }
+ else
+ {
+ NSOPR_LOGERR("phy_net is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("args is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex(network_obj, "ipam", &ipam_obj);
+ if (ipam_obj)
+ {
+ json_object_object_get_ex(ipam_obj, "subnet", &subnet_obj);
+ if (subnet_obj)
+ {
+ int iRet;
+ char tmp[IP_MODULE_LENGTH_32] = { 0 };
+ const char *subnet = json_object_get_string(subnet_obj);
+ struct in_addr addr;
+
+ retVal = memset_s(&addr, sizeof(addr), 0, sizeof(addr));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ if ((NULL == subnet) || (subnet[0] == 0)
+ || (strlen(subnet) > IP_MODULE_LENGTH_32))
+ {
+ NSOPR_LOGERR("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ const char *sub = strstr(subnet, "/");
+ if ((NULL == sub)
+ || (sizeof(tmp) - 1 <= (unsigned int) (sub - subnet))
+ || (strlen(sub) >= sizeof(tmp) - 1))
+ {
+ NSOPR_LOGERR("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ iRet =
+ strncpy_s(tmp, sizeof(tmp), subnet, (size_t) (sub - subnet));
+ if (EOK != iRet)
+ {
+ NSOPR_LOGERR("STRNCPY_S failed]ret=%d", iRet);
+ goto RETURN_ERROR;
+ }
+
+ iRet = spl_inet_aton(tmp, &addr);
+ if (0 == iRet)
+ {
+ NSOPR_LOGERR("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet =
+ (struct ip_subnet *) malloc(sizeof(struct ip_subnet));
+ if (!pst_network_configuration->ip_subnet)
+ {
+ NSOPR_LOGERR("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ memset_s(pst_network_configuration->ip_subnet,
+ sizeof(struct ip_subnet), 0,
+ sizeof(struct ip_subnet));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet->next = NULL;
+ pst_network_configuration->ip_subnet->subnet =
+ spl_ntohl(addr.s_addr);
+
+ iRet = atoi(sub + 1);
+ if ((iRet < 0) || (iRet > IP_MODULE_LENGTH_32))
+ {
+ NSOPR_LOGERR("mask is not ok");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet->mask_len =
+ (unsigned int) iRet;
+ }
+ else
+ {
+ NSOPR_LOGERR("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR("ipam is not ok");
+ goto RETURN_ERROR;
+ }
+
+ const char *network_json = json_object_get_string(network_obj);
+ if ((NULL == network_json) || (network_json[0] == 0))
+ {
+ NSOPR_LOGERR("json_object_get_string failed");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->buffer = malloc_network_buffer();
+ if (!pst_network_configuration->buffer)
+ {
+ NSOPR_LOGERR("malloc_network_buffer failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(get_network_json(pst_network_configuration),
+ IP_MODULE_NETWORK_JSON_LEN, network_json);
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("STRCPY_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ return pst_network_configuration;
+
+ RETURN_ERROR:
+ if (pst_network_configuration)
+ {
+ free_network_configuration(pst_network_configuration, IP_MODULE_TRUE);
+ pst_network_configuration = NULL;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *parse_network_json(char *param,
+ struct network_configuration
+ *pnetwork_list)
+{
+ struct json_object *obj = json_tokener_parse(param);
+ struct network_configuration *pst_network_configuration = NULL;
+
+ if (!obj)
+ {
+ NSOPR_LOGERR("parse error");
+ return NULL;
+ }
+
+ int network_num = json_object_array_length(obj);
+ if (0 == network_num)
+ {
+ json_object_put(obj);
+ return NULL;
+ }
+
+ int i;
+ for (i = 0; i < network_num; i++)
+ {
+ struct json_object *network_obj = json_object_array_get_idx(obj, i);
+ if (network_obj)
+ {
+ pst_network_configuration = parse_network_obj(network_obj);
+ if (!pst_network_configuration)
+ {
+ NSOPR_LOGERR("parse_network_obj error");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->next = pnetwork_list;
+ pnetwork_list = pst_network_configuration;
+ pst_network_configuration = NULL;
+ }
+ else
+ {
+ NSOPR_LOGERR("network_obj is NULL");
+ goto RETURN_ERROR;
+ }
+ }
+
+ if (pnetwork_list)
+ {
+ if (!is_network_configuration_ok(pnetwork_list))
+ {
+ NSOPR_LOGERR("network_configuration is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+
+ json_object_put(obj);
+ return pnetwork_list;
+
+ RETURN_ERROR:
+ free_network_configuration(pnetwork_list, IP_MODULE_TRUE);
+ json_object_put(obj);
+ return NULL;
+}
+
+int del_network_by_name(char *name)
+{
+ struct network_configuration *network = NULL;
+ struct network_configuration **ref = &g_network_list.header;
+
+ while ((network = *ref))
+ {
+ if (strcasecmp(name, network->network_name) == 0)
+ {
+ *ref = network->next;
+ network->next = NULL;
+
+ free_network_configuration(network, IP_MODULE_FALSE);
+ return 0;
+ }
+
+ ref = &network->next;
+ }
+
+ return NSCRTL_RD_NOT_EXIST;
+}
+
+int is_in_same_network(unsigned int src_ip, unsigned int dst_ip)
+{
+ if (src_ip == dst_ip)
+ {
+ return 1;
+ }
+
+ struct network_configuration *src = get_network_by_ip_with_tree(src_ip);
+ struct network_configuration *dst = get_network_by_ip_with_tree(dst_ip);
+ if (src && (src == dst))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+struct network_configuration *get_network_list()
+{
+ return g_network_list.header;
+}