Пример #1
0
int str_to_u64(const char *str, __u64 *u64_out, __u64 min, __u64 max)
{
	unsigned long long int result;
	int error;

	error = str_to_ull(str, NULL, min, max, &result);

	*u64_out = result;
	return error;
}
Пример #2
0
int str_to_port_range(char *str, struct port_range *range)
{
	unsigned long long int tmp;
	char *endptr = NULL;
	int error;

	error = str_to_ull(str, &endptr, 0, 65535, &tmp);
	if (error)
		return error;
	range->min = tmp;

	if (*endptr != '-') {
		range->max = range->min;
		return 0;
	}

	error = str_to_ull(endptr + 1, NULL, 0, 65535, &tmp);
	if (!error)
		range->max = tmp;
	return error;
}
Пример #3
0
static int main_config_parser_cb(const char *path,
                                 char *key,
                                 char *value,
                                 enum parser_cb_type type,
                                 const char **error_string,
                                 icmap_map_t config_map,
                                 void *user_data)
{
    int ii;
    long long int val;
    long long int min_val, max_val;
    icmap_value_types_t val_type = ICMAP_VALUETYPE_BINARY;
    unsigned long long int ull;
    int add_as_string;
    char key_name[ICMAP_KEYNAME_MAXLEN];
    static char formated_err[256];
    struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
    struct key_value_list_item *kv_item;
    struct list_head *iter, *iter_next;
    int uid, gid;

    switch (type) {
    case PARSER_CB_START:
        memset(data, 0, sizeof(struct main_cp_cb_data));
        data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
        break;
    case PARSER_CB_END:
        break;
    case PARSER_CB_ITEM:
        add_as_string = 1;

        switch (data->state) {
        case MAIN_CP_CB_DATA_STATE_NORMAL:
            break;
        case MAIN_CP_CB_DATA_STATE_PLOAD:
            if ((strcmp(path, "pload.count") == 0) ||
                    (strcmp(path, "pload.size") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT32;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint32_r(config_map, path, val);
                add_as_string = 0;
            }
            break;
        case MAIN_CP_CB_DATA_STATE_QUORUM:
            if ((strcmp(path, "quorum.expected_votes") == 0) ||
                    (strcmp(path, "quorum.votes") == 0) ||
                    (strcmp(path, "quorum.last_man_standing_window") == 0) ||
                    (strcmp(path, "quorum.leaving_timeout") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT32;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint32_r(config_map, path, val);
                add_as_string = 0;
            }

            if ((strcmp(path, "quorum.two_node") == 0) ||
                    (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
                    (strcmp(path, "quorum.allow_downscale") == 0) ||
                    (strcmp(path, "quorum.wait_for_all") == 0) ||
                    (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
                    (strcmp(path, "quorum.last_man_standing") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT8;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint8_r(config_map, path, val);
                add_as_string = 0;
            }
            break;
        case MAIN_CP_CB_DATA_STATE_QDEVICE:
            if ((strcmp(path, "quorum.device.timeout") == 0) ||
                    (strcmp(path, "quorum.device.votes") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT32;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint32_r(config_map, path, val);
                add_as_string = 0;
            }
            if ((strcmp(path, "quorum.device.master_wins") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT8;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint8_r(config_map, path, val);
                add_as_string = 0;
            }
            break;
        case MAIN_CP_CB_DATA_STATE_TOTEM:
            if ((strcmp(path, "totem.version") == 0) ||
                    (strcmp(path, "totem.nodeid") == 0) ||
                    (strcmp(path, "totem.threads") == 0) ||
                    (strcmp(path, "totem.token") == 0) ||
                    (strcmp(path, "totem.token_coefficient") == 0) ||
                    (strcmp(path, "totem.token_retransmit") == 0) ||
                    (strcmp(path, "totem.hold") == 0) ||
                    (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
                    (strcmp(path, "totem.join") == 0) ||
                    (strcmp(path, "totem.send_join") == 0) ||
                    (strcmp(path, "totem.consensus") == 0) ||
                    (strcmp(path, "totem.merge") == 0) ||
                    (strcmp(path, "totem.downcheck") == 0) ||
                    (strcmp(path, "totem.fail_recv_const") == 0) ||
                    (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
                    (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
                    (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
                    (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
                    (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
                    (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
                    (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
                    (strcmp(path, "totem.max_network_delay") == 0) ||
                    (strcmp(path, "totem.window_size") == 0) ||
                    (strcmp(path, "totem.max_messages") == 0) ||
                    (strcmp(path, "totem.miss_count_const") == 0) ||
                    (strcmp(path, "totem.netmtu") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT32;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint32_r(config_map,path, val);
                add_as_string = 0;
            }
            if (strcmp(path, "totem.config_version") == 0) {
                if (str_to_ull(value, &ull) != 0) {
                    goto atoi_error;
                }
                icmap_set_uint64_r(config_map, path, ull);
                add_as_string = 0;
            }
            if (strcmp(path, "totem.ip_version") == 0) {
                if ((strcmp(value, "ipv4") != 0) &&
                        (strcmp(value, "ipv6") != 0)) {
                    *error_string = "Invalid ip_version type";

                    return (0);
                }
            }
            if (strcmp(path, "totem.crypto_type") == 0) {
                if ((strcmp(value, "nss") != 0) &&
                        (strcmp(value, "aes256") != 0) &&
                        (strcmp(value, "aes192") != 0) &&
                        (strcmp(value, "aes128") != 0) &&
                        (strcmp(value, "3des") != 0)) {
                    *error_string = "Invalid crypto type";

                    return (0);
                }
            }
            if (strcmp(path, "totem.crypto_cipher") == 0) {
                if ((strcmp(value, "none") != 0) &&
                        (strcmp(value, "aes256") != 0) &&
                        (strcmp(value, "aes192") != 0) &&
                        (strcmp(value, "aes128") != 0) &&
                        (strcmp(value, "3des") != 0)) {
                    *error_string = "Invalid cipher type";

                    return (0);
                }
            }
            if (strcmp(path, "totem.crypto_hash") == 0) {
                if ((strcmp(value, "none") != 0) &&
                        (strcmp(value, "md5") != 0) &&
                        (strcmp(value, "sha1") != 0) &&
                        (strcmp(value, "sha256") != 0) &&
                        (strcmp(value, "sha384") != 0) &&
                        (strcmp(value, "sha512") != 0)) {
                    *error_string = "Invalid hash type";

                    return (0);
                }
            }
            break;

        case MAIN_CP_CB_DATA_STATE_QB:
            if (strcmp(path, "qb.ipc_type") == 0) {
                if ((strcmp(value, "native") != 0) &&
                        (strcmp(value, "shm") != 0) &&
                        (strcmp(value, "socket") != 0)) {
                    *error_string = "Invalid qb ipc_type";

                    return (0);
                }
            }
            break;

        case MAIN_CP_CB_DATA_STATE_INTERFACE:
            if (strcmp(path, "totem.interface.ringnumber") == 0) {
                val_type = ICMAP_VALUETYPE_UINT8;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }

                data->ringnumber = val;
                add_as_string = 0;
            }
            if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
                data->bindnetaddr = strdup(value);
                add_as_string = 0;
            }
            if (strcmp(path, "totem.interface.mcastaddr") == 0) {
                data->mcastaddr = strdup(value);
                add_as_string = 0;
            }
            if (strcmp(path, "totem.interface.broadcast") == 0) {
                data->broadcast = strdup(value);
                add_as_string = 0;
            }
            if (strcmp(path, "totem.interface.mcastport") == 0) {
                val_type = ICMAP_VALUETYPE_UINT16;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                data->mcastport = val;
                add_as_string = 0;
            }
            if (strcmp(path, "totem.interface.ttl") == 0) {
                val_type = ICMAP_VALUETYPE_UINT8;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }
                data->ttl = val;
                add_as_string = 0;
            }
            break;
        case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
            if (strcmp(key, "subsys") == 0) {
                data->subsys = strdup(value);
                if (data->subsys == NULL) {
                    *error_string = "Can't alloc memory";

                    return (0);
                }
            } else {
                kv_item = malloc(sizeof(*kv_item));
                if (kv_item == NULL) {
                    *error_string = "Can't alloc memory";

                    return (0);
                }
                memset(kv_item, 0, sizeof(*kv_item));

                kv_item->key = strdup(key);
                kv_item->value = strdup(value);
                if (kv_item->key == NULL || kv_item->value == NULL) {
                    free(kv_item);
                    *error_string = "Can't alloc memory";

                    return (0);
                }
                list_init(&kv_item->list);
                list_add(&kv_item->list, &data->logger_subsys_items_head);
            }
            add_as_string = 0;
            break;
        case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
            if (strcmp(key, "subsys") == 0) {
                data->subsys = strdup(value);
                if (data->subsys == NULL) {
                    *error_string = "Can't alloc memory";

                    return (0);
                }
            } else if (strcmp(key, "name") == 0) {
                data->logging_daemon_name = strdup(value);
                if (data->logging_daemon_name == NULL) {
                    *error_string = "Can't alloc memory";

                    return (0);
                }
            } else {
                kv_item = malloc(sizeof(*kv_item));
                if (kv_item == NULL) {
                    *error_string = "Can't alloc memory";

                    return (0);
                }
                memset(kv_item, 0, sizeof(*kv_item));

                kv_item->key = strdup(key);
                kv_item->value = strdup(value);
                if (kv_item->key == NULL || kv_item->value == NULL) {
                    free(kv_item);
                    *error_string = "Can't alloc memory";

                    return (0);
                }
                list_init(&kv_item->list);
                list_add(&kv_item->list, &data->logger_subsys_items_head);
            }
            add_as_string = 0;
            break;
        case MAIN_CP_CB_DATA_STATE_UIDGID:
            if (strcmp(key, "uid") == 0) {
                uid = uid_determine(value);
                if (uid == -1) {
                    *error_string = error_string_response;
                    return (0);
                }
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
                         uid);
                icmap_set_uint8_r(config_map, key_name, 1);
                add_as_string = 0;
            } else if (strcmp(key, "gid") == 0) {
                gid = gid_determine(value);
                if (gid == -1) {
                    *error_string = error_string_response;
                    return (0);
                }
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
                         gid);
                icmap_set_uint8_r(config_map, key_name, 1);
                add_as_string = 0;
            } else {
                *error_string = "uidgid: Only uid and gid are allowed items";
                return (0);
            }
            break;
        case MAIN_CP_CB_DATA_STATE_MEMBER:
            if (strcmp(key, "memberaddr") != 0) {
                *error_string = "Only memberaddr is allowed in member section";

                return (0);
            }

            kv_item = malloc(sizeof(*kv_item));
            if (kv_item == NULL) {
                *error_string = "Can't alloc memory";

                return (0);
            }
            memset(kv_item, 0, sizeof(*kv_item));

            kv_item->key = strdup(key);
            kv_item->value = strdup(value);
            if (kv_item->key == NULL || kv_item->value == NULL) {
                free(kv_item);
                *error_string = "Can't alloc memory";

                return (0);
            }
            list_init(&kv_item->list);
            list_add(&kv_item->list, &data->member_items_head);
            add_as_string = 0;
            break;
        case MAIN_CP_CB_DATA_STATE_NODELIST:
            break;
        case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
            snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
            if ((strcmp(key, "nodeid") == 0) ||
                    (strcmp(key, "quorum_votes") == 0)) {
                val_type = ICMAP_VALUETYPE_UINT32;
                if (safe_atoq(value, &val, val_type) != 0) {
                    goto atoi_error;
                }

                icmap_set_uint32_r(config_map, key_name, val);
                add_as_string = 0;
            }

            if (strcmp(key, "ring0_addr") == 0) {
                data->ring0_addr_added = 1;
            }

            if (add_as_string) {
                icmap_set_string_r(config_map, key_name, value);
                add_as_string = 0;
            }
            break;
        }

        if (add_as_string) {
            icmap_set_string_r(config_map, path, value);
        }
        break;
    case PARSER_CB_SECTION_START:
        if (strcmp(path, "totem.interface") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
            data->ringnumber = 0;
            data->mcastport = -1;
            data->ttl = -1;
            list_init(&data->member_items_head);
        };
        if (strcmp(path, "totem") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
        };
        if (strcmp(path, "qb") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_QB;
        }
        if (strcmp(path, "logging.logger_subsys") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS;
            list_init(&data->logger_subsys_items_head);
            data->subsys = NULL;
        }
        if (strcmp(path, "logging.logging_daemon") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON;
            list_init(&data->logger_subsys_items_head);
            data->subsys = NULL;
            data->logging_daemon_name = NULL;
        }
        if (strcmp(path, "uidgid") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
        }
        if (strcmp(path, "totem.interface.member") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_MEMBER;
        }
        if (strcmp(path, "quorum") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_QUORUM;
        }
        if (strcmp(path, "quorum.device") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_QDEVICE;
        }
        if (strcmp(path, "nodelist") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_NODELIST;
            data->node_number = 0;
        }
        if (strcmp(path, "nodelist.node") == 0) {
            data->state = MAIN_CP_CB_DATA_STATE_NODELIST_NODE;
            data->ring0_addr_added = 0;
        }
        break;
    case PARSER_CB_SECTION_END:
        switch (data->state) {
        case MAIN_CP_CB_DATA_STATE_NORMAL:
            break;
        case MAIN_CP_CB_DATA_STATE_PLOAD:
            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_INTERFACE:
            /*
             * Create new interface section
             */
            if (data->bindnetaddr != NULL) {
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
                         data->ringnumber);
                icmap_set_string_r(config_map, key_name, data->bindnetaddr);

                free(data->bindnetaddr);
                data->bindnetaddr = NULL;
            }

            if (data->mcastaddr != NULL) {
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
                         data->ringnumber);
                icmap_set_string_r(config_map, key_name, data->mcastaddr);

                free(data->mcastaddr);
                data->mcastaddr = NULL;
            }

            if (data->broadcast != NULL) {
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
                         data->ringnumber);
                icmap_set_string_r(config_map, key_name, data->broadcast);

                free(data->broadcast);
                data->broadcast = NULL;
            }

            if (data->mcastport > -1) {
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
                         data->ringnumber);
                icmap_set_uint16_r(config_map, key_name, data->mcastport);
            }

            if (data->ttl > -1) {
                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
                         data->ringnumber);
                icmap_set_uint8_r(config_map, key_name, data->ttl);
            }

            ii = 0;
            for (iter = data->member_items_head.next;
                    iter != &data->member_items_head; iter = iter_next) {
                kv_item = list_entry(iter, struct key_value_list_item, list);

                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
                         data->ringnumber, ii);
                icmap_set_string_r(config_map, key_name, kv_item->value);

                iter_next = iter->next;

                free(kv_item->value);
                free(kv_item->key);
                free(kv_item);
                ii++;
            }

            data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
            break;
        case MAIN_CP_CB_DATA_STATE_TOTEM:
            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_QB:
            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
            if (data->subsys == NULL) {
                *error_string = "No subsys key in logger_subsys directive";

                return (0);
            }

            for (iter = data->logger_subsys_items_head.next;
                    iter != &data->logger_subsys_items_head; iter = iter_next) {
                kv_item = list_entry(iter, struct key_value_list_item, list);

                snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
                         data->subsys, kv_item->key);
                icmap_set_string_r(config_map, key_name, kv_item->value);

                iter_next = iter->next;

                free(kv_item->value);
                free(kv_item->key);
                free(kv_item);
            }

            snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
                     data->subsys);
            icmap_set_string_r(config_map, key_name, data->subsys);

            free(data->subsys);

            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
            if (data->logging_daemon_name == NULL) {
                *error_string = "No name key in logging_daemon directive";

                return (0);
            }

            for (iter = data->logger_subsys_items_head.next;
                    iter != &data->logger_subsys_items_head; iter = iter_next) {
                kv_item = list_entry(iter, struct key_value_list_item, list);

                if (data->subsys == NULL) {
                    if (strcmp(data->logging_daemon_name, "corosync") == 0) {
                        snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
                                 "logging.%s",
                                 kv_item->key);
                    } else {
                        snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
                                 "logging.logging_daemon.%s.%s",
                                 data->logging_daemon_name, kv_item->key);
                    }
                } else {
                    if (strcmp(data->logging_daemon_name, "corosync") == 0) {
                        snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
                                 "logging.logger_subsys.%s.%s",
                                 data->subsys,
                                 kv_item->key);
                    } else {
                        snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
                                 "logging.logging_daemon.%s.%s.%s",
                                 data->logging_daemon_name, data->subsys,
                                 kv_item->key);
                    }
                }
                icmap_set_string_r(config_map, key_name, kv_item->value);

                iter_next = iter->next;

                free(kv_item->value);
                free(kv_item->key);
                free(kv_item);
            }

            if (data->subsys == NULL) {
                if (strcmp(data->logging_daemon_name, "corosync") != 0) {
                    snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
                             data->logging_daemon_name);
                    icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
                }
            } else {
                if (strcmp(data->logging_daemon_name, "corosync") == 0) {
                    snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
                             data->subsys);
                    icmap_set_string_r(config_map, key_name, data->subsys);

                } else {
                    snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
                             data->logging_daemon_name, data->subsys);
                    icmap_set_string_r(config_map, key_name, data->subsys);
                    snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
                             data->logging_daemon_name, data->subsys);
                    icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
                }
            }

            free(data->subsys);
            free(data->logging_daemon_name);

            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_UIDGID:
            data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
            break;
        case MAIN_CP_CB_DATA_STATE_MEMBER:
            data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
            break;
        case MAIN_CP_CB_DATA_STATE_QUORUM:
            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_QDEVICE:
            data->state = MAIN_CP_CB_DATA_STATE_QUORUM;
            break;
        case MAIN_CP_CB_DATA_STATE_NODELIST:
            data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
            break;
        case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
            if (!data->ring0_addr_added) {
                *error_string = "No ring0_addr specified for node";

                return (0);
            }
            data->node_number++;
            data->state = MAIN_CP_CB_DATA_STATE_NODELIST;
            break;
        }
        break;
    }

    return (1);

atoi_error:
    min_val = max_val = 0;
    /*
     * This is really assert, because developer ether doesn't set val_type correctly or
     * we've got here after some nasty memory overwrite
     */
    assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);

    snprintf(formated_err, sizeof(formated_err),
             "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
             key, min_val, max_val, value);
    *error_string = formated_err;

    return (0);
}