#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_N(ip_config, json_obj, ifname, INTERFACE_NAMSIZ); s2j_struct_get_basic_element(ip_config, json_obj, int, family); S2J_STRUCT_GET_STRING_ELEMENT_N(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); *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, json_obj, int, config_type); s2j_struct_get_basic_element(ip_config, json_obj, string, ifname); s2j_struct_get_basic_element(ip_config, json_obj, int, family); s2j_struct_get_basic_element(ip_config, json_obj, string, ipaddr); s2j_struct_get_basic_element(ip_config, json_obj, 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; //cJSON *json_obj = NULL; 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); /* create Student JSON object */ 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); json_ip = cJSON_PrintUnformatted(json_obj); *outlen = strlen(json_ip) + 1; memcpy(output, json_ip, *outlen); free(json_ip); cJSON_Delete(json_obj); 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; //cJSON *json_obj = NULL; char *json_ip; 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); /* create Student JSON object */ 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); } json_ip = cJSON_PrintUnformatted(json_array); *outlen = strlen(json_ip) + 1; memcpy(output, json_ip, *outlen); free(json_ip); cJSON_Delete(json_array); 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; 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) - 1); 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); } 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", output); RET_ERR_FORMART(ret, code, output, *output_len); ASSERT_RET(ret); return RET_OK; }