579 lines
16 KiB
C
579 lines
16 KiB
C
#include "configm.h"
|
||
#include "rpc.h"
|
||
#include "parsefile.h"
|
||
#include "netconfig.h"
|
||
|
||
uchar ip_masklen(struct in_addr netmask)
|
||
{
|
||
uint tmp = ~ntohl(netmask.s_addr);
|
||
if (tmp)
|
||
/* clz: count leading zeroes. sadly, the behaviour of this
|
||
* builtin
|
||
* is undefined for a 0 argument, even though most CPUs give 32
|
||
*/
|
||
return __builtin_clz(tmp);
|
||
else
|
||
return 32;
|
||
}
|
||
|
||
|
||
/* Convert masklen into IP address's netmask (network byte order). */
|
||
void masklen2ip(const int masklen, struct in_addr *netmask)
|
||
{
|
||
if(masklen < 0 || masklen > IPV4_MAX_BITLEN)
|
||
{
|
||
return;
|
||
}
|
||
|
||
/* left shift is only defined for less than the size of the type.
|
||
* we unconditionally use long long in case the target platform
|
||
* has defined behaviour for << 32 (or has a 64-bit left shift) */
|
||
|
||
if (sizeof(unsigned long long) > 4)
|
||
netmask->s_addr = htonl(0xffffffffULL << (32 - masklen));
|
||
else
|
||
netmask->s_addr =
|
||
htonl(masklen ? 0xffffffffU << (32 - masklen) : 0);
|
||
}
|
||
|
||
static char *ip_inet6_print(struct in6_addr *ptr)
|
||
{
|
||
static char name[80] = {0};
|
||
|
||
inet_ntop(AF_INET6, ptr, name, 80);
|
||
return name;
|
||
}
|
||
|
||
|
||
void ip_save_file(ip_config_t *ip_conf, uint config_type)
|
||
{
|
||
char *addr_name = "address";
|
||
char *mask_name = "netmask";
|
||
//struct in_addr netmask;
|
||
char addr_buff[IF_BUFF_LEN] = {0};
|
||
char mask_buff[IF_BUFF_LEN] = {0};
|
||
|
||
if(config_type == CM_CONFIG_SET)
|
||
{
|
||
sprintf(addr_buff, "address %s\n", inet_ntoa(ip_conf->ipv4.addr));
|
||
sprintf(mask_buff, "netmask %s\n", inet_ntoa(ip_conf->ipv4.mask));
|
||
rpc_log_info("%s %s",addr_buff, mask_buff);
|
||
|
||
ip_conf_file_set(ip_conf->ifname, addr_name, addr_buff);
|
||
ip_conf_file_set(ip_conf->ifname, mask_name, mask_buff);
|
||
}
|
||
else if(config_type == CM_CONFIG_DEL)
|
||
{
|
||
ip_conf_file_del(ip_conf->ifname, addr_name);
|
||
ip_conf_file_del(ip_conf->ifname, mask_name);
|
||
}
|
||
}
|
||
|
||
void ip6_save_file(ip_config_t *ip_conf, uint config_type)
|
||
{
|
||
char *addr_name = "address";
|
||
char *mask_name = "netmask";
|
||
char addr_buff[IF_BUFF_LEN] = {0};
|
||
char mask_buff[IF_BUFF_LEN] = {0};
|
||
|
||
if(config_type == CM_CONFIG_SET)
|
||
{
|
||
sprintf(addr_buff, "address %s\n", ip_inet6_print(&ip_conf->ipv6.addr));
|
||
sprintf(mask_buff, "netmask %d\n", ip_conf->ipv6.prefixlen);
|
||
rpc_log_info("%s %s",addr_buff, mask_buff);
|
||
|
||
ipv6_conf_file_set(ip_conf->ifname, addr_name, addr_buff);
|
||
ipv6_conf_file_set(ip_conf->ifname, mask_name, mask_buff);
|
||
}
|
||
else if(config_type == CM_CONFIG_DEL)
|
||
{
|
||
ipv6_conf_file_del(ip_conf->ifname, addr_name);
|
||
ipv6_conf_file_del(ip_conf->ifname, mask_name);
|
||
}
|
||
}
|
||
|
||
ret_code ip_config_json_parse(pointer input, uint *conf_type, ip_config_t *config_buff)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
cJSON *json_obj;
|
||
int err = 1;
|
||
|
||
json_obj = cJSON_Parse(input);
|
||
if(!json_obj)
|
||
{
|
||
return RET_JSONERR;
|
||
}
|
||
|
||
rpc_json_print(json_obj);
|
||
|
||
s2j_create_struct_obj(ip_config, ip_config_string_t);
|
||
|
||
if(ip_config == NULL)
|
||
{
|
||
cJSON_Delete(json_obj);
|
||
return RET_NOMEM;
|
||
}
|
||
|
||
s2j_struct_get_basic_element(ip_config, json_obj, int, config_type);
|
||
s2j_struct_get_basic_element(ip_config, json_obj, int, family);
|
||
|
||
s2j_struct_get_string_element(ip_config, json_obj, ifname, INTERFACE_NAMSIZ);
|
||
s2j_struct_get_string_element(ip_config, json_obj, ipaddr, DOT_IPV6_STR);
|
||
s2j_struct_get_string_element(ip_config, json_obj, prefixlen, DOT_IPV6_STR);
|
||
|
||
strncpy(config_buff->ifname, ip_config->ifname, INTERFACE_NAMSIZ - 1);
|
||
|
||
config_buff->family = (uchar)ip_config->family;
|
||
|
||
if(config_buff->family == AF_INET)
|
||
{
|
||
err = inet_pton(AF_INET, ip_config->prefixlen, &(config_buff->ipv4.mask));
|
||
if(err != 1)
|
||
{
|
||
inet_pton(AF_INET, IPV4_DEFAULT_NETMASK, &(config_buff->ipv4.mask));
|
||
}
|
||
err = inet_pton(AF_INET, ip_config->ipaddr, &(config_buff->ipv4.addr));
|
||
}
|
||
else if(config_buff->family == AF_INET6)
|
||
{
|
||
config_buff->ipv6.prefixlen = (uchar)strtoul(ip_config->prefixlen, 0, 0);
|
||
if(config_buff->ipv6.prefixlen > IPV6_MAX_PREFIXLEN)
|
||
{
|
||
config_buff->ipv6.prefixlen = IPV6_DEFAULT_PREFIXLEN;
|
||
}
|
||
err = inet_pton(AF_INET6, ip_config->ipaddr, &(config_buff->ipv6.addr));
|
||
}
|
||
|
||
if(err != 1)
|
||
{
|
||
ret = RET_IPINVALID;
|
||
}
|
||
|
||
if(ip_config->config_type)
|
||
{
|
||
*conf_type = ip_config->config_type;
|
||
}
|
||
|
||
s2j_delete_struct_obj(ip_config);
|
||
cJSON_Delete(json_obj);
|
||
|
||
return ret;
|
||
}
|
||
|
||
cJSON *ipv4_format_json(if_info_t *config_buff)
|
||
{
|
||
cJSON *json_array;
|
||
v4addr_str *if_ipv4 = &(config_buff->ipv4);
|
||
|
||
json_array = cJSON_CreateArray();
|
||
ASSERT_PTR(json_array, NULL);
|
||
|
||
s2j_create_json_obj(json_ipv4);
|
||
s2j_json_set_basic_element(json_ipv4, if_ipv4, string, addr);
|
||
s2j_json_set_basic_element(json_ipv4, if_ipv4, string, prefixlen);
|
||
|
||
cJSON_AddItemToArray(json_array, json_ipv4);
|
||
|
||
return json_array;
|
||
}
|
||
|
||
|
||
cJSON *ipv6_format_json(if_info_t *config_buff, int v6_cnt)
|
||
{
|
||
cJSON *json_array;
|
||
v6addr_str *if_ipv6;
|
||
int i;
|
||
|
||
json_array = cJSON_CreateArray();
|
||
ASSERT_PTR(json_array, NULL);
|
||
|
||
for(i = 0; i < v6_cnt; i++)
|
||
{
|
||
if_ipv6 = &(config_buff->ipv6[i]);
|
||
|
||
s2j_create_json_obj(json_ipv6);
|
||
|
||
s2j_json_set_basic_element(json_ipv6, if_ipv6, string, addr);
|
||
s2j_json_set_basic_element(json_ipv6, if_ipv6, int, prefixlen);
|
||
|
||
cJSON_AddItemToArray(json_array, json_ipv6);
|
||
}
|
||
|
||
return json_array;
|
||
}
|
||
|
||
cJSON * ip_config_format_json(if_info_t *config_buff, int v6_cnt)
|
||
{
|
||
v4addr_str *ipv4 = &config_buff->ipv4;
|
||
if_cnt_t *stats = &config_buff->stats;
|
||
cJSON *v4_array;
|
||
cJSON *v6_array;
|
||
|
||
s2j_create_json_obj(json_obj);
|
||
|
||
|
||
s2j_create_json_obj(json_stats);
|
||
s2j_json_set_basic_element(json_stats, stats, string, rcv_packets);
|
||
s2j_json_set_basic_element(json_stats, stats, string, rcv_bytes);
|
||
s2j_json_set_basic_element(json_stats, stats, string, snd_packets);
|
||
s2j_json_set_basic_element(json_stats, stats, string, snd_bytes);
|
||
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, ifname);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, ipenable);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, v4protocol);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, v6protocol);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, role);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, maxspeed);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, state);
|
||
s2j_json_set_basic_element(json_obj, config_buff, string, hwaddr);
|
||
|
||
v4_array = ipv4_format_json(config_buff);
|
||
v6_array = ipv6_format_json(config_buff, v6_cnt);
|
||
if(v4_array)
|
||
{
|
||
cJSON_AddItemToObject(json_obj, "ipv4", v4_array);
|
||
}
|
||
|
||
if(v6_array)
|
||
{
|
||
cJSON_AddItemToObject(json_obj, "ipv6", v6_array);
|
||
}
|
||
|
||
cJSON_AddItemToObject(json_obj, "statistics", json_stats);
|
||
|
||
return json_obj;
|
||
}
|
||
|
||
ret_code if_get_info(if_info_t *if_info, int *v6_cnt)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
|
||
ret = if_get_ipenable(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_get_v4proto(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_get_v6proto(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_get_hwaddr(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_get_maxspeed(if_info);
|
||
//ASSERT_RET(ret);
|
||
|
||
ret = if_get_linkstat(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_get_prefix(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
ret = if_read_stats_file(if_info);
|
||
ASSERT_RET(ret);
|
||
|
||
*v6_cnt = if_get_prefix6(if_info);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
ret_code ip_config_v4chk(uint config_type, ip_config_t *ip_conf)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
|
||
if (ipv4_martian(&(ip_conf->ipv4.addr)))
|
||
{
|
||
ret = RET_IPINVALID;
|
||
}
|
||
|
||
ASSERT_RET(ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
ret_code ip_config_v6chk(uint config_type, ip_config_t *ip_conf)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
|
||
if (ipv6_martian(&(ip_conf->ipv6.addr)))
|
||
{
|
||
ret = RET_IPINVALID;
|
||
}
|
||
|
||
ASSERT_RET(ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
ret_code ip_config_set_chk(uint source,uint config_type,
|
||
pointer input, int input_len,
|
||
pointer output, int *output_len)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
ip_config_t *ip_conf;
|
||
|
||
ip_conf = (ip_config_t *)input;
|
||
|
||
if(input_len < sizeof(ip_config_t)
|
||
|| strlen(ip_conf->ifname) == 0)
|
||
{
|
||
ret = RET_INPUTERR;
|
||
}
|
||
|
||
if(ip_conf->family == AF_INET)
|
||
{
|
||
ret = ip_config_v4chk(config_type, ip_conf);
|
||
}
|
||
else if(ip_conf->family == AF_INET6)
|
||
{
|
||
ret = ip_config_v6chk(config_type, ip_conf);
|
||
}
|
||
|
||
ASSERT_RET(ret);
|
||
|
||
return RET_OK;
|
||
}
|
||
|
||
ret_code ip_config_get_chk(uint source,uint config_type,
|
||
pointer input, int input_len,
|
||
pointer output, int *output_len)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
ip_config_t *ip_config;
|
||
|
||
ip_config = (ip_config_t *)input;
|
||
|
||
if(input_len < sizeof(ip_config_t)
|
||
|| strlen(ip_config->ifname) == 0 )
|
||
{
|
||
ret = RET_INPUTERR;
|
||
}
|
||
ASSERT_RET(ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
ret_code ip_config_getall_chk(uint source,uint config_type,
|
||
pointer input, int input_len,
|
||
pointer output, int *output_len)
|
||
{
|
||
ret_code ret = RET_OK;
|
||
|
||
if(*output_len < MAX_IF_NUM * sizeof(ip_config_t))
|
||
{
|
||
ret = RET_INPUTERR;
|
||
}
|
||
ASSERT_RET(ret);
|
||
|
||
return ret;
|
||
}
|
||
|
||
ret_code ip_config_chk(uint source,uint *config_type,
|
||
pointer input, int *input_len,
|
||
pointer output, int *output_len)
|
||
|
||
{
|
||
int config_len = sizeof(ip_config_t);
|
||
uint conf_type = CM_CONFIG_GET;
|
||
ip_config_t ip_config = {0};
|
||
ret_code ret = RET_OK;
|
||
|
||
ret = ip_config_json_parse(input, &conf_type, &ip_config);
|
||
ASSERT_RET(ret);
|
||
|
||
switch (conf_type)
|
||
{
|
||
case CM_CONFIG_SET:
|
||
case CM_CONFIG_DEL:
|
||
ret = ip_config_set_chk(source, conf_type,
|
||
&ip_config, config_len,
|
||
output, output_len);
|
||
break;
|
||
case CM_CONFIG_GET:
|
||
ret = ip_config_get_chk(source, conf_type,
|
||
&ip_config, config_len,
|
||
output, output_len);
|
||
break;
|
||
case CM_CONFIG_GET_ALL:
|
||
ret = ip_config_getall_chk(source, conf_type,
|
||
&ip_config, config_len,
|
||
output, output_len);
|
||
break;
|
||
default:
|
||
ret = RET_NOTSUPPORT;
|
||
}
|
||
|
||
/* 将传入的json数据转换成结构体,便于后续处理 */
|
||
if(config_len <= CM_BUFF_SIZE)
|
||
{
|
||
memset(input, 0, *input_len);
|
||
memcpy(input, &ip_config, config_len);
|
||
*config_type = conf_type;
|
||
*input_len = config_len;
|
||
}
|
||
else
|
||
{
|
||
ret = RET_NOMEM;
|
||
}
|
||
|
||
RET_ERR_FORMART(ret, output, *output_len);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
设置ipv4地址
|
||
{"config_type":3,"ifname":"br0","family":2,"ipaddr":"192.168.3.1","prefixlen":16}
|
||
设置ipv6地址
|
||
{"config_type":3,"ifname":"br0","family":10,"ipaddr":"2001::1","prefixlen":64}
|
||
删除ipv4地址
|
||
{"config_type":2,"ifname":"br0","family":2,"ipaddr":"192.168.3.1","prefixlen":16}
|
||
删除ipv6地址
|
||
{"config_type":2,"ifname":"br0","family":10,"ipaddr":"2001::1","prefixlen":64}
|
||
*/
|
||
|
||
ret_code ip_config_proc(uint source, uint config_type,
|
||
pointer input, int input_len,
|
||
pointer output, int *output_len)
|
||
{
|
||
uint conf_type = config_type;
|
||
ip_config_t *ip_conf;
|
||
ret_code ret = RET_OK;
|
||
|
||
ip_conf = (ip_config_t *)input;
|
||
|
||
if(ip_conf->family == AF_INET)
|
||
{
|
||
rpc_log_info("config type is %d, if %s ip %s\n",
|
||
conf_type, ip_conf->ifname,
|
||
inet_ntoa(ip_conf->ipv4.addr));
|
||
|
||
rpc_log_info("netmask is %s\n",inet_ntoa(ip_conf->ipv4.mask) );
|
||
|
||
if(conf_type == CM_CONFIG_DEL)
|
||
{
|
||
ip_conf->ipv4.addr.s_addr = 0;
|
||
}
|
||
|
||
ret = if_set_prefix(ip_conf);
|
||
RET_ERR_FORMART(ret, output, *output_len);
|
||
ASSERT_RET(ret);
|
||
|
||
ip_save_file(ip_conf, conf_type);
|
||
}
|
||
else if(ip_conf->family == AF_INET6)
|
||
{
|
||
rpc_log_info("config type is %d, if %s ip %s prefixlen %d\n",
|
||
conf_type, ip_conf->ifname,
|
||
ip_inet6_print(&(ip_conf->ipv6.addr)),
|
||
ip_conf->ipv6.prefixlen);
|
||
|
||
ret = if_set_prefix6(conf_type, ip_conf);
|
||
RET_ERR_FORMART(ret, output, *output_len);
|
||
ASSERT_RET(ret);
|
||
|
||
ip6_save_file(ip_conf, conf_type);
|
||
}
|
||
|
||
return RET_OK;
|
||
}
|
||
|
||
/*{"config_type":4,"ifname":"br0"}*/
|
||
ret_code ip_config_get(uint source,
|
||
pointer input, int input_len,
|
||
pointer output, int *output_len)
|
||
{
|
||
if_info_t if_info = {0};
|
||
ret_code ret = RET_OK;
|
||
ip_config_t *if_config;
|
||
cJSON *item_obj;
|
||
int v6_cnt = 0;
|
||
|
||
if_config = (ip_config_t *)input;
|
||
strncpy(if_info.ifname, if_config->ifname, INTERFACE_NAMSIZ - 1);
|
||
|
||
ret = if_get_info(&if_info, &v6_cnt);
|
||
ASSERT_RET(ret);
|
||
|
||
item_obj = ip_config_format_json(&if_info, v6_cnt);
|
||
*output_len = cm_format_data(RET_OK, item_obj, output);
|
||
|
||
return ret;
|
||
}
|
||
|
||
/* {"config_type":5} */
|
||
ret_code ip_config_get_all(uint source, pointer output, int *output_len)
|
||
{
|
||
struct ifreq *ifreq;
|
||
ret_code ret = RET_OK;
|
||
int if_count = 0;
|
||
if_info_t *if_info;
|
||
cJSON *json_array;
|
||
cJSON *item_obj;
|
||
int v6_cnt = 0;
|
||
int i;
|
||
|
||
ifreq = rpc_new0(struct ifreq, MAX_IF_NUM);
|
||
ASSERT_PTR(ifreq, RET_NOMEM);
|
||
|
||
if_count = if_get_allport(ifreq, MAX_IF_NUM);
|
||
|
||
rpc_log_info("if num is %d\n", if_count);
|
||
|
||
if((if_count * sizeof(if_info_t) > CM_BUFF_SIZE)
|
||
|| (if_count == 0))
|
||
{
|
||
rpc_free(ifreq);
|
||
ret = RET_NOMEM;
|
||
}
|
||
ASSERT_RET(ret);
|
||
|
||
if_info = rpc_new0(if_info_t, if_count);
|
||
if(if_info == NULL)
|
||
{
|
||
rpc_free(ifreq);
|
||
return RET_NOMEM;
|
||
}
|
||
|
||
json_array = cJSON_CreateArray();
|
||
if(json_array == NULL)
|
||
{
|
||
rpc_free(ifreq);
|
||
rpc_free(if_info);
|
||
return RET_NOMEM;
|
||
}
|
||
|
||
for(i = 0; i < if_count; i++)
|
||
{
|
||
rpc_log_info("get interface %s info\n", ifreq[i].ifr_name);
|
||
strncpy(if_info[i].ifname, ifreq[i].ifr_name, INTERFACE_NAMSIZ - 1);
|
||
|
||
v6_cnt = 0;
|
||
ret = if_get_info(&if_info[i], &v6_cnt);
|
||
ASSERT_CONTINUE(ret);
|
||
|
||
item_obj = ip_config_format_json(&if_info[i], v6_cnt);
|
||
if(item_obj == NULL)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
cJSON_AddItemToArray(json_array, item_obj);
|
||
}
|
||
|
||
rpc_free(ifreq);
|
||
rpc_free(if_info);
|
||
|
||
*output_len = cm_format_data(RET_OK, json_array, output);
|
||
|
||
rpc_log_info("ip_config_get_all: %s\n", (char *)output);
|
||
|
||
RET_ERR_FORMART(ret, output, *output_len);
|
||
|
||
ASSERT_RET(ret);
|
||
|
||
return RET_OK;
|
||
}
|