secgateway/Platform/user/configm/config-server/netconfig/ipconfig/ipconfig.c

579 lines
16 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}