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