38 #include <sys/types.h>
40 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
58 #include <qb/qbutil.h>
59 #define LOGSYS_UTILS_ONLY 1
78 const char **error_string,
123 static int read_config_file_into_icmap(
124 const char **error_string,
icmap_map_t config_map);
125 static char error_string_response[512];
127 static int uid_determine (
const char *req_user)
130 struct passwd passwd;
131 struct passwd* pwdptr = &passwd;
132 struct passwd* temp_pwd_pt;
138 id = strtol(req_user, &ep, 10);
139 if (*ep ==
'\0' &&
id >= 0 &&
id <= UINT_MAX) {
143 pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
145 if (pwdlinelen == -1) {
149 pwdbuffer = malloc (pwdlinelen);
151 while ((rc = getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) == ERANGE) {
155 if (pwdlinelen <= 32678) {
156 n = realloc (pwdbuffer, pwdlinelen);
165 sprintf (error_string_response,
"getpwnam_r(): %s", strerror(rc));
168 if (temp_pwd_pt == NULL) {
170 sprintf (error_string_response,
171 "The '%s' user is not found in /etc/passwd, please read the documentation.",
175 pw_uid = passwd.pw_uid;
181 static int gid_determine (
const char *req_group)
183 int corosync_gid = 0;
185 struct group * grpptr = &group;
186 struct group * temp_grp_pt;
192 id = strtol(req_group, &ep, 10);
193 if (*ep ==
'\0' &&
id >= 0 &&
id <= UINT_MAX) {
197 grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
199 if (grplinelen == -1) {
203 grpbuffer = malloc (grplinelen);
205 while ((rc = getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) == ERANGE) {
209 if (grplinelen <= 32678) {
210 n = realloc (grpbuffer, grplinelen);
219 sprintf (error_string_response,
"getgrnam_r(): %s", strerror(rc));
222 if (temp_grp_pt == NULL) {
224 sprintf (error_string_response,
225 "The '%s' group is not found in /etc/group, please read the documentation.",
229 corosync_gid = group.gr_gid;
234 static char *strchr_rs (
const char *haystack,
int byte)
236 const char *end_address = strchr (haystack, byte);
240 while (*end_address ==
' ' || *end_address ==
'\t')
244 return ((
char *) end_address);
249 if (read_config_file_into_icmap(error_string, config_map)) {
256 static char *remove_whitespace(
char *
string,
int remove_colon_and_brace)
262 while (*start ==
' ' || *start ==
'\t')
265 end = start+(strlen(start))-1;
266 while ((*end ==
' ' || *end ==
'\t' || (remove_colon_and_brace && (*end ==
':' || *end ==
'{'))) && end > start)
276 static int parse_section(FILE *fp,
278 const char **error_string,
290 if (strcmp(path,
"") == 0) {
291 parser_cb(
"", NULL, NULL,
PARSER_CB_START, error_string, config_map, user_data);
294 while (fgets (line,
sizeof (line), fp)) {
295 if (strlen(line) > 0) {
296 if (line[strlen(line) - 1] ==
'\n')
297 line[strlen(line) - 1] =
'\0';
298 if (strlen (line) > 0 && line[strlen(line) - 1] ==
'\r')
299 line[strlen(line) - 1] =
'\0';
304 for (i = strlen (line) - 1; i > -1; i--) {
305 if (line[i] ==
'\t' || line[i] ==
' ') {
313 for (i = 0; i < strlen (line); i++) {
314 if (line[i] !=
'\t' && line[i] !=
' ') {
329 if ((loc = strchr_rs (line,
'{'))) {
330 char *section = remove_whitespace(line, 1);
336 *error_string =
"parser error: Start of section makes total cmap path too long";
339 strcpy(new_keyname, path);
340 if (strcmp(path,
"") != 0) {
341 strcat(new_keyname,
".");
343 strcat(new_keyname, section);
349 if (parse_section(fp, new_keyname, error_string, depth + 1, parser_cb, config_map, user_data))
356 if ((loc = strchr_rs (line,
':'))) {
361 key = remove_whitespace(line, 1);
362 value = remove_whitespace(loc, 0);
365 *error_string =
"parser error: New key makes total cmap path too long";
368 strcpy(new_keyname, path);
369 if (strcmp(path,
"") != 0) {
370 strcat(new_keyname,
".");
372 strcat(new_keyname, key);
374 if (!parser_cb(new_keyname, key, value,
PARSER_CB_ITEM, error_string, config_map, user_data)) {
381 if (strchr_rs (line,
'}')) {
383 *error_string =
"parser error: Unexpected closing brace";
396 if (strcmp(path,
"") != 0) {
397 *error_string =
"parser error: Missing closing brace";
401 if (strcmp(path,
"") == 0) {
402 parser_cb(
"", NULL, NULL,
PARSER_CB_END, error_string, config_map, user_data);
408 static int safe_atoq_range(
icmap_value_types_t value_type,
long long int *min_val,
long long int *max_val)
410 switch (value_type) {
432 long long int min_val, max_val;
437 val = strtoll(str, &endptr, 10);
438 if (errno == ERANGE) {
446 if (*endptr !=
'\0') {
450 if (safe_atoq_range(target_type, &min_val, &max_val) != 0) {
454 if (val < min_val || val > max_val) {
462 static int str_to_ull(
const char *str,
unsigned long long int *res)
464 unsigned long long int val;
469 val = strtoull(str, &endptr, 10);
470 if (errno == ERANGE) {
478 if (*endptr !=
'\0') {
486 static int main_config_parser_cb(
const char *path,
490 const char **error_string,
496 long long int min_val, max_val;
498 unsigned long long int ull;
501 static char formated_err[256];
517 switch (data->
state) {
521 if ((strcmp(path,
"pload.count") == 0) ||
522 (strcmp(path,
"pload.size") == 0)) {
524 if (safe_atoq(value, &val, val_type) != 0) {
532 if ((strcmp(path,
"quorum.expected_votes") == 0) ||
533 (strcmp(path,
"quorum.votes") == 0) ||
534 (strcmp(path,
"quorum.last_man_standing_window") == 0) ||
535 (strcmp(path,
"quorum.leaving_timeout") == 0)) {
537 if (safe_atoq(value, &val, val_type) != 0) {
544 if ((strcmp(path,
"quorum.two_node") == 0) ||
545 (strcmp(path,
"quorum.expected_votes_tracking") == 0) ||
546 (strcmp(path,
"quorum.allow_downscale") == 0) ||
547 (strcmp(path,
"quorum.wait_for_all") == 0) ||
548 (strcmp(path,
"quorum.auto_tie_breaker") == 0) ||
549 (strcmp(path,
"quorum.last_man_standing") == 0)) {
551 if (safe_atoq(value, &val, val_type) != 0) {
559 if ((strcmp(path,
"quorum.device.timeout") == 0) ||
560 (strcmp(path,
"quorum.device.sync_timeout") == 0) ||
561 (strcmp(path,
"quorum.device.votes") == 0)) {
563 if (safe_atoq(value, &val, val_type) != 0) {
569 if ((strcmp(path,
"quorum.device.master_wins") == 0)) {
571 if (safe_atoq(value, &val, val_type) != 0) {
579 if ((strcmp(path,
"totem.version") == 0) ||
580 (strcmp(path,
"totem.nodeid") == 0) ||
581 (strcmp(path,
"totem.threads") == 0) ||
582 (strcmp(path,
"totem.token") == 0) ||
583 (strcmp(path,
"totem.token_coefficient") == 0) ||
584 (strcmp(path,
"totem.token_retransmit") == 0) ||
585 (strcmp(path,
"totem.hold") == 0) ||
586 (strcmp(path,
"totem.token_retransmits_before_loss_const") == 0) ||
587 (strcmp(path,
"totem.join") == 0) ||
588 (strcmp(path,
"totem.send_join") == 0) ||
589 (strcmp(path,
"totem.consensus") == 0) ||
590 (strcmp(path,
"totem.merge") == 0) ||
591 (strcmp(path,
"totem.downcheck") == 0) ||
592 (strcmp(path,
"totem.fail_recv_const") == 0) ||
593 (strcmp(path,
"totem.seqno_unchanged_const") == 0) ||
594 (strcmp(path,
"totem.rrp_token_expired_timeout") == 0) ||
595 (strcmp(path,
"totem.rrp_problem_count_timeout") == 0) ||
596 (strcmp(path,
"totem.rrp_problem_count_threshold") == 0) ||
597 (strcmp(path,
"totem.rrp_problem_count_mcast_threshold") == 0) ||
598 (strcmp(path,
"totem.rrp_autorecovery_check_timeout") == 0) ||
599 (strcmp(path,
"totem.heartbeat_failures_allowed") == 0) ||
600 (strcmp(path,
"totem.max_network_delay") == 0) ||
601 (strcmp(path,
"totem.window_size") == 0) ||
602 (strcmp(path,
"totem.max_messages") == 0) ||
603 (strcmp(path,
"totem.miss_count_const") == 0) ||
604 (strcmp(path,
"totem.netmtu") == 0)) {
606 if (safe_atoq(value, &val, val_type) != 0) {
612 if (strcmp(path,
"totem.config_version") == 0) {
613 if (str_to_ull(value, &ull) != 0) {
619 if (strcmp(path,
"totem.ip_version") == 0) {
620 if ((strcmp(value,
"ipv4") != 0) &&
621 (strcmp(value,
"ipv6") != 0)) {
622 *error_string =
"Invalid ip_version type";
627 if (strcmp(path,
"totem.crypto_type") == 0) {
628 if ((strcmp(value,
"nss") != 0) &&
629 (strcmp(value,
"aes256") != 0) &&
630 (strcmp(value,
"aes192") != 0) &&
631 (strcmp(value,
"aes128") != 0) &&
632 (strcmp(value,
"3des") != 0)) {
633 *error_string =
"Invalid crypto type";
638 if (strcmp(path,
"totem.crypto_cipher") == 0) {
639 if ((strcmp(value,
"none") != 0) &&
640 (strcmp(value,
"aes256") != 0) &&
641 (strcmp(value,
"aes192") != 0) &&
642 (strcmp(value,
"aes128") != 0) &&
643 (strcmp(value,
"3des") != 0)) {
644 *error_string =
"Invalid cipher type";
649 if (strcmp(path,
"totem.crypto_hash") == 0) {
650 if ((strcmp(value,
"none") != 0) &&
651 (strcmp(value,
"md5") != 0) &&
652 (strcmp(value,
"sha1") != 0) &&
653 (strcmp(value,
"sha256") != 0) &&
654 (strcmp(value,
"sha384") != 0) &&
655 (strcmp(value,
"sha512") != 0)) {
656 *error_string =
"Invalid hash type";
664 if (strcmp(path,
"qb.ipc_type") == 0) {
665 if ((strcmp(value,
"native") != 0) &&
666 (strcmp(value,
"shm") != 0) &&
667 (strcmp(value,
"socket") != 0)) {
668 *error_string =
"Invalid qb ipc_type";
676 if (strcmp(path,
"totem.interface.ringnumber") == 0) {
678 if (safe_atoq(value, &val, val_type) != 0) {
685 if (strcmp(path,
"totem.interface.bindnetaddr") == 0) {
689 if (strcmp(path,
"totem.interface.mcastaddr") == 0) {
693 if (strcmp(path,
"totem.interface.broadcast") == 0) {
697 if (strcmp(path,
"totem.interface.mcastport") == 0) {
699 if (safe_atoq(value, &val, val_type) != 0) {
705 if (strcmp(path,
"totem.interface.ttl") == 0) {
707 if (safe_atoq(value, &val, val_type) != 0) {
715 if (strcmp(key,
"subsys") == 0) {
716 data->
subsys = strdup(value);
717 if (data->
subsys == NULL) {
718 *error_string =
"Can't alloc memory";
723 kv_item = malloc(
sizeof(*kv_item));
724 if (kv_item == NULL) {
725 *error_string =
"Can't alloc memory";
729 memset(kv_item, 0,
sizeof(*kv_item));
731 kv_item->
key = strdup(key);
732 kv_item->
value = strdup(value);
733 if (kv_item->
key == NULL || kv_item->
value == NULL) {
735 *error_string =
"Can't alloc memory";
739 list_init(&kv_item->
list);
745 if (strcmp(key,
"subsys") == 0) {
746 data->
subsys = strdup(value);
747 if (data->
subsys == NULL) {
748 *error_string =
"Can't alloc memory";
752 }
else if (strcmp(key,
"name") == 0) {
755 *error_string =
"Can't alloc memory";
760 kv_item = malloc(
sizeof(*kv_item));
761 if (kv_item == NULL) {
762 *error_string =
"Can't alloc memory";
766 memset(kv_item, 0,
sizeof(*kv_item));
768 kv_item->
key = strdup(key);
769 kv_item->
value = strdup(value);
770 if (kv_item->
key == NULL || kv_item->
value == NULL) {
772 *error_string =
"Can't alloc memory";
776 list_init(&kv_item->
list);
782 if (strcmp(key,
"uid") == 0) {
783 uid = uid_determine(value);
785 *error_string = error_string_response;
792 }
else if (strcmp(key,
"gid") == 0) {
793 gid = gid_determine(value);
795 *error_string = error_string_response;
803 *error_string =
"uidgid: Only uid and gid are allowed items";
808 if (strcmp(key,
"memberaddr") != 0) {
809 *error_string =
"Only memberaddr is allowed in member section";
814 kv_item = malloc(
sizeof(*kv_item));
815 if (kv_item == NULL) {
816 *error_string =
"Can't alloc memory";
820 memset(kv_item, 0,
sizeof(*kv_item));
822 kv_item->
key = strdup(key);
823 kv_item->
value = strdup(value);
824 if (kv_item->
key == NULL || kv_item->
value == NULL) {
826 *error_string =
"Can't alloc memory";
830 list_init(&kv_item->
list);
838 if ((strcmp(key,
"nodeid") == 0) ||
839 (strcmp(key,
"quorum_votes") == 0)) {
841 if (safe_atoq(value, &val, val_type) != 0) {
849 if (strcmp(key,
"ring0_addr") == 0) {
865 if (strcmp(path,
"totem.interface") == 0) {
872 if (strcmp(path,
"totem") == 0) {
875 if (strcmp(path,
"qb") == 0) {
878 if (strcmp(path,
"logging.logger_subsys") == 0) {
883 if (strcmp(path,
"logging.logging_daemon") == 0) {
889 if (strcmp(path,
"uidgid") == 0) {
892 if (strcmp(path,
"totem.interface.member") == 0) {
895 if (strcmp(path,
"quorum") == 0) {
898 if (strcmp(path,
"quorum.device") == 0) {
901 if (strcmp(path,
"nodelist") == 0) {
905 if (strcmp(path,
"nodelist.node") == 0) {
911 switch (data->
state) {
954 if (data->
ttl > -1) {
969 iter_next = iter->
next;
971 free(kv_item->
value);
986 if (data->
subsys == NULL) {
987 *error_string =
"No subsys key in logger_subsys directive";
1000 iter_next = iter->
next;
1002 free(kv_item->
value);
1017 *error_string =
"No name key in logging_daemon directive";
1026 if (data->
subsys == NULL) {
1033 "logging.logging_daemon.%s.%s",
1039 "logging.logger_subsys.%s.%s",
1044 "logging.logging_daemon.%s.%s.%s",
1051 iter_next = iter->
next;
1053 free(kv_item->
value);
1058 if (data->
subsys == NULL) {
1102 *error_string =
"No ring0_addr specified for node";
1116 min_val = max_val = 0;
1121 assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1123 snprintf(formated_err,
sizeof(formated_err),
1124 "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1125 key, min_val, max_val, value);
1126 *error_string = formated_err;
1131 static int uidgid_config_parser_cb(
const char *path,
1135 const char **error_string,
1148 if (strcmp(path,
"uidgid.uid") == 0) {
1149 uid = uid_determine(value);
1151 *error_string = error_string_response;
1157 }
else if (strcmp(path,
"uidgid.gid") == 0) {
1158 gid = gid_determine(value);
1160 *error_string = error_string_response;
1167 *error_string =
"uidgid: Only uid and gid are allowed items";
1172 if (strcmp(path,
"uidgid") != 0) {
1173 *error_string =
"uidgid: Can't add subsection different than uidgid";
1184 static int read_uidgid_files_into_icmap(
1185 const char **error_string,
1189 const char *dirname;
1191 struct dirent *dirent;
1192 struct dirent *entry;
1193 char filename[PATH_MAX + FILENAME_MAX + 1];
1197 struct stat stat_buf;
1201 dp = opendir (dirname);
1206 len = offsetof(
struct dirent, d_name) + FILENAME_MAX + 1;
1208 entry = malloc(len);
1209 if (entry == NULL) {
1214 for (return_code = readdir_r(dp, entry, &dirent);
1215 dirent != NULL && return_code == 0;
1216 return_code = readdir_r(dp, entry, &dirent)) {
1218 snprintf(filename,
sizeof (filename),
"%s/%s", dirname, dirent->d_name);
1219 res = stat (filename, &stat_buf);
1220 if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1222 fp = fopen (filename,
"r");
1223 if (fp == NULL)
continue;
1227 res = parse_section(fp, key_name, error_string, 0, uidgid_config_parser_cb, config_map, NULL);
1245 static int read_config_file_into_icmap(
1246 const char **error_string,
1250 const char *filename;
1251 char *error_reason = error_string_response;
1256 filename = getenv (
"COROSYNC_MAIN_CONFIG_FILE");
1260 fp = fopen (filename,
"r");
1262 char error_str[100];
1263 const char *error_ptr = qb_strerror_r(errno, error_str,
sizeof(error_str));
1264 snprintf (error_reason,
sizeof(error_string_response),
1265 "Can't read file %s reason = (%s)",
1266 filename, error_ptr);
1267 *error_string = error_reason;
1273 res = parse_section(fp, key_name, error_string, 0, main_config_parser_cb, config_map, &data);
1278 res = read_uidgid_files_into_icmap(error_string, config_map);
1282 snprintf (error_reason,
sizeof(error_string_response),
1283 "Successfully read main configuration file '%s'.", filename);
1284 *error_string = error_reason;
char * logging_daemon_name
struct list_head logger_subsys_items_head
struct list_head member_items_head
int coroparse_configparse(icmap_map_t config_map, const char **error_string)
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
enum main_cp_cb_data_state state
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
#define ICMAP_KEYNAME_MAXLEN
cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
int(* parser_cb_f)(const char *path, char *key, char *value, enum parser_cb_type type, const char **error_string, icmap_map_t config_map, void *user_data)
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
#define list_entry(ptr, type, member)