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

562 lines
15 KiB
C
Raw Normal View History

#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_log_info("json input:\n %s \n", cJSON_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_log_info("json input:%s \n", cJSON_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;
}
cJSON_AddItemToArray(json_array, json_obj);
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_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;
}