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

562 lines
15 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);
}
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->prefix));
masklen2ip(ip_conf->prefixlen, &netmask);
sprintf(mask_buff, "netmask %s\n", inet_ntoa(netmask));
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);
}
}
ret_code ip_config_json_parse(pointer input, uint *conf_type, ip_config_t *config_buff)
{
//ip_config_string_t *ip_config;
cJSON *json_obj;
json_obj = cJSON_Parse(input);
if(!json_obj)
{
return RET_INPUTERR;
}
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_string_element(ip_config, json_obj, ifname, INTERFACE_NAMSIZ);
s2j_struct_get_basic_element(ip_config, json_obj, int, family);
s2j_struct_get_string_element(ip_config, json_obj, ipaddr, DOT_IP_STR);
s2j_struct_get_basic_element(ip_config, json_obj, int, prefixlen);
strncpy(config_buff->ifname, ip_config->ifname, INTERFACE_NAMSIZ - 1);
config_buff->family = (uchar)ip_config->family;
config_buff->prefixlen = (uchar)ip_config->prefixlen;
config_buff->prefix.s_addr = inet_addr(ip_config->ipaddr);
if(ip_config->config_type)
{
*conf_type = ip_config->config_type;
}
s2j_delete_struct_obj(ip_config);
cJSON_Delete(json_obj);
return RET_OK;
}
ret_code ip_config_json_parse_array(pointer input, uint *conf_type,
ip_config_t *config_buff, int *cnt)
{
//ip_config_string_t *ip_config;
cJSON *json_obj;
cJSON* pArrayItem;
int iCount = 0, i = 0;
json_obj = cJSON_Parse(input);
if(!json_obj)
{
return RET_INPUTERR;
}
rpc_json_print(json_obj);
iCount = cJSON_GetArraySize(json_obj);
config_buff = rpc_new0(ip_config_t, iCount);
conf_type = rpc_new0(uint, iCount);
if(!config_buff || !conf_type)
{
return RET_NOMEM;
}
s2j_create_struct_obj(ip_config, ip_config_string_t);
if(ip_config == NULL)
{
cJSON_Delete(json_obj);
rpc_free(config_buff);
return RET_NOMEM;
}
*cnt = 0;
for(i = 0; i < iCount; i++)
{
pArrayItem = cJSON_GetArrayItem(json_obj, i);
if(pArrayItem)
{
memset(ip_config, 0, sizeof(ip_config_string_t));
s2j_struct_get_basic_element(ip_config, pArrayItem, int, config_type);
s2j_struct_get_string_element(ip_config, pArrayItem, ifname, INTERFACE_NAMSIZ);
s2j_struct_get_basic_element(ip_config, pArrayItem, int, family);
s2j_struct_get_string_element(ip_config, pArrayItem, ipaddr, DOT_IP_STR);
s2j_struct_get_basic_element(ip_config, pArrayItem, int, prefixlen);
strncpy(config_buff[*cnt].ifname, ip_config->ifname, INTERFACE_NAMSIZ - 1);
config_buff[*cnt].family = (uchar)ip_config->family;
config_buff[*cnt].prefixlen = (uchar)ip_config->prefixlen;
config_buff[*cnt].prefix.s_addr = inet_addr(ip_config->ipaddr);
conf_type[*cnt] = ip_config->config_type;
(*cnt)++;
}
}
s2j_delete_struct_obj(ip_config);
cJSON_Delete(json_obj);
return RET_OK;
}
ret_code ip_config_format_json(ip_config_t *config_buff,
pointer output, int *outlen)
{
ip_config_string_t tem_buff = {0};
ip_config_string_t *ip_config = &tem_buff;
char *json_ip;
ip_config->family = AF_INET;
ip_config->prefixlen = config_buff->prefixlen;
strncpy(ip_config->ifname, config_buff->ifname, INTERFACE_NAMSIZ - 1);
strncpy(ip_config->ipaddr, inet_ntoa(config_buff->prefix), DOT_IP_STR - 1);
s2j_create_json_obj(json_obj);
if(json_obj == NULL)
{
return RET_NOMEM;
}
s2j_json_set_basic_element(json_obj, ip_config, string, ifname);
s2j_json_set_basic_element(json_obj, ip_config, int, family);
s2j_json_set_basic_element(json_obj, ip_config, string, ipaddr);
s2j_json_set_basic_element(json_obj, ip_config, int, prefixlen);
*outlen = cm_format_data(RET_OK, json_obj, output);
return RET_OK;
}
ret_code ip_config_format_json_array(ip_config_t *config_buff,
int count, pointer output,
int *outlen)
{
ip_config_string_t tem_buff = {0};
ip_config_string_t *ip_config = &tem_buff;
cJSON *json_array = NULL;
int i;
json_array = cJSON_CreateArray();
if(json_array == NULL)
{
return RET_NOMEM;
}
for(i = 0; i < count; i++)
{
memset(ip_config, 0, sizeof(ip_config_string_t));
ip_config->family = AF_INET;
ip_config->prefixlen = config_buff[i].prefixlen;
strncpy(ip_config->ifname, config_buff[i].ifname, INTERFACE_NAMSIZ - 1);
strncpy(ip_config->ipaddr, inet_ntoa(config_buff[i].prefix), DOT_IP_STR - 1);
s2j_create_json_obj(json_obj);
if(json_obj == NULL)
{
return RET_NOMEM;
}
s2j_json_set_basic_element(json_obj, ip_config, string, ifname);
s2j_json_set_basic_element(json_obj, ip_config, int, family);
s2j_json_set_basic_element(json_obj, ip_config, string, ipaddr);
s2j_json_set_basic_element(json_obj, ip_config, int, prefixlen);
cJSON_AddItemToArray(json_array, json_obj);
}
*outlen = cm_format_data(RET_OK, json_array, output);
return RET_OK;
}
ret_code if_set_prefix(ip_config_t *ip_conf, int *code)
{
ret_code ret;
struct ifreq ifreq = {0};
struct sockaddr_in addr;
struct sockaddr_in mask;
strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1);
addr.sin_addr = ip_conf->prefix;
addr.sin_family = ip_conf->family;
memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in));
ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq, code);
ASSERT_RET(ret);
if(ip_conf->prefix.s_addr != 0)
{
masklen2ip(ip_conf->prefixlen, &mask.sin_addr);
mask.sin_family = ip_conf->family;
memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in));
ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq, code);
ASSERT_RET(ret);
}
return RET_OK;
}
ret_code if_get_prefix(ip_config_t *ip_conf, int *code)
{
struct sockaddr_in *addr;
struct ifreq netmask;
struct ifreq ifreq;
ret_code ret = RET_OK;
int mask_ret;
int i;
if(ip_conf->family != AF_INET)
{
ret = RET_INPUTERR;
}
ASSERT_RET(ret);
memset(&ifreq, 0, sizeof(struct ifreq));
rpc_log_info("get interface %s info\n", ip_conf->ifname);
strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1);
ret = if_ioctl(SIOCGIFADDR, (caddr_t)&ifreq, code);
ASSERT_RET(ret);
ip_conf->prefix = ((struct sockaddr_in *)&(ifreq.ifr_addr))->sin_addr;
memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1);
ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&ifreq, &mask_ret);
ASSERT_RET_NO(ret);
addr = ( struct sockaddr_in * )&(ifreq.ifr_netmask);
ip_conf->prefixlen = ip_masklen(addr->sin_addr);
return ret;
}
ret_code if_get_prefix_all(pointer output, int *output_len, int *code)
{
struct ifreq ifreq[MAX_IF_NUM];
struct sockaddr_in *addr;
struct ifreq netmask;
ip_config_t *ip_conf;
struct ifconf ifc;
int if_count = 0;
ret_code ret;
int mask_ret;
int i;
memset(ifreq, 0, MAX_IF_NUM * sizeof(struct ifreq));
if_count = if_read_dev_file(ifreq, MAX_IF_NUM);
if(if_count == 0)
{
memset(&ifc, 0, sizeof(struct ifconf));
ifc.ifc_len = MAX_IF_NUM * sizeof(struct ifreq);
ifc.ifc_buf = (char *)ifreq;
ret = if_ioctl(SIOCGIFCONF, (caddr_t)&ifc, code);
ASSERT_RET(ret);
if_count = ifc.ifc_len / (sizeof(struct ifreq));
}
rpc_log_info("if num is %d\n", if_count);
if((if_count * sizeof(ip_config_t) > CM_BUFF_SIZE)
|| (if_count == 0))
{
ret = RET_NOMEM;
ASSERT_RET(ret);
}
ip_conf = rpc_new0(ip_config_t, MAX_IF_NUM);
if(ip_conf == NULL)
{
return RET_NOMEM;
}
for(i = 0; i < if_count; i++)
{
rpc_log_info("get interface %s info\n", ifreq[i].ifr_name);
strncpy(ip_conf[i].ifname, ifreq[i].ifr_name, INTERFACE_NAMSIZ - 1);
ip_conf[i].family = AF_INET;
if_get_prefix(&ip_conf[i], code);
}
ip_config_format_json_array(ip_conf, if_count, output, output_len);
rpc_free(ip_conf);
return RET_OK;
}
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 (config_type != CM_CONFIG_DEL && ipv4_martian(&ip_conf->prefix))
{
ret = RET_IPINVALID;
}
ASSERT_RET(ret);
if(ip_conf->prefixlen == 0 || ip_conf->prefixlen > IPV4_MAX_PREFIXLEN)
{
ip_conf->prefixlen = IPV4_DEFAULT_PREFIXLEN;
}
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_conf;
ip_conf = (ip_config_t *)input;
if(input_len < sizeof(ip_config_t)
|| strlen(ip_conf->ifname) == 0 )
{
ret = RET_INPUTERR;
}
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;
}
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;
int code = 0;
ip_config_json_parse(input, &conf_type, &ip_config);
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, code, output, *output_len);
return ret;
}
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 conf_buff = {0};
ip_config_t *ip_conf = &conf_buff;
ret_code ret = RET_OK;
int code;
ip_conf = (ip_config_t *)input;
if(conf_type == CM_CONFIG_DEL)
{
ip_conf->prefix.s_addr = 0;
ip_conf->prefixlen = IPV4_DEFAULT_PREFIXLEN;
}
rpc_log_info("config type is %d, if %s ip %s prefixlen %d\n",
conf_type, ip_conf->ifname,
inet_ntoa(ip_conf->prefix),
ip_conf->prefixlen);
ret = if_set_prefix(ip_conf, &code);
RET_ERR_FORMART(ret, code, output, *output_len);
ASSERT_RET(ret);
ip_save_file(ip_conf, conf_type);
return RET_OK;
}
ret_code ip_config_get(uint source,
pointer input, int input_len,
pointer output, int *output_len)
{
ip_config_t *ip_conf;
ret_code ret = RET_OK;
int code, conf_type;
ip_conf = (ip_config_t *)input;
ret = if_get_prefix(ip_conf, &code);
RET_ERR_FORMART(ret, code, output, *output_len);
ASSERT_RET(ret);
ip_config_format_json(ip_conf, output, output_len);
return ret;
}
ret_code ip_config_get_all(uint source, pointer output, int *output_len)
{
ret_code ret = RET_OK;
int code = 0;
*output_len = 0;
ret = if_get_prefix_all(output, output_len, &code);
rpc_log_info("ip_config_get_all: %s\n", (char *)output);
RET_ERR_FORMART(ret, code, output, *output_len);
ASSERT_RET(ret);
return RET_OK;
}