2019-06-18 07:54:42 +00:00
|
|
|
#include "configm.h"
|
|
|
|
#include "ipconfig.h"
|
|
|
|
#include "rpc.h"
|
|
|
|
#include "parsefile.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));
|
2019-06-27 07:27:41 +00:00
|
|
|
rpc_log_info("%s %s",addr_buff, mask_buff);
|
2019-06-18 07:54:42 +00:00
|
|
|
|
|
|
|
set_if_config(ip_conf->ifname, addr_name, addr_buff);
|
|
|
|
set_if_config(ip_conf->ifname, mask_name, mask_buff);
|
|
|
|
}
|
|
|
|
else if(config_type == CM_CONFIG_DEL)
|
|
|
|
{
|
|
|
|
del_if_config(ip_conf->ifname, addr_name);
|
|
|
|
del_if_config(ip_conf->ifname, mask_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* call ioctl system call */
|
|
|
|
ret_code if_ioctl(unsigned long request, caddr_t ifreq, int *ret)
|
|
|
|
{
|
|
|
|
int sock;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
*ret = 0;
|
|
|
|
|
|
|
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sock < 0)
|
|
|
|
{
|
|
|
|
rpc_log_error("Cannot create UDP socket");
|
|
|
|
return RET_SOCKERR;
|
|
|
|
}
|
|
|
|
if ((*ret = ioctl(sock, request, ifreq)) < 0)
|
|
|
|
{
|
|
|
|
err = errno;
|
|
|
|
rpc_log_error("Ioctl error: %s\n", strerror(errno));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
close(sock);
|
|
|
|
|
|
|
|
if (*ret < 0)
|
|
|
|
{
|
|
|
|
errno = err;
|
|
|
|
*ret = err;
|
|
|
|
return RET_SYSERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_code if_set_prefix(ip_config_t *ip_conf, int *code)
|
|
|
|
{
|
|
|
|
ret_code ret;
|
|
|
|
struct ifreq ifreq;
|
|
|
|
struct sockaddr_in addr;
|
|
|
|
struct sockaddr_in mask;
|
|
|
|
|
|
|
|
strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name));
|
|
|
|
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 0;
|
|
|
|
}
|
|
|
|
|
2019-06-26 08:48:45 +00:00
|
|
|
ret_code if_get_prefix_all(ip_config_t *ip_conf, short *single_len, int *cnt, int *code)
|
2019-06-18 07:54:42 +00:00
|
|
|
{
|
|
|
|
struct ifreq ifreq[MAX_IF_NUM];
|
|
|
|
struct sockaddr_in *addr;
|
|
|
|
struct ifreq netmask;
|
|
|
|
struct ifconf ifc;
|
|
|
|
int if_count = 0;
|
|
|
|
ret_code ret;
|
|
|
|
int mask_ret;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
memset(&ifc, 0, sizeof(struct ifconf));
|
|
|
|
memset(&ifreq, 0, MAX_IF_NUM * sizeof(struct ifreq));
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
ret = RET_NOMEM;
|
|
|
|
ASSERT_RET(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
*cnt = 0;
|
|
|
|
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);
|
|
|
|
ip_conf[i].family = AF_INET;
|
|
|
|
ip_conf[i].prefix = ((struct sockaddr_in *)&(ifreq[i].ifr_addr))->sin_addr;
|
|
|
|
|
|
|
|
memset(&netmask, 0, sizeof(netmask));
|
|
|
|
strncpy(netmask.ifr_name, ifreq[i].ifr_name, sizeof(netmask.ifr_name));
|
|
|
|
|
|
|
|
ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&netmask, &mask_ret);
|
|
|
|
ASSERT_RET_NO(ret);
|
|
|
|
|
|
|
|
addr = ( struct sockaddr_in * )&(netmask.ifr_netmask );
|
|
|
|
ip_conf[i].prefixlen = ip_masklen(addr->sin_addr);
|
|
|
|
|
2019-06-26 08:48:45 +00:00
|
|
|
single_len[i] = sizeof(ip_config_t);
|
|
|
|
|
2019-06-18 07:54:42 +00:00
|
|
|
(*cnt)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
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 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;
|
|
|
|
}
|
|
|
|
|
2019-06-27 07:27:41 +00:00
|
|
|
if (config_type != CM_CONFIG_DEL && ipv4_martian(&ip_conf->prefix))
|
2019-06-18 07:54:42 +00:00
|
|
|
{
|
|
|
|
ret = RET_IPINVALID;
|
|
|
|
}
|
|
|
|
|
2019-06-27 07:27:41 +00:00
|
|
|
|
2019-06-18 07:54:42 +00:00
|
|
|
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)
|
|
|
|
|
|
|
|
{
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
int code = 0;
|
|
|
|
|
|
|
|
switch (config_type)
|
|
|
|
{
|
|
|
|
case CM_CONFIG_SET:
|
|
|
|
case CM_CONFIG_DEL:
|
|
|
|
ret = ip_config_set_chk(source, config_type,
|
|
|
|
input, input_len,
|
|
|
|
output, output_len);
|
|
|
|
break;
|
|
|
|
case CM_CONFIG_GET:
|
|
|
|
ret = ip_config_get_chk(source, config_type,
|
|
|
|
input, input_len,
|
|
|
|
output, output_len);
|
|
|
|
break;
|
|
|
|
case CM_CONFIG_GET_ALL:
|
|
|
|
ret = ip_config_getall_chk(source, config_type,
|
|
|
|
input, input_len,
|
|
|
|
output, output_len);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = RET_NOTSUPPORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
ip_config_t *ip_conf;
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
int code;
|
|
|
|
|
|
|
|
ip_conf = (ip_config_t *)input;
|
|
|
|
|
|
|
|
if(config_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",
|
|
|
|
config_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, config_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;
|
|
|
|
|
|
|
|
ip_conf = (ip_config_t *)input;
|
|
|
|
|
|
|
|
ret = if_get_prefix(ip_conf, &code);
|
|
|
|
|
|
|
|
RET_ERR_FORMART(ret, code, output, *output_len);
|
|
|
|
ASSERT_RET(ret);
|
|
|
|
|
|
|
|
memcpy(output, ip_conf, sizeof(ip_config_t));
|
|
|
|
*output_len = sizeof(ip_config_t);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret_code ip_config_get_all(uint source, uint64 config_id,
|
|
|
|
pointer output, short *single_len,
|
2019-06-26 08:48:45 +00:00
|
|
|
int *count)
|
2019-06-18 07:54:42 +00:00
|
|
|
{
|
2019-06-26 08:48:45 +00:00
|
|
|
int output_len = 0;
|
|
|
|
ret_code ret = RET_OK;
|
|
|
|
int code = 0;
|
2019-06-18 07:54:42 +00:00
|
|
|
|
|
|
|
rpc_log_info("ip_config_get_all\r\n");
|
|
|
|
|
2019-06-26 08:48:45 +00:00
|
|
|
ret = if_get_prefix_all((ip_config_t *)output, single_len, count, &code);
|
2019-06-18 07:54:42 +00:00
|
|
|
|
2019-06-26 08:48:45 +00:00
|
|
|
RET_ERR_FORMART(ret, code, output, output_len);
|
|
|
|
ASSERT_RET(ret);
|
2019-06-18 07:54:42 +00:00
|
|
|
|
|
|
|
return RET_OK;
|
|
|
|
|
|
|
|
}
|