2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <unistd.h>
|
2019-08-02 09:47:38 +00:00
|
|
|
|
#include "list.h"
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
#include "configm.h"
|
|
|
|
|
#include "brconfig.h"
|
|
|
|
|
#include "rpc.h"
|
|
|
|
|
#include "parsefile.h"
|
|
|
|
|
#include "brnetlink.h"
|
2019-08-02 06:59:46 +00:00
|
|
|
|
#include "parsefile.h"
|
2019-08-02 09:47:38 +00:00
|
|
|
|
#include "libbridge.h"
|
2019-08-02 10:49:50 +00:00
|
|
|
|
#include "libbridge_private.h"
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 事件通知函数 */
|
2019-08-02 10:49:50 +00:00
|
|
|
|
br_event_head_t br_event_tbl = {.head.first = NULL, .lock = 0, .init = FALSE};
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
int br_invoke_event(BR_EVENT_TYPE event_type, br_event_t event_arg)
|
|
|
|
|
{
|
|
|
|
|
br_event_node_t *hnode;
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&(br_event_tbl.lock));
|
|
|
|
|
hlist_for_each_entry(hnode, &(br_event_tbl.head), list)
|
|
|
|
|
{
|
|
|
|
|
if(hnode->br_event == event_type)
|
|
|
|
|
{
|
|
|
|
|
hnode->event_func(event_type, event_arg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&(br_event_tbl.lock));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int br_event_register(BR_EVENT_TYPE event_type, BR_EVENT_FUNC event_func)
|
|
|
|
|
{
|
|
|
|
|
br_event_node_t *hnode = NULL;
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
if(br_event_tbl.init == FALSE)
|
2019-08-02 10:11:34 +00:00
|
|
|
|
{
|
|
|
|
|
INIT_HLIST_HEAD(&(br_event_tbl.head));
|
2019-08-01 10:22:48 +00:00
|
|
|
|
pthread_mutex_init(&(br_event_tbl.lock), NULL);
|
2019-08-02 10:49:50 +00:00
|
|
|
|
br_event_tbl.init = TRUE;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hnode = (br_event_node_t *)rpc_new0(br_event_node_t, 1);
|
|
|
|
|
if(!hnode)
|
|
|
|
|
{
|
|
|
|
|
rpc_log_error("br_event_register failed\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
INIT_HLIST_NODE(&hnode->list);
|
|
|
|
|
hnode->br_event = event_type;
|
|
|
|
|
hnode->event_func = event_func;
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&(br_event_tbl.lock));
|
|
|
|
|
hlist_add_head(&hnode->list, &(br_event_tbl.head));
|
|
|
|
|
pthread_mutex_unlock(&(br_event_tbl.lock));
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_event_unregister(BR_EVENT_TYPE event_type, BR_EVENT_FUNC event_func)
|
|
|
|
|
{
|
|
|
|
|
br_event_node_t *hnode = NULL;
|
|
|
|
|
struct hlist_node *n;
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
if(br_event_tbl.init == FALSE)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&(br_event_tbl.lock));
|
|
|
|
|
hlist_for_each_entry_safe(hnode, n, &(br_event_tbl.head), list)
|
|
|
|
|
{
|
|
|
|
|
if(event_type == hnode->br_event &&
|
|
|
|
|
event_func == hnode->event_func)
|
|
|
|
|
{
|
|
|
|
|
hlist_del(&hnode->list);
|
|
|
|
|
rpc_free(hnode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&(br_event_tbl.lock));
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥配置辅助函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
int br_copy_port_name(const char *b, const char *p, void *arg)
|
|
|
|
|
{
|
|
|
|
|
br_if_temp_t *br_if = (br_if_temp_t *)arg;
|
|
|
|
|
char *dst_ptr = NULL;
|
|
|
|
|
|
|
|
|
|
br_if->if_list = realloc(br_if->if_list, INTERFACE_NAMSIZ);
|
|
|
|
|
ASSERT_PTR_RET(br_if->if_list);
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
dst_ptr = br_if->if_list + br_if->index * INTERFACE_NAMSIZ;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
strncpy(dst_ptr, p, INTERFACE_NAMSIZ - 1);
|
|
|
|
|
|
|
|
|
|
br_if->index++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_name_chk(char *br_name)
|
|
|
|
|
{
|
|
|
|
|
if(strlen(br_name) == 0
|
|
|
|
|
|| strlen(br_name) > BR_NAMSIZ - 1
|
|
|
|
|
|| strstr(br_name, "br-vl") != NULL)
|
|
|
|
|
{
|
|
|
|
|
return RET_BR_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
int br_name_cmp(const char *br_name, void *args)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
br_temp_t *cmp_args = (br_temp_t *)args;
|
|
|
|
|
|
|
|
|
|
if(strcmp(br_name, cmp_args->br_name) == 0)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
cmp_args->result = TRUE;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boolean br_is_exist(char *br_name)
|
|
|
|
|
{
|
2019-08-02 11:06:01 +00:00
|
|
|
|
br_temp_t cmp_args = {br_name, FALSE};
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
br_foreach_bridge(br_name_cmp, &cmp_args);
|
|
|
|
|
|
|
|
|
|
return cmp_args.result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret_code br_if_bridge_get(char *port_name, char* br_name)
|
|
|
|
|
{
|
|
|
|
|
char bridge_name[BR_NAMSIZ] = {0};
|
|
|
|
|
|
|
|
|
|
if(get_br_from_port(port_name, bridge_name) == RET_OK)
|
|
|
|
|
{
|
|
|
|
|
if(br_name)
|
|
|
|
|
{
|
|
|
|
|
strncpy(br_name, bridge_name, BR_NAMSIZ - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_NOTFOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_bridge_check(char *port_list, int cnt, uint config_type)
|
|
|
|
|
{
|
|
|
|
|
char *ptr_name = NULL;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i< cnt; i++)
|
|
|
|
|
{
|
|
|
|
|
ptr_name = port_list + INTERFACE_NAMSIZ * i;
|
|
|
|
|
if (if_nametoindex(ptr_name) == 0)
|
|
|
|
|
{
|
|
|
|
|
return RET_NOTFOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(br_if_bridge_get(ptr_name, NULL) == RET_OK)
|
|
|
|
|
{
|
|
|
|
|
if(config_type == CM_CONFIG_ADD)
|
|
|
|
|
{
|
|
|
|
|
return RET_EXIST;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(config_type == CM_CONFIG_DEL)
|
|
|
|
|
{
|
|
|
|
|
return RET_NOTFOUND;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 06:59:46 +00:00
|
|
|
|
ret_code br_save_file(BR_EVENT_TYPE event_type,
|
|
|
|
|
char *br_name, char *port_name)
|
|
|
|
|
{
|
|
|
|
|
char *key_str = "bridge_ports";
|
|
|
|
|
char config_str[IF_BUFF_LEN] = {0};
|
|
|
|
|
ret_code ret;
|
|
|
|
|
|
|
|
|
|
switch(event_type)
|
|
|
|
|
{
|
|
|
|
|
case BR_CREATE_EVENT:
|
|
|
|
|
if_conf_file_add(br_name);
|
|
|
|
|
break;
|
|
|
|
|
case BR_DELETE_EVENT:
|
2019-08-02 10:49:50 +00:00
|
|
|
|
if_conf_file_del(br_name);
|
2019-08-02 06:59:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case BR_IF_JOIN_EVENT:
|
|
|
|
|
if(if_conf_file_get(br_name, key_str, config_str) == RET_OK)
|
|
|
|
|
{
|
|
|
|
|
if(strstr(config_str, port_name) != NULL)
|
|
|
|
|
{
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
strcat(config_str, " ");
|
|
|
|
|
strcat(config_str, port_name);
|
|
|
|
|
}
|
|
|
|
|
if_conf_file_set(br_name, key_str, config_str);
|
|
|
|
|
break;
|
|
|
|
|
case BR_IF_LEAVE_EVENT:
|
|
|
|
|
if(if_conf_file_get(br_name, key_str, config_str) == RET_OK)
|
|
|
|
|
{
|
|
|
|
|
if(strstr(config_str, port_name) != NULL)
|
|
|
|
|
{
|
|
|
|
|
del_sub_string(config_str, port_name);
|
|
|
|
|
rpc_log_info("BR_IF_LEAVE_EVENT: %s\n", config_str);
|
|
|
|
|
if_conf_file_set(br_name, key_str, config_str);
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ret_code br_if_bridge_add(char *br_name, char *port_list, int cnt, int *sys_err)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
br_event_t event_arg = {0};
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
char *port_name;
|
|
|
|
|
int err = 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
for(i = 0; i < cnt; i++)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
2019-08-02 06:59:46 +00:00
|
|
|
|
br_invoke_event(BR_IF_JOIN_EVENT_PRE, event_arg);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
port_name = port_list + INTERFACE_NAMSIZ * i;
|
|
|
|
|
err = br_add_interface(br_name, port_name);
|
|
|
|
|
if(err != 0)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
*sys_err = err;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret = RET_SYSERR;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
event_arg.br_name = br_name;
|
|
|
|
|
event_arg.if_name = port_name;
|
|
|
|
|
|
2019-08-01 10:22:48 +00:00
|
|
|
|
br_invoke_event(BR_IF_JOIN_EVENT, event_arg);
|
2019-08-02 06:59:46 +00:00
|
|
|
|
|
|
|
|
|
br_save_file(BR_IF_JOIN_EVENT, br_name, port_name);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_bridge_del(char * br_name, char *port_list, int cnt, int *sys_err)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
br_event_t event_arg = {0};
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code ret = RET_OK;
|
2019-08-02 10:49:50 +00:00
|
|
|
|
char *port_name;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
int err = 0;
|
|
|
|
|
int i;
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
for(i = 0; i < cnt; i++)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
2019-08-02 06:59:46 +00:00
|
|
|
|
br_invoke_event(BR_IF_LEAVE_EVENT_PRE, event_arg);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
port_name = port_list + INTERFACE_NAMSIZ * i;
|
|
|
|
|
err = br_del_interface(br_name, port_name);
|
|
|
|
|
if(err != 0)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
*sys_err = err;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret = RET_SYSERR;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
event_arg.br_name = br_name;
|
|
|
|
|
event_arg.if_name = port_name;
|
|
|
|
|
|
2019-08-01 10:22:48 +00:00
|
|
|
|
br_invoke_event(BR_IF_LEAVE_EVENT, event_arg);
|
2019-08-02 06:59:46 +00:00
|
|
|
|
|
|
|
|
|
br_save_file(BR_IF_LEAVE_EVENT, br_name, port_name);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_if_bridge_num(char *br_name)
|
|
|
|
|
{
|
|
|
|
|
int cnt = 0;
|
2019-08-02 11:06:01 +00:00
|
|
|
|
int err = 0;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
err = br_for_port_num(br_name, &cnt);
|
|
|
|
|
cnt = (err != 0) ? 0 : cnt;
|
|
|
|
|
|
|
|
|
|
return cnt;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 06:59:46 +00:00
|
|
|
|
ret_code br_bridge_add(char *br_name, int *sys_err)
|
2019-08-02 05:48:30 +00:00
|
|
|
|
{
|
|
|
|
|
br_event_t event_arg = {br_name, NULL};
|
|
|
|
|
int sys_ret = 0;
|
2019-08-02 06:59:46 +00:00
|
|
|
|
|
|
|
|
|
br_invoke_event(BR_CREATE_EVENT_PRE, event_arg);
|
2019-08-02 05:48:30 +00:00
|
|
|
|
|
|
|
|
|
sys_ret = br_add_bridge(br_name);
|
|
|
|
|
*sys_err = sys_ret;
|
|
|
|
|
|
|
|
|
|
if(sys_ret != 0)
|
|
|
|
|
{
|
|
|
|
|
return RET_SYSERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
br_invoke_event(BR_CREATE_EVENT, event_arg);
|
2019-08-02 06:59:46 +00:00
|
|
|
|
|
|
|
|
|
br_save_file(BR_CREATE_EVENT, br_name, NULL);
|
|
|
|
|
|
2019-08-02 05:48:30 +00:00
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_bridge_del(char * br_name, int *sys_err)
|
|
|
|
|
{
|
|
|
|
|
br_event_t event_arg = {br_name, NULL};
|
|
|
|
|
int sys_ret = 0;
|
|
|
|
|
|
2019-08-02 06:59:46 +00:00
|
|
|
|
br_invoke_event(BR_DELETE_EVENT_PRE, event_arg);
|
|
|
|
|
|
2019-08-02 05:48:30 +00:00
|
|
|
|
sys_ret = br_del_bridge(br_name);
|
|
|
|
|
*sys_err = sys_ret;
|
|
|
|
|
|
|
|
|
|
if(sys_ret != 0)
|
|
|
|
|
{
|
|
|
|
|
return RET_SYSERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
br_invoke_event(BR_DELETE_EVENT, event_arg);
|
2019-08-02 06:59:46 +00:00
|
|
|
|
|
|
|
|
|
br_save_file(BR_DELETE_EVENT, br_name, NULL);
|
|
|
|
|
|
2019-08-02 05:48:30 +00:00
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥配置json格式转换函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
ret_code br_config_json_parse(pointer input, uint *conf_type, char *br_name)
|
|
|
|
|
{
|
|
|
|
|
cJSON *json_obj;
|
|
|
|
|
|
|
|
|
|
json_obj = cJSON_Parse(input);
|
|
|
|
|
ASSERT_PTR_RET(json_obj);
|
|
|
|
|
|
|
|
|
|
rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj));
|
|
|
|
|
|
|
|
|
|
s2j_create_struct_obj(br_config, br_config_string_t);
|
|
|
|
|
|
|
|
|
|
if(br_config == NULL)
|
|
|
|
|
{
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
return RET_NOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_struct_get_basic_element(br_config, json_obj, int, config_type);
|
|
|
|
|
s2j_struct_get_string_element(br_config, json_obj, br_name, BR_NAMSIZ);
|
|
|
|
|
|
|
|
|
|
strncpy(br_name, br_config->br_name, BR_NAMSIZ - 1);
|
|
|
|
|
*conf_type = br_config->config_type;
|
|
|
|
|
|
|
|
|
|
s2j_delete_struct_obj(br_config);
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_json_to_string( cJSON *json_obj, pointer output)
|
|
|
|
|
{
|
|
|
|
|
char *json_str;
|
|
|
|
|
int output_len = 0;
|
|
|
|
|
|
|
|
|
|
if(json_obj == NULL)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
json_str = cJSON_PrintUnformatted(json_obj);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
output_len = strlen(json_str) + 1;
|
|
|
|
|
|
|
|
|
|
if(output_len > CM_BUFF_SIZE)
|
|
|
|
|
{
|
|
|
|
|
rpc_log_warn("output len is too long %d, cut off!", output_len);
|
|
|
|
|
json_str[CM_BUFF_SIZE - 1] = '\0';
|
|
|
|
|
output_len = CM_BUFF_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy(output, json_str, output_len);
|
|
|
|
|
|
|
|
|
|
rpc_free(json_str);
|
|
|
|
|
s2j_delete_json_obj(json_obj);
|
|
|
|
|
|
|
|
|
|
return output_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cJSON *br_config_format_json(br_config_t *br_config)
|
|
|
|
|
{
|
|
|
|
|
s2j_create_json_obj(json_obj);
|
|
|
|
|
if(json_obj == NULL)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_json_set_basic_element(json_obj, br_config, string, br_name);
|
|
|
|
|
s2j_json_set_array_element(json_obj, br_config, string,
|
|
|
|
|
ports, br_config->port_num);
|
|
|
|
|
|
|
|
|
|
return json_obj;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
ret_code br_bridge_info(const char *br_name, cJSON *json_obj, int *err)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
br_if_temp_t br_if = {0};
|
|
|
|
|
br_config_t br_config = {0};
|
|
|
|
|
|
|
|
|
|
br_if.index = 0;
|
|
|
|
|
br_if.if_list = NULL;
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
*err = br_foreach_port(br_name, br_copy_port_name, &br_if);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
if (*err >= 0)
|
|
|
|
|
{
|
|
|
|
|
strncpy(br_config.br_name, br_name, BR_NAMSIZ - 1);
|
|
|
|
|
br_config.ports = br_if.if_list;
|
|
|
|
|
br_config.port_num = br_if.index;
|
|
|
|
|
json_obj = br_config_format_json(&br_config);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = RET_SYSERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(br_if.if_list)
|
|
|
|
|
{
|
|
|
|
|
rpc_free(br_if.if_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
int br_bridge_info_each(const char *br_name, void *args)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
cJSON *json_array = (cJSON *)args;
|
|
|
|
|
cJSON *json_obj = NULL;
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
|
|
ret = br_bridge_info(br_name, json_obj, &err);
|
|
|
|
|
|
|
|
|
|
if(json_obj)
|
|
|
|
|
{
|
|
|
|
|
cJSON_AddItemToArray(json_array, json_obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_config_json_parse(pointer input, uint *conf_type, br_config_t *br_if)
|
|
|
|
|
{
|
|
|
|
|
cJSON *json_obj;
|
|
|
|
|
int port_num = 0;
|
|
|
|
|
|
|
|
|
|
json_obj = cJSON_Parse(input);
|
|
|
|
|
ASSERT_PTR_RET(json_obj);
|
|
|
|
|
|
|
|
|
|
rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj));
|
|
|
|
|
|
|
|
|
|
s2j_create_struct_obj(br_if_conf, br_if_config_string_t);
|
|
|
|
|
|
|
|
|
|
if(br_if_conf == NULL)
|
|
|
|
|
{
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
return RET_NOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_struct_get_basic_element(br_if_conf, json_obj, int, config_type);
|
|
|
|
|
*conf_type = br_if_conf->config_type;
|
|
|
|
|
|
|
|
|
|
if(br_if_conf->config_type != CM_CONFIG_GET_ALL)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
s2j_struct_get_string_element(br_if_conf, json_obj, br_name, BR_NAMSIZ);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
strncpy(br_if->br_name, br_if_conf->br_name, BR_NAMSIZ - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(br_if_conf->config_type == CM_CONFIG_ADD
|
|
|
|
|
|| br_if_conf->config_type == CM_CONFIG_DEL)
|
|
|
|
|
{
|
|
|
|
|
s2j_struct_get_array_string_n(br_if_conf, json_obj, string,
|
|
|
|
|
ports, port_num, INTERFACE_NAMSIZ);
|
|
|
|
|
br_if->port_num = port_num;
|
|
|
|
|
br_if->ports = br_if_conf->ports; /*指针赋值,后续需要对该指针进行内存释放*/
|
|
|
|
|
br_if_conf->ports = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_delete_struct_obj(br_if_conf);
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥配置钩子函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code br_config_chk(uint source,uint *config_type,
|
|
|
|
|
pointer input, int *input_len,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
int config_len = 0;
|
|
|
|
|
uint conf_type = CM_CONFIG_GET;
|
|
|
|
|
char br_name[BR_NAMSIZ] = {0};
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int code = 0;
|
|
|
|
|
|
|
|
|
|
br_config_json_parse(input, &conf_type, br_name);
|
|
|
|
|
config_len = strlen(br_name) + 1;
|
|
|
|
|
|
|
|
|
|
switch (conf_type)
|
|
|
|
|
{
|
|
|
|
|
case CM_CONFIG_ADD:
|
|
|
|
|
case CM_CONFIG_DEL:
|
|
|
|
|
case CM_CONFIG_GET:
|
|
|
|
|
ret = br_name_chk(br_name);
|
|
|
|
|
break;
|
|
|
|
|
case CM_CONFIG_GET_ALL:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ret = RET_NOTSUPPORT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 将传入的json数据转换成结构体,便于后续处理 */
|
|
|
|
|
if(config_len <= CM_BUFF_SIZE)
|
|
|
|
|
{
|
|
|
|
|
memset(input, 0, *input_len);
|
|
|
|
|
memcpy(input, br_name, config_len);
|
|
|
|
|
*config_type = conf_type;
|
|
|
|
|
*input_len = config_len;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = RET_NOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RET_ERR_FORMART(ret, code, output, *output_len);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_config_proc(uint source, uint config_type,
|
|
|
|
|
pointer input, int input_len,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int sys_ret = 0;
|
|
|
|
|
char *br_name;
|
|
|
|
|
|
|
|
|
|
br_name = (char *)input;
|
|
|
|
|
|
|
|
|
|
if(config_type == CM_CONFIG_ADD)
|
|
|
|
|
{
|
2019-08-02 05:48:30 +00:00
|
|
|
|
ret = br_bridge_add(br_name, &sys_ret);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
else if(config_type == CM_CONFIG_DEL)
|
|
|
|
|
{
|
2019-08-02 05:48:30 +00:00
|
|
|
|
|
|
|
|
|
ret = br_bridge_del(br_name, &sys_ret);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 05:48:30 +00:00
|
|
|
|
RET_ERR_FORMART(ret, sys_ret, output, *output_len);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥接口配置钩子函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code br_if_config_chk(uint source,uint *config_type,
|
|
|
|
|
pointer input, int *input_len,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
br_config_t br_config = {0};
|
|
|
|
|
br_config_t *temp_conf = NULL;
|
|
|
|
|
int cfg_len = 0;
|
|
|
|
|
|
|
|
|
|
br_if_config_json_parse(input, config_type, &br_config);
|
|
|
|
|
|
|
|
|
|
cfg_len = BR_NAMSIZ + sizeof(br_config.port_num)
|
|
|
|
|
+ br_config.port_num * INTERFACE_NAMSIZ;
|
|
|
|
|
|
|
|
|
|
if(cfg_len > CM_BUFF_SIZE)
|
|
|
|
|
{
|
|
|
|
|
ret = RET_NOMEM;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = br_name_chk(br_config.br_name);
|
|
|
|
|
if(ret != RET_OK)
|
|
|
|
|
{
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
if(br_is_exist(br_config.br_name) == FALSE)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
ret = RET_NOTFOUND;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(*config_type != CM_CONFIG_ADD && *config_type != CM_CONFIG_DEL)
|
|
|
|
|
{
|
|
|
|
|
ret = RET_INPUTERR;
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = br_if_bridge_check(br_config.ports, br_config.port_num, *config_type);
|
|
|
|
|
if(ret != RET_OK)
|
|
|
|
|
{
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(input, 0, *input_len);
|
|
|
|
|
temp_conf = (br_config_t *)input;
|
|
|
|
|
|
|
|
|
|
strncpy(temp_conf->br_name, br_config.br_name, BR_NAMSIZ - 1);
|
|
|
|
|
temp_conf->port_num = br_config.port_num;
|
|
|
|
|
memcpy(temp_conf->ports, br_config.ports, br_config.port_num * INTERFACE_NAMSIZ);
|
|
|
|
|
|
|
|
|
|
*input_len = cfg_len;
|
|
|
|
|
|
|
|
|
|
exit:
|
|
|
|
|
RET_ERR_FORMART(ret, 0, output, *output_len);
|
|
|
|
|
rpc_free(br_config.ports);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_config_proc(uint source, uint config_type,
|
|
|
|
|
pointer input, int input_len,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
br_config_t *br_conf = (br_config_t *)input;
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
|
|
if(config_type == CM_CONFIG_ADD)
|
|
|
|
|
{
|
|
|
|
|
ret = br_if_bridge_add(br_conf->br_name, br_conf->ports,
|
|
|
|
|
br_conf->port_num, &err);
|
|
|
|
|
}
|
|
|
|
|
else if(config_type == CM_CONFIG_DEL)
|
|
|
|
|
{
|
|
|
|
|
ret = br_if_bridge_del(br_conf->br_name, br_conf->ports,
|
|
|
|
|
br_conf->port_num, &err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RET_ERR_FORMART(ret, err, output, *output_len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_config_get(uint source,
|
|
|
|
|
pointer input, int input_len,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
cJSON *json_obj = NULL;
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
|
|
ret = br_bridge_info((char *)input, json_obj, &err);
|
|
|
|
|
|
|
|
|
|
if(ret != RET_OK)
|
|
|
|
|
{
|
|
|
|
|
RET_ERR_FORMART(ret, err, output, *output_len);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*output_len = br_json_to_string(json_obj, output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_if_config_get_all(uint source,
|
|
|
|
|
pointer output, int *output_len)
|
|
|
|
|
{
|
|
|
|
|
cJSON *json_obj = NULL;
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
|
|
json_obj = cJSON_CreateArray();
|
|
|
|
|
if(json_obj == NULL)
|
|
|
|
|
{
|
|
|
|
|
ret = RET_NOMEM;
|
|
|
|
|
RET_ERR_FORMART(RET_NOMEM, err, output, *output_len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(br_foreach_bridge(br_bridge_info_each, json_obj) > 0)
|
|
|
|
|
{
|
|
|
|
|
*output_len = br_json_to_string(json_obj, output);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥FDB配置辅助函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
void br_format_time(const struct timeval *tv, char *str, int len)
|
|
|
|
|
{
|
|
|
|
|
snprintf(str, len, "%4i.%.2i", (int)tv->tv_sec, (int)tv->tv_usec/10000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int br_compare_fdbs(const void *_f0, const void *_f1)
|
|
|
|
|
{
|
|
|
|
|
const struct fdb_entry *f0 = _f0;
|
|
|
|
|
const struct fdb_entry *f1 = _f1;
|
|
|
|
|
|
|
|
|
|
return memcmp(f0->mac_addr, f1->mac_addr, 6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_get_if_from_portno(const char *brname, int port_no, char *ifname)
|
|
|
|
|
{
|
|
|
|
|
int ifindices[MAX_PORTS];
|
|
|
|
|
unsigned long args[4] = { BRCTL_GET_PORT_LIST,
|
|
|
|
|
(unsigned long)ifindices, MAX_PORTS, 0 };
|
2019-08-02 10:49:50 +00:00
|
|
|
|
struct ifreq ifr;
|
|
|
|
|
int br_fd = -1;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
|
|
|
|
|
if (port_no >= MAX_PORTS)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
memset(ifindices, 0, sizeof(ifindices));
|
|
|
|
|
strncpy(ifr.ifr_name, brname, IFNAMSIZ);
|
|
|
|
|
ifr.ifr_data = (char *) &args;
|
|
|
|
|
|
2019-08-02 10:49:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((br_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ioctl(br_fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
2019-08-01 10:22:48 +00:00
|
|
|
|
dprintf("get_portno: get ports of %s failed: %s\n",
|
|
|
|
|
brname, strerror(errno));
|
2019-08-02 10:49:50 +00:00
|
|
|
|
close(br_fd);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(if_indextoname(ifindices[port_no], ifname) == NULL)
|
|
|
|
|
{
|
2019-08-02 10:49:50 +00:00
|
|
|
|
close(br_fd);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2019-08-02 10:49:50 +00:00
|
|
|
|
|
|
|
|
|
close(br_fd);
|
2019-08-01 10:22:48 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int br_fdb_get(char *brname, struct fdb_entry **br_fdb)
|
|
|
|
|
{
|
|
|
|
|
struct fdb_entry *fdb;
|
|
|
|
|
int i = 0, n = 0;
|
|
|
|
|
int offset = 0;
|
|
|
|
|
|
|
|
|
|
fdb = NULL;
|
|
|
|
|
*br_fdb = NULL;
|
|
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
|
fdb = realloc(fdb, (offset + FDB_CHUNK) * sizeof(struct fdb_entry));
|
|
|
|
|
if (!fdb) {
|
|
|
|
|
rpc_log_error("Out of memory\n");
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*br_fdb = fdb;
|
|
|
|
|
|
|
|
|
|
n = br_read_fdb(brname, fdb+offset, offset, FDB_CHUNK);
|
|
|
|
|
if (n == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
rpc_log_error( "read of forward table failed: %s\n", strerror(errno));
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
offset += n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
qsort(fdb, offset, sizeof(struct fdb_entry), br_compare_fdbs);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
printf("port no\tmac addr\t\tis local?\tageing timer\n");
|
|
|
|
|
for (i = 0; i < offset; i++) {
|
|
|
|
|
const struct fdb_entry *f = fdb + i;
|
|
|
|
|
printf("%3i\t", f->port_no);
|
|
|
|
|
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t",
|
|
|
|
|
f->mac_addr[0], f->mac_addr[1], f->mac_addr[2],
|
|
|
|
|
f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]);
|
|
|
|
|
printf("%s\t\t", f->is_local?"yes":"no");
|
|
|
|
|
br_show_timer(&f->ageing_timer_value);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_fdb_cpy(br_fdb_status_t *fdb_status, struct fdb_entry *fdb)
|
|
|
|
|
{
|
|
|
|
|
struct fdb_entry *temp_fdb;
|
|
|
|
|
char if_name[INTERFACE_NAMSIZ];
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < fdb_status->fdb_num && i < MAC_MAXIZS; i++)
|
|
|
|
|
{
|
|
|
|
|
temp_fdb = fdb + i;
|
|
|
|
|
|
|
|
|
|
memset(if_name, 0, INTERFACE_NAMSIZ);
|
|
|
|
|
if(br_get_if_from_portno(fdb_status->br_name,
|
|
|
|
|
temp_fdb->port_no,
|
|
|
|
|
if_name) != 0)
|
|
|
|
|
{
|
|
|
|
|
rpc_log_error("port no %d can not get ifname\n", temp_fdb->port_no);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
snprintf(fdb_status->fdb_info[i].mac_addr, MAC_STRSIZ,
|
|
|
|
|
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
|
temp_fdb->mac_addr[0], temp_fdb->mac_addr[1], temp_fdb->mac_addr[2],
|
|
|
|
|
temp_fdb->mac_addr[3], temp_fdb->mac_addr[4], temp_fdb->mac_addr[5]);
|
|
|
|
|
|
|
|
|
|
strncpy(fdb_status->fdb_info[i].port, if_name, INTERFACE_NAMSIZ - 1);
|
|
|
|
|
|
|
|
|
|
if(temp_fdb->is_local)
|
|
|
|
|
{
|
|
|
|
|
strncpy(fdb_status->fdb_info[i].local, "true", LOCAL_STRSIZ - 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strncpy(fdb_status->fdb_info[i].local, "false", LOCAL_STRSIZ - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
br_format_time(&temp_fdb->ageing_timer_value,
|
|
|
|
|
fdb_status->fdb_info[i].time, TIME_STRSIZ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥FDB配置json格式转换 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code br_fdb_config_json_parse(pointer input, uint *conf_type, br_fdb_config_t *br_fdb)
|
|
|
|
|
{
|
|
|
|
|
cJSON *json_obj;
|
|
|
|
|
int port_num = 0;
|
|
|
|
|
|
|
|
|
|
json_obj = cJSON_Parse(input);
|
|
|
|
|
if(!json_obj)
|
|
|
|
|
{
|
|
|
|
|
return RET_INPUTERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rpc_log_info("json input:\n %s\n", cJSON_Print(json_obj));
|
|
|
|
|
|
|
|
|
|
s2j_create_struct_obj(br_fdb_conf, br_fdb_string_t);
|
|
|
|
|
|
|
|
|
|
if(br_fdb_conf == NULL)
|
|
|
|
|
{
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
return RET_NOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_struct_get_string_element(br_fdb_conf, json_obj, string, br_name, BR_NAMSIZ);
|
|
|
|
|
|
|
|
|
|
*conf_type = br_fdb_conf->config_type;
|
|
|
|
|
strncpy(br_fdb->br_name, br_fdb_conf->br_name, BR_NAMSIZ - 1);
|
|
|
|
|
|
|
|
|
|
s2j_delete_struct_obj(br_fdb_conf);
|
|
|
|
|
cJSON_Delete(json_obj);
|
|
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_each_fdb_to_json_string(cJSON *json_array, fdb_info_t *fdb_info)
|
|
|
|
|
{
|
|
|
|
|
s2j_create_json_obj(fdb_obj);
|
2019-08-02 10:49:50 +00:00
|
|
|
|
|
2019-08-01 10:22:48 +00:00
|
|
|
|
if(fdb_obj == NULL)
|
|
|
|
|
{
|
|
|
|
|
return RET_NOMEM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_json_set_basic_element(fdb_obj, fdb_info, string, mac_addr);
|
|
|
|
|
s2j_json_set_basic_element(fdb_obj, fdb_info, string, port);
|
|
|
|
|
s2j_json_set_basic_element(fdb_obj, fdb_info, string, local);
|
|
|
|
|
s2j_json_set_basic_element(fdb_obj, fdb_info, string, time);
|
|
|
|
|
|
|
|
|
|
cJSON_AddItemToArray(json_array, fdb_obj);
|
|
|
|
|
|
2019-08-02 11:06:01 +00:00
|
|
|
|
return RET_OK;
|
2019-08-01 10:22:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int br_fdb_to_json_string(br_fdb_status_t *fdb_status, char *output)
|
|
|
|
|
{
|
|
|
|
|
cJSON *fdb_array;
|
|
|
|
|
char *json_str;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
s2j_create_json_obj(br_obj);
|
|
|
|
|
fdb_array = cJSON_CreateArray();
|
|
|
|
|
|
|
|
|
|
if(br_obj == NULL || fdb_array)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s2j_json_set_basic_element(br_obj, fdb_status, string, br_name);
|
|
|
|
|
s2j_json_set_basic_element(br_obj, fdb_status, int, fdb_num);
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < fdb_status->fdb_num; i++)
|
|
|
|
|
{
|
|
|
|
|
br_each_fdb_to_json_string(fdb_array, &(fdb_status->fdb_info[i]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cJSON_AddItemToObject(br_obj, "fdb", fdb_array);
|
|
|
|
|
|
|
|
|
|
br_json_to_string(br_obj, output);
|
|
|
|
|
|
|
|
|
|
return (strlen(output) + 1);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-02 10:11:34 +00:00
|
|
|
|
/* 桥FDB表配置钩子函数 */
|
2019-08-01 10:22:48 +00:00
|
|
|
|
ret_code br_fdb_config_chk(uint source,uint *config_type,
|
2019-08-02 05:48:30 +00:00
|
|
|
|
pointer input, int *input_len,
|
|
|
|
|
pointer output, int *output_len)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
br_fdb_config_t br_fdb = {0};
|
|
|
|
|
br_fdb_config_t *temp_conf;
|
|
|
|
|
int cfg_len = 0;
|
|
|
|
|
|
|
|
|
|
ret = br_fdb_config_json_parse(input, config_type, &br_fdb);
|
|
|
|
|
if(ret != RET_OK)
|
|
|
|
|
{
|
|
|
|
|
RET_ERR_FORMART(ret, 0, output, *output_len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(*config_type != CM_CONFIG_GET)
|
|
|
|
|
{
|
|
|
|
|
ret = RET_INPUTERR;
|
|
|
|
|
RET_ERR_FORMART(ret, 0, output, *output_len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 回填解析过的数据 */
|
|
|
|
|
memset(input, 0, *input_len);
|
|
|
|
|
temp_conf = (br_fdb_config_t *)input;
|
|
|
|
|
|
|
|
|
|
strncpy(temp_conf->br_name, br_fdb.br_name, BR_NAMSIZ - 1);
|
|
|
|
|
*input_len = cfg_len;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret_code br_fdb_config_get(uint source,
|
2019-08-02 05:48:30 +00:00
|
|
|
|
pointer input, int input_len,
|
|
|
|
|
pointer output, int *output_len)
|
2019-08-01 10:22:48 +00:00
|
|
|
|
{
|
|
|
|
|
br_fdb_status_t *fdb_status;
|
|
|
|
|
br_fdb_config_t *br_fdb;
|
|
|
|
|
struct fdb_entry *fdb;
|
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
|
|
br_fdb = (br_fdb_config_t *)input;
|
|
|
|
|
|
|
|
|
|
fdb_status = (br_fdb_status_t *)rpc_new0(br_fdb_status_t, 1);
|
|
|
|
|
if(fdb_status == NULL)
|
|
|
|
|
{
|
|
|
|
|
ret = RET_NOMEM;
|
|
|
|
|
RET_ERR_FORMART(ret, 0, output, *output_len);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strncpy(fdb_status->br_name, br_fdb->br_name, BR_NAMSIZ - 1);
|
|
|
|
|
fdb_status->fdb_num = br_fdb_get(br_fdb->br_name, &fdb);
|
|
|
|
|
fdb_status->fdb_num = br_fdb_cpy(fdb_status, fdb);
|
|
|
|
|
|
|
|
|
|
*output_len = br_fdb_to_json_string(fdb_status, output);
|
|
|
|
|
|
|
|
|
|
rpc_free(fdb);
|
|
|
|
|
rpc_free(fdb_status);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|