/** * Load subnet array. * @param[in] cfg Config section. * @param[in] option Option name. * @param[in,out] array Resulting array. * @return <0 - error. 0 - success. >0 - not found. */ static int zcfg_load_subnet_list(const config_setting_t *option, zsubnet_group_t *array) { utarray_init(array, &ut_ip_range_icd); if (!option) { return 1; } if (CONFIG_TYPE_LIST != option->type) { return -1; } int count = config_setting_length(option); for (int i = 0; i < count; i++) { ip_range_t range; char ip_str[INET_ADDRSTRLEN]; const char *item = config_setting_get_string_elem(option, i); const char *cidr_pos = strchr(item, '/'); // search CIDR, and make sure, that ip part is not bigger than buffer size if (cidr_pos && (((size_t) (cidr_pos - item) < sizeof(ip_str)))) { strncpy(ip_str, item, cidr_pos - item); ip_str[cidr_pos - item] = '\0'; struct in_addr ip_addr; if (0 < inet_pton(AF_INET, ip_str, &ip_addr)) { uint8_t cidr = 0; if ((0 == str_to_u8(cidr_pos + 1, &cidr)) && (cidr <= CIDR_MAX)) { range.ip_start = ntohl(ip_addr.s_addr); range.ip_end = IP_RANGE_END(range.ip_start, cidr); utarray_push_back(array, &range); continue; } } } // error handler ZLOG(LOG_ERR, "config:%s:%s: invalid subnet: %s", option->parent->name, option->name, item); utarray_done(array); return -1; } if (count) { utarray_sort(array, ip_range_cmp); } return 0; }
/** * Load ip-mask array. * @param[in] cfg Config section. * @param[in] option Option name. * @param[in,out] array Resulting array. * @return Zero on success. */ static int load_ip_mask_list(const config_setting_t *cfg, const char *option, UT_array *array) { config_setting_t *cfg_list = config_setting_get_member(cfg, option); if (!cfg_list) { ZERO_LOG(LOG_ERR, "config: missing %s entry", option); return 0; } if (config_setting_type(cfg_list) != CONFIG_TYPE_LIST) { ZERO_LOG(LOG_ERR, "config: invalid %s entry", option); return -1; } int count = config_setting_length(cfg_list); if (0 >= count) { return 0; } utarray_init(array, &ut_ip_range_icd); for (int i = 0; i < count; i++) { struct ip_range range; const char *entry = config_setting_get_string_elem(cfg_list, i); if (!entry) { ZERO_LOG(LOG_ERR, "config: failed to get next %s record", option); continue; } char ip_str[INET_ADDRSTRLEN]; const char *cidr_pos = strchr(entry, '/'); // we search for CIDR, and make sure, that ip part is not bigger than allowed size if (cidr_pos && ((size_t)(cidr_pos - entry) < sizeof(ip_str))) { strncpy(ip_str, entry, cidr_pos - entry); ip_str[cidr_pos - entry] = '\0'; struct in_addr ip_addr; if (0 < inet_pton(AF_INET, ip_str, &ip_addr)) { u_long cidr = strtoul(cidr_pos + 1, NULL, 10); if (cidr != ULONG_MAX && cidr <= 32) { range.ip_start = ntohl(ip_addr.s_addr); range.ip_end = IP_RANGE_END(range.ip_start, cidr); utarray_push_back(array, &range); continue; } } } // if we here, then entry is invalid ZERO_LOG(LOG_ERR, "config: invalid %s item: %s", option, entry); utarray_done(array); return -1; } utarray_sort(array, ip_range_cmp); return 0; }