corosync 3.1.10
coroparse.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006-2022 Red Hat, Inc.
3 *
4 * All rights reserved.
5 *
6 * Author: Patrick Caulfield (pcaulfie@redhat.com)
7 * Jan Friesse (jfriesse@redhat.com)
8 *
9 * This software licensed under BSD license, the text of which follows:
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 *
14 * - Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * - Neither the name of the MontaVista Software, Inc. nor the names of its
20 * contributors may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include <config.h>
37
38#include <sys/types.h>
39#include <sys/uio.h>
40#include <sys/socket.h>
41#include <sys/stat.h>
42#include <sys/un.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <stdlib.h>
48#include <stdio.h>
49#include <errno.h>
50#include <string.h>
51#include <dirent.h>
52#include <libgen.h>
53#include <limits.h>
54#include <stddef.h>
55#include <grp.h>
56#include <pwd.h>
57
58#include <qb/qblist.h>
59#include <qb/qbutil.h>
60#define LOGSYS_UTILS_ONLY 1
61#include <corosync/logsys.h>
62#include <corosync/icmap.h>
63
64#include "main.h"
65#include "util.h"
66
75
96
97typedef int (*parser_cb_f)(const char *path,
98 char *key,
99 char *value,
100 enum main_cp_cb_data_state *state,
101 enum parser_cb_type type,
102 const char **error_string,
103 icmap_map_t config_map,
104 void *user_data);
105
107 char *key;
108 char *value;
109 struct qb_list_head list;
110};
111
135
136static int read_config_file_into_icmap(
137 const char **error_string, icmap_map_t config_map);
138static char error_string_response[512];
139
140static int uid_determine (const char *req_user)
141{
142 int pw_uid = 0;
143 struct passwd passwd;
144 struct passwd* pwdptr = &passwd;
145 struct passwd* temp_pwd_pt;
146 char *pwdbuffer;
147 int pwdlinelen, rc;
148 long int id;
149 char *ep;
150
151 id = strtol(req_user, &ep, 10);
152 if (*req_user != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
153 return (id);
154 }
155
156 pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
157
158 if (pwdlinelen == -1) {
159 pwdlinelen = 256;
160 }
161
162 pwdbuffer = malloc (pwdlinelen);
163
164 while ((rc = getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) == ERANGE) {
165 char *n;
166
167 pwdlinelen *= 2;
168 if (pwdlinelen <= 32678) {
169 n = realloc (pwdbuffer, pwdlinelen);
170 if (n != NULL) {
171 pwdbuffer = n;
172 continue;
173 }
174 }
175 }
176 if (rc != 0) {
177 free (pwdbuffer);
178 sprintf (error_string_response, "getpwnam_r(): %s", strerror(rc));
179 return (-1);
180 }
181 if (temp_pwd_pt == NULL) {
182 free (pwdbuffer);
183 sprintf (error_string_response,
184 "The '%s' user is not found in /etc/passwd, please read the documentation.",
185 req_user);
186 return (-1);
187 }
188 pw_uid = passwd.pw_uid;
189 free (pwdbuffer);
190
191 return pw_uid;
192}
193
194static int gid_determine (const char *req_group)
195{
196 int corosync_gid = 0;
197 struct group group;
198 struct group * grpptr = &group;
199 struct group * temp_grp_pt;
200 char *grpbuffer;
201 int grplinelen, rc;
202 long int id;
203 char *ep;
204
205 id = strtol(req_group, &ep, 10);
206 if (*req_group != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
207 return (id);
208 }
209
210 grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
211
212 if (grplinelen == -1) {
213 grplinelen = 256;
214 }
215
216 grpbuffer = malloc (grplinelen);
217
218 while ((rc = getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) == ERANGE) {
219 char *n;
220
221 grplinelen *= 2;
222 if (grplinelen <= 32678) {
223 n = realloc (grpbuffer, grplinelen);
224 if (n != NULL) {
225 grpbuffer = n;
226 continue;
227 }
228 }
229 }
230 if (rc != 0) {
231 free (grpbuffer);
232 sprintf (error_string_response, "getgrnam_r(): %s", strerror(rc));
233 return (-1);
234 }
235 if (temp_grp_pt == NULL) {
236 free (grpbuffer);
237 sprintf (error_string_response,
238 "The '%s' group is not found in /etc/group, please read the documentation.",
239 req_group);
240 return (-1);
241 }
242 corosync_gid = group.gr_gid;
243 free (grpbuffer);
244
245 return corosync_gid;
246}
247static char *strchr_rs (const char *haystack, int byte)
248{
249 const char *end_address = strchr (haystack, byte);
250 if (end_address) {
251 end_address += 1; /* skip past { or = */
252
253 while (*end_address == ' ' || *end_address == '\t' || (unsigned char)*end_address == 0xA0)
254 end_address++;
255 }
256
257 return ((char *) end_address);
258}
259
260int coroparse_configparse (icmap_map_t config_map, const char **error_string)
261{
262 if (read_config_file_into_icmap(error_string, config_map)) {
263 return -1;
264 }
265
266 return 0;
267}
268
269static char *remove_whitespace(char *string, int remove_colon_and_brace)
270{
271 char *start;
272 char *end;
273
274 start = string;
275 if (*start == '\0')
276 return start;
277
278 while (*start == ' ' || *start == '\t' || (unsigned char)*start == 0xA0)
279 start++;
280
281 end = start+(strlen(start))-1;
282 while ((*end == ' ' || *end == '\t' || (unsigned char)*end == 0xA0 || (remove_colon_and_brace && (*end == ':' || *end == '{'))) && end > start)
283 end--;
284 if (*end != '\0')
285 *(end + 1) = '\0';
286
287 return start;
288}
289
290
291
292static int parse_section(FILE *fp,
293 const char *fname,
294 int *line_no,
295 const char *path,
296 const char **error_string,
297 int depth,
298 enum main_cp_cb_data_state state,
299 parser_cb_f parser_cb,
300 icmap_map_t config_map,
301 void *user_data)
302{
303 char line[512];
304 int i;
305 char *loc;
306 int ignore_line;
307 char new_keyname[ICMAP_KEYNAME_MAXLEN];
308 static char formated_err[384];
309 const char *tmp_error_string;
310
311 if (strcmp(path, "") == 0) {
312 parser_cb("", NULL, NULL, &state, PARSER_CB_START, error_string, config_map, user_data);
313 }
314
315 tmp_error_string = NULL;
316
317 while (fgets (line, sizeof (line), fp)) {
318 (*line_no)++;
319
320 if (strlen(line) > 0) {
321 /*
322 * Check if complete line was read. Use feof to handle files
323 * without ending \n at the end of the file
324 */
325 if ((line[strlen(line) - 1] != '\n') && !feof(fp)) {
326 tmp_error_string = "Line too long";
327 goto parse_error;
328 }
329
330 if (line[strlen(line) - 1] == '\n')
331 line[strlen(line) - 1] = '\0';
332 if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
333 line[strlen(line) - 1] = '\0';
334 }
335 /*
336 * Clear out white space and tabs
337 */
338 for (i = strlen (line) - 1; i > -1; i--) {
339 if (line[i] == '\t' || line[i] == ' ' || (unsigned char)line[i] == 0xA0) {
340 line[i] = '\0';
341 } else {
342 break;
343 }
344 }
345
346 ignore_line = 1;
347 for (i = 0; i < strlen (line); i++) {
348 if (line[i] != '\t' && line[i] != ' ' && (unsigned char)line[i] != 0xA0) {
349 if (line[i] != '#')
350 ignore_line = 0;
351
352 break;
353 }
354 }
355 /*
356 * Clear out comments and empty lines
357 */
358 if (ignore_line) {
359 continue;
360 }
361
362 /* New section ? */
363 if ((loc = strchr_rs (line, '{'))) {
364 char *section;
365 char *after_section;
366 enum main_cp_cb_data_state newstate;
367
368 *(loc-1) = '\0';
369 section = remove_whitespace(line, 1);
370 after_section = remove_whitespace(loc, 0);
371
372 if (strcmp(section, "") == 0) {
373 tmp_error_string = "Missing section name before opening bracket '{'";
374 goto parse_error;
375 }
376
377 if (strcmp(after_section, "") != 0) {
378 tmp_error_string = "Extra characters after opening bracket '{'";
379 goto parse_error;
380 }
381
382 if (strlen(path) + strlen(section) + 1 >= ICMAP_KEYNAME_MAXLEN) {
383 tmp_error_string = "Start of section makes total cmap path too long";
384 goto parse_error;
385 }
386 strcpy(new_keyname, path);
387 if (strcmp(path, "") != 0) {
388 strcat(new_keyname, ".");
389 }
390 strcat(new_keyname, section);
391
392 /* Only use the new state for items further down the stack */
393 newstate = state;
394 if (!parser_cb(new_keyname, NULL, NULL, &newstate, PARSER_CB_SECTION_START,
395 &tmp_error_string, config_map, user_data)) {
396 goto parse_error;
397 }
398
399 if (parse_section(fp, fname, line_no, new_keyname, error_string, depth + 1, newstate,
400 parser_cb, config_map, user_data))
401 return -1;
402
403 continue ;
404 }
405
406 /* New key/value */
407 if ((loc = strchr_rs (line, ':'))) {
408 char *key;
409 char *value;
410
411 *(loc-1) = '\0';
412 key = remove_whitespace(line, 1);
413 value = remove_whitespace(loc, 0);
414
415 if (strlen(key) == 0) {
416 tmp_error_string = "Key name can't be empty";
417 goto parse_error;
418 }
419
420 if (strlen(path) + strlen(key) + 1 >= ICMAP_KEYNAME_MAXLEN) {
421 tmp_error_string = "New key makes total cmap path too long";
422 goto parse_error;
423 }
424 strcpy(new_keyname, path);
425 if (strcmp(path, "") != 0) {
426 strcat(new_keyname, ".");
427 }
428 strcat(new_keyname, key);
429
430 if (!parser_cb(new_keyname, key, value, &state, PARSER_CB_ITEM, &tmp_error_string,
431 config_map, user_data)) {
432 goto parse_error;
433 }
434
435 continue ;
436 }
437
438 if (strchr_rs (line, '}')) {
439 char *trimmed_line;
440 trimmed_line = remove_whitespace(line, 0);
441
442 if (strcmp(trimmed_line, "}") != 0) {
443 tmp_error_string = "Extra characters before or after closing bracket '}'";
444 goto parse_error;
445 }
446
447 if (depth == 0) {
448 tmp_error_string = "Unexpected closing brace";
449
450 goto parse_error;
451 }
452
453 if (!parser_cb(path, NULL, NULL, &state, PARSER_CB_SECTION_END, &tmp_error_string,
454 config_map, user_data)) {
455 goto parse_error;
456 }
457
458 return 0;
459 }
460
461 /*
462 * Line is not opening section, ending section or value -> error
463 */
464 tmp_error_string = "Line is not opening or closing section or key value";
465 goto parse_error;
466 }
467
468 if (strcmp(path, "") != 0) {
469 tmp_error_string = "Missing closing brace";
470 goto parse_error;
471 }
472
473 if (strcmp(path, "") == 0) {
474 parser_cb("", NULL, NULL, &state, PARSER_CB_END, error_string, config_map, user_data);
475 parser_cb("", NULL, NULL, &state, PARSER_CB_CLEANUP, error_string, config_map, user_data);
476 }
477
478 return 0;
479
480parse_error:
481 if (snprintf(formated_err, sizeof(formated_err), "parser error: %s:%u: %s", fname, *line_no,
482 tmp_error_string) >= sizeof(formated_err)) {
483 *error_string = "Can't format parser error message";
484 } else {
485 *error_string = formated_err;
486 }
487
488 parser_cb("", NULL, NULL, &state, PARSER_CB_CLEANUP, error_string, config_map, user_data);
489
490 return -1;
491}
492
493static int safe_atoq_range(icmap_value_types_t value_type, long long int *min_val, long long int *max_val)
494{
495 switch (value_type) {
496 case ICMAP_VALUETYPE_INT8: *min_val = INT8_MIN; *max_val = INT8_MAX; break;
497 case ICMAP_VALUETYPE_UINT8: *min_val = 0; *max_val = UINT8_MAX; break;
498 case ICMAP_VALUETYPE_INT16: *min_val = INT16_MIN; *max_val = INT16_MAX; break;
499 case ICMAP_VALUETYPE_UINT16: *min_val = 0; *max_val = UINT16_MAX; break;
500 case ICMAP_VALUETYPE_INT32: *min_val = INT32_MIN; *max_val = INT32_MAX; break;
501 case ICMAP_VALUETYPE_UINT32: *min_val = 0; *max_val = UINT32_MAX; break;
502 default:
503 return (-1);
504 }
505
506 return (0);
507}
508
509/*
510 * Convert string str to long long int res. Type of result is target_type and currently only
511 * ICMAP_VALUETYPE_[U]INT[8|16|32] is supported.
512 * Return 0 on success, -1 on failure.
513 */
514static int safe_atoq(const char *str, long long int *res, icmap_value_types_t target_type)
515{
516 long long int val;
517 long long int min_val, max_val;
518 char *endptr;
519
520 errno = 0;
521
522 val = strtoll(str, &endptr, 10);
523 if (errno == ERANGE) {
524 return (-1);
525 }
526
527 if (endptr == str) {
528 return (-1);
529 }
530
531 if (*endptr != '\0') {
532 return (-1);
533 }
534
535 if (safe_atoq_range(target_type, &min_val, &max_val) != 0) {
536 return (-1);
537 }
538
539 if (val < min_val || val > max_val) {
540 return (-1);
541 }
542
543 *res = val;
544 return (0);
545}
546
547static int str_to_ull(const char *str, unsigned long long int *res)
548{
549 unsigned long long int val;
550 char *endptr;
551
552 errno = 0;
553
554 val = strtoull(str, &endptr, 10);
555 if (errno == ERANGE) {
556 return (-1);
557 }
558
559 if (endptr == str) {
560 return (-1);
561 }
562
563 if (*endptr != '\0') {
564 return (-1);
565 }
566
567 *res = val;
568 return (0);
569}
570
571static int get_dscp_value(char *str, int *dscp) {
572 struct dscp_name {const char *name; int dscp;} names[] = {
573 {"cs0", 0}, {"cs1", 8}, {"cs2", 16}, {"cs3", 24},
574 {"cs4", 32}, {"cs5", 40}, {"cs6", 48}, {"cs7", 56},
575 {"af11", 10}, {"af12", 12}, {"af13", 14}, {"af21", 18},
576 {"af22", 20}, {"af23", 22}, {"af31", 26}, {"af32", 28},
577 {"af33", 30}, {"af41", 34}, {"af42", 36}, {"af43", 38},
578 {"ef", 46}, {NULL, 0}
579 };
580 struct dscp_name *n;
581 long val;
582 char *end;
583
584 /*
585 * allow dscp symbolical names according to
586 * https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
587 */
588 for (n = names; n->name; n++) {
589 if (strcmp(str, n->name) == 0) {
590 *dscp = n->dscp;
591 return 0;
592 }
593 }
594
595 /* allow dscp as number (decimal, hex, octal) */
596 errno = 0;
597 val = strtol(str, &end, 0);
598 if (errno == 0 && *end == '\0' && val >= 0 && val <= 63) {
599 *dscp = val;
600 return 0;
601 }
602
603 return -1;
604}
605
606static int handle_crypto_model(const char *val, const char **error_string)
607{
608
609 if (util_is_valid_knet_crypto_model(val, NULL, 0,
610 "Invalid crypto model. Should be ", error_string) == 1) {
611 return (0);
612 } else {
613 return (-1);
614 }
615}
616
617static int handle_compress_model(const char *val, const char **error_string)
618{
619
620 if (util_is_valid_knet_compress_model(val, NULL, 0,
621 "Invalid compression model. Should be ", error_string) == 1) {
622 return (0);
623 } else {
624 return (-1);
625 }
626}
627
628static int main_config_parser_cb(const char *path,
629 char *key,
630 char *value,
631 enum main_cp_cb_data_state *state,
632 enum parser_cb_type type,
633 const char **error_string,
634 icmap_map_t config_map,
635 void *user_data)
636{
637 int ii;
638 long long int val;
639 long long int min_val, max_val;
641 unsigned long long int ull;
642 int add_as_string;
643 char key_name[ICMAP_KEYNAME_MAXLEN + 1];
644 static char formated_err[256];
645 struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
646 struct key_value_list_item *kv_item;
647 struct qb_list_head *iter, *tmp_iter;
648 int uid, gid, dscp;
649 cs_error_t cs_err;
650 const char *path_prefix;
651
652 cs_err = CS_OK;
653
654 /*
655 * Formally this check is not needed because length is checked by parse_section
656 */
657 if (strlen(path) >= sizeof(key_name)) {
658 if (snprintf(formated_err, sizeof(formated_err),
659 "Can't store path \"%s\" into key_name", path) >= sizeof(formated_err)) {
660 *error_string = "Can't format path into key_name error message";
661 } else {
662 *error_string = formated_err;
663 }
664 return (0);
665 }
666 /*
667 * Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
668 * are using path, so initialize key_name to valid value
669 */
670 strncpy(key_name, path, sizeof(key_name) - 1);
671
672 switch (type) {
673 case PARSER_CB_START:
674 memset(data, 0, sizeof(struct main_cp_cb_data));
675 qb_list_init(&data->logger_subsys_items_head);
676 qb_list_init(&data->member_items_head);
678 break;
679 case PARSER_CB_END:
680 break;
682 free(data->bindnetaddr);
683 free(data->mcastaddr);
684 free(data->broadcast);
685 free(data->knet_transport);
686
687 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
688 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
689 qb_list_del(&kv_item->list);
690
691 free(kv_item->value);
692 free(kv_item->key);
693 free(kv_item);
694 }
695
696 free(data->subsys);
697 free(data->logging_daemon_name);
698
699 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
700 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
701 qb_list_del(&kv_item->list);
702
703 free(kv_item->value);
704 free(kv_item->key);
705 free(kv_item);
706 }
707 break;
708 case PARSER_CB_ITEM:
709 add_as_string = 1;
710
711 switch (*state) {
713 break;
715 if ((strcmp(path, "pload.count") == 0) ||
716 (strcmp(path, "pload.size") == 0)) {
717 val_type = ICMAP_VALUETYPE_UINT32;
718 if (safe_atoq(value, &val, val_type) != 0) {
719 goto safe_atoq_error;
720 }
721 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
722 goto icmap_set_error;
723 }
724 add_as_string = 0;
725 }
726 break;
728 if ((strcmp(path, "quorum.expected_votes") == 0) ||
729 (strcmp(path, "quorum.votes") == 0) ||
730 (strcmp(path, "quorum.last_man_standing_window") == 0) ||
731 (strcmp(path, "quorum.leaving_timeout") == 0)) {
732 val_type = ICMAP_VALUETYPE_UINT32;
733 if (safe_atoq(value, &val, val_type) != 0) {
734 goto safe_atoq_error;
735 }
736 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
737 goto icmap_set_error;
738 }
739 add_as_string = 0;
740 }
741
742 if ((strcmp(path, "quorum.two_node") == 0) ||
743 (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
744 (strcmp(path, "quorum.allow_downscale") == 0) ||
745 (strcmp(path, "quorum.wait_for_all") == 0) ||
746 (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
747 (strcmp(path, "quorum.last_man_standing") == 0)) {
748 val_type = ICMAP_VALUETYPE_UINT8;
749 if (safe_atoq(value, &val, val_type) != 0) {
750 goto safe_atoq_error;
751 }
752 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
753 goto icmap_set_error;
754 }
755 add_as_string = 0;
756 }
757 break;
759 if ((strcmp(path, "quorum.device.timeout") == 0) ||
760 (strcmp(path, "quorum.device.sync_timeout") == 0) ||
761 (strcmp(path, "quorum.device.votes") == 0)) {
762 val_type = ICMAP_VALUETYPE_UINT32;
763 if (safe_atoq(value, &val, val_type) != 0) {
764 goto safe_atoq_error;
765 }
766 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
767 goto icmap_set_error;
768 }
769 add_as_string = 0;
770 }
771 if ((strcmp(path, "quorum.device.master_wins") == 0)) {
772 val_type = ICMAP_VALUETYPE_UINT8;
773 if (safe_atoq(value, &val, val_type) != 0) {
774 goto safe_atoq_error;
775 }
776 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
777 goto icmap_set_error;
778 }
779 add_as_string = 0;
780 }
781 break;
783 if ((strcmp(path, "totem.version") == 0) ||
784 (strcmp(path, "totem.nodeid") == 0) ||
785 (strcmp(path, "totem.threads") == 0) ||
786 (strcmp(path, "totem.token") == 0) ||
787 (strcmp(path, "totem.token_coefficient") == 0) ||
788 (strcmp(path, "totem.token_retransmit") == 0) ||
789 (strcmp(path, "totem.token_warning") == 0) ||
790 (strcmp(path, "totem.hold") == 0) ||
791 (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
792 (strcmp(path, "totem.join") == 0) ||
793 (strcmp(path, "totem.send_join") == 0) ||
794 (strcmp(path, "totem.consensus") == 0) ||
795 (strcmp(path, "totem.merge") == 0) ||
796 (strcmp(path, "totem.downcheck") == 0) ||
797 (strcmp(path, "totem.fail_recv_const") == 0) ||
798 (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
799 (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
800 (strcmp(path, "totem.max_network_delay") == 0) ||
801 (strcmp(path, "totem.window_size") == 0) ||
802 (strcmp(path, "totem.max_messages") == 0) ||
803 (strcmp(path, "totem.miss_count_const") == 0) ||
804 (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
805 (strcmp(path, "totem.knet_mtu") == 0) ||
806 (strcmp(path, "totem.knet_compression_threshold") == 0) ||
807 (strcmp(path, "totem.netmtu") == 0)) {
808 val_type = ICMAP_VALUETYPE_UINT32;
809 if (safe_atoq(value, &val, val_type) != 0) {
810 goto safe_atoq_error;
811 }
812 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
813 goto icmap_set_error;
814 }
815 add_as_string = 0;
816 }
817 if (strcmp(path, "totem.knet_compression_level") == 0) {
818 val_type = ICMAP_VALUETYPE_INT32;
819 if (safe_atoq(value, &val, val_type) != 0) {
820 goto safe_atoq_error;
821 }
822 if ((cs_err = icmap_set_int32_r(config_map, path, val)) != CS_OK) {
823 goto icmap_set_error;
824 }
825 add_as_string = 0;
826 }
827 if (strcmp(path, "totem.config_version") == 0) {
828 if (str_to_ull(value, &ull) != 0) {
829 goto str_to_ull_error;
830 }
831 if ((cs_err = icmap_set_uint64_r(config_map, path, ull)) != CS_OK) {
832 goto icmap_set_error;
833 }
834 add_as_string = 0;
835 }
836 if (strcmp(path, "totem.ip_version") == 0) {
837 if ((strcmp(value, "ipv4") != 0) &&
838 (strcmp(value, "ipv6") != 0) &&
839 (strcmp(value, "ipv6-4") != 0) &&
840 (strcmp(value, "ipv4-6") != 0)) {
841 *error_string = "Invalid ip_version type";
842
843 return (0);
844 }
845 }
846 if (strcmp(path, "totem.crypto_model") == 0) {
847 if (handle_crypto_model(value, error_string) != 0) {
848 return (0);
849 }
850 }
851
852 if (strcmp(path, "totem.crypto_cipher") == 0) {
853 if ((strcmp(value, "none") != 0) &&
854 (strcmp(value, "aes256") != 0) &&
855 (strcmp(value, "aes192") != 0) &&
856 (strcmp(value, "aes128") != 0)) {
857 *error_string = "Invalid cipher type. "
858 "Should be none, aes256, aes192 or aes128";
859
860 return (0);
861 }
862 }
863 if (strcmp(path, "totem.crypto_hash") == 0) {
864 if ((strcmp(value, "none") != 0) &&
865 (strcmp(value, "md5") != 0) &&
866 (strcmp(value, "sha1") != 0) &&
867 (strcmp(value, "sha256") != 0) &&
868 (strcmp(value, "sha384") != 0) &&
869 (strcmp(value, "sha512") != 0)) {
870 *error_string = "Invalid hash type. "
871 "Should be none, md5, sha1, sha256, sha384 or sha512";
872
873 return (0);
874 }
875 }
876
877 if (strcmp(path, "totem.knet_compression_model") == 0) {
878 if (handle_compress_model(value, error_string) != 0) {
879 return (0);
880 }
881 }
882
883 if (strcmp(path, "totem.ip_dscp") == 0) {
884 if (get_dscp_value(value, &dscp) != 0) {
885 goto str_to_dscp_error;
886 }
887 if ((cs_err = icmap_set_uint8_r(config_map, path, dscp)) != CS_OK) {
888 goto icmap_set_error;
889 }
890 add_as_string = 0;
891 }
892
893 break;
894
896 if (strcmp(path, "system.qb_ipc_type") == 0) {
897 if ((strcmp(value, "native") != 0) &&
898 (strcmp(value, "shm") != 0) &&
899 (strcmp(value, "socket") != 0)) {
900 *error_string = "Invalid system.qb_ipc_type";
901
902 return (0);
903 }
904 }
905 if (strcmp(path, "system.sched_rr") == 0) {
906 if ((strcmp(value, "yes") != 0) &&
907 (strcmp(value, "no") != 0)) {
908 *error_string = "Invalid system.sched_rr value";
909
910 return (0);
911 }
912 }
913 if (strcmp(path, "system.move_to_root_cgroup") == 0) {
914 if ((strcmp(value, "yes") != 0) &&
915 (strcmp(value, "no") != 0) &&
916 (strcmp(value, "auto") != 0)) {
917 *error_string = "Invalid system.move_to_root_cgroup";
918
919 return (0);
920 }
921 }
922 if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
923 if ((strcmp(value, "yes") != 0) &&
924 (strcmp(value, "no") != 0)) {
925 *error_string = "Invalid system.allow_knet_handle_fallback";
926
927 return (0);
928 }
929 }
930 break;
931
933 if (strcmp(path, "totem.interface.linknumber") == 0) {
934 val_type = ICMAP_VALUETYPE_UINT8;
935 if (safe_atoq(value, &val, val_type) != 0) {
936 goto safe_atoq_error;
937 }
938
939 data->linknumber = val;
940 add_as_string = 0;
941 }
942 if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
943 free(data->bindnetaddr);
944 data->bindnetaddr = strdup(value);
945 add_as_string = 0;
946 }
947 if (strcmp(path, "totem.interface.mcastaddr") == 0) {
948 free(data->mcastaddr);
949 data->mcastaddr = strdup(value);
950 add_as_string = 0;
951 }
952 if (strcmp(path, "totem.interface.broadcast") == 0) {
953 free(data->broadcast);
954 data->broadcast = strdup(value);
955 add_as_string = 0;
956 }
957 if (strcmp(path, "totem.interface.mcastport") == 0) {
958 val_type = ICMAP_VALUETYPE_UINT16;
959 if (safe_atoq(value, &val, val_type) != 0) {
960 goto safe_atoq_error;
961 }
962 data->mcastport = val;
963 add_as_string = 0;
964 }
965 if (strcmp(path, "totem.interface.ttl") == 0) {
966 val_type = ICMAP_VALUETYPE_UINT8;
967 if (safe_atoq(value, &val, val_type) != 0) {
968 goto safe_atoq_error;
969 }
970 data->ttl = val;
971 add_as_string = 0;
972 }
973 if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
974 val_type = ICMAP_VALUETYPE_UINT8;
975 if (safe_atoq(value, &val, val_type) != 0) {
976 goto safe_atoq_error;
977 }
978 data->knet_link_priority = val;
979 add_as_string = 0;
980 }
981 if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
982 val_type = ICMAP_VALUETYPE_UINT32;
983 if (safe_atoq(value, &val, val_type) != 0) {
984 goto safe_atoq_error;
985 }
986 data->knet_ping_interval = val;
987 add_as_string = 0;
988 }
989 if (strcmp(path, "totem.interface.knet_ping_timeout") == 0) {
990 val_type = ICMAP_VALUETYPE_UINT32;
991 if (safe_atoq(value, &val, val_type) != 0) {
992 goto safe_atoq_error;
993 }
994 data->knet_ping_timeout = val;
995 add_as_string = 0;
996 }
997 if (strcmp(path, "totem.interface.knet_ping_precision") == 0) {
998 val_type = ICMAP_VALUETYPE_UINT32;
999 if (safe_atoq(value, &val, val_type) != 0) {
1000 goto safe_atoq_error;
1001 }
1002 data->knet_ping_precision = val;
1003 add_as_string = 0;
1004 }
1005 if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
1006 val_type = ICMAP_VALUETYPE_UINT32;
1007 if (safe_atoq(value, &val, val_type) != 0) {
1008 goto safe_atoq_error;
1009 }
1010 data->knet_pong_count = val;
1011 add_as_string = 0;
1012 }
1013 if (strcmp(path, "totem.interface.knet_transport") == 0) {
1014 free(data->knet_transport);
1015 data->knet_transport = strdup(value);
1016 add_as_string = 0;
1017 }
1018 break;
1020 if (strcmp(path, "logging.logger_subsys.subsys") == 0) {
1021 free(data->subsys);
1022 data->subsys = strdup(value);
1023 if (data->subsys == NULL) {
1024 *error_string = "Can't alloc memory";
1025
1026 return (0);
1027 }
1028 } else {
1029 path_prefix = "logging.logger_subsys.";
1030 if (strlen(path) < strlen(path_prefix) ||
1031 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1032 *error_string = "Internal error - incorrect path prefix for logger subsys state";
1033
1034 return (0);
1035 }
1036
1037 kv_item = malloc(sizeof(*kv_item));
1038 if (kv_item == NULL) {
1039 *error_string = "Can't alloc memory";
1040
1041 return (0);
1042 }
1043 memset(kv_item, 0, sizeof(*kv_item));
1044
1045 kv_item->key = strdup(path + strlen(path_prefix));
1046 kv_item->value = strdup(value);
1047 if (kv_item->key == NULL || kv_item->value == NULL) {
1048 free(kv_item->key);
1049 free(kv_item->value);
1050 free(kv_item);
1051 *error_string = "Can't alloc memory";
1052
1053 return (0);
1054 }
1055 qb_list_init(&kv_item->list);
1056 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
1057 }
1058 add_as_string = 0;
1059 break;
1061 if (strcmp(path, "logging.logging_daemon.subsys") == 0) {
1062 free(data->subsys);
1063 data->subsys = strdup(value);
1064 if (data->subsys == NULL) {
1065 *error_string = "Can't alloc memory";
1066
1067 return (0);
1068 }
1069 } else if (strcmp(path, "logging.logging_daemon.name") == 0) {
1070 free(data->logging_daemon_name);
1071 data->logging_daemon_name = strdup(value);
1072 if (data->logging_daemon_name == NULL) {
1073 *error_string = "Can't alloc memory";
1074
1075 return (0);
1076 }
1077 } else {
1078 path_prefix = "logging.logging_daemon.";
1079 if (strlen(path) < strlen(path_prefix) ||
1080 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1081 *error_string = "Internal error - incorrect path prefix for logging daemon state";
1082
1083 return (0);
1084 }
1085
1086 kv_item = malloc(sizeof(*kv_item));
1087 if (kv_item == NULL) {
1088 *error_string = "Can't alloc memory";
1089
1090 return (0);
1091 }
1092 memset(kv_item, 0, sizeof(*kv_item));
1093
1094 kv_item->key = strdup(path + strlen(path_prefix));
1095 kv_item->value = strdup(value);
1096 if (kv_item->key == NULL || kv_item->value == NULL) {
1097 free(kv_item->key);
1098 free(kv_item->value);
1099 free(kv_item);
1100 *error_string = "Can't alloc memory";
1101
1102 return (0);
1103 }
1104 qb_list_init(&kv_item->list);
1105 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
1106 }
1107 add_as_string = 0;
1108 break;
1110 if (strcmp(path, "uidgid.uid") == 0) {
1111 uid = uid_determine(value);
1112 if (uid == -1) {
1113 *error_string = error_string_response;
1114 return (0);
1115 }
1116 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1117 uid);
1118 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1119 goto icmap_set_error;
1120 }
1121 add_as_string = 0;
1122 } else if (strcmp(path, "uidgid.gid") == 0) {
1123 gid = gid_determine(value);
1124 if (gid == -1) {
1125 *error_string = error_string_response;
1126 return (0);
1127 }
1128 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1129 gid);
1130 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1131 goto icmap_set_error;
1132 }
1133 add_as_string = 0;
1134 } else {
1135 *error_string = "uidgid: Only uid and gid are allowed items";
1136 return (0);
1137 }
1138 break;
1140 if (strcmp(path, "totem.interface.member.memberaddr") != 0) {
1141 *error_string = "Only memberaddr is allowed in member section";
1142
1143 return (0);
1144 }
1145
1146 kv_item = malloc(sizeof(*kv_item));
1147 if (kv_item == NULL) {
1148 *error_string = "Can't alloc memory";
1149
1150 return (0);
1151 }
1152 memset(kv_item, 0, sizeof(*kv_item));
1153
1154 kv_item->key = strdup(key);
1155 kv_item->value = strdup(value);
1156 if (kv_item->key == NULL || kv_item->value == NULL) {
1157 free(kv_item->key);
1158 free(kv_item->value);
1159 free(kv_item);
1160 *error_string = "Can't alloc memory";
1161
1162 return (0);
1163 }
1164 qb_list_init(&kv_item->list);
1165 qb_list_add(&kv_item->list, &data->member_items_head);
1166 add_as_string = 0;
1167 break;
1169 break;
1171 path_prefix = "nodelist.node.";
1172 if (strlen(path) < strlen(path_prefix) ||
1173 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1174 *error_string = "Internal error - incorrect path prefix for nodelist node state";
1175
1176 return (0);
1177 }
1178
1179 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number,
1180 path + strlen(path_prefix));
1181 if ((strcmp(path, "nodelist.node.nodeid") == 0) ||
1182 (strcmp(path, "nodelist.node.quorum_votes") == 0)) {
1183 val_type = ICMAP_VALUETYPE_UINT32;
1184 if (safe_atoq(value, &val, val_type) != 0) {
1185 goto safe_atoq_error;
1186 }
1187
1188 if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1189 goto icmap_set_error;
1190 }
1191 add_as_string = 0;
1192 }
1193
1194 if (add_as_string) {
1195 if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1196 goto icmap_set_error;
1197 };
1198 add_as_string = 0;
1199 }
1200 break;
1202 if (strcmp(key, "watchdog_timeout") == 0) {
1203 val_type = ICMAP_VALUETYPE_UINT32;
1204 if (safe_atoq(value, &val, val_type) != 0) {
1205 goto safe_atoq_error;
1206 }
1207 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1208 goto icmap_set_error;
1209 }
1210 add_as_string = 0;
1211 }
1212 break;
1215 if (strcmp(key, "poll_period") == 0) {
1216 if (str_to_ull(value, &ull) != 0) {
1217 goto str_to_ull_error;
1218 }
1219 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1220 goto icmap_set_error;
1221 }
1222 add_as_string = 0;
1223 }
1224 break;
1227 if (strcmp(key, "poll_period") == 0) {
1228 if (str_to_ull(value, &ull) != 0) {
1229 goto str_to_ull_error;
1230 }
1231 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1232 goto icmap_set_error;
1233 }
1234 add_as_string = 0;
1235 }
1236 break;
1237 }
1238
1239 if (add_as_string) {
1240 if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1241 goto icmap_set_error;
1242 }
1243 }
1244 break;
1246 if (strcmp(path, "totem.interface") == 0) {
1248 data->linknumber = 0;
1249 data->mcastport = -1;
1250 data->ttl = -1;
1251 data->knet_link_priority = -1;
1252 data->knet_ping_interval = -1;
1253 data->knet_ping_timeout = -1;
1254 data->knet_ping_precision = -1;
1255 data->knet_pong_count = -1;
1256 data->knet_transport = NULL;
1257 qb_list_init(&data->member_items_head);
1258 };
1259 if (strcmp(path, "totem") == 0) {
1261 };
1262 if (strcmp(path, "system") == 0) {
1264 }
1265 if (strcmp(path, "logging.logger_subsys") == 0) {
1267 qb_list_init(&data->logger_subsys_items_head);
1268 data->subsys = NULL;
1269 }
1270 if (strcmp(path, "logging.logging_daemon") == 0) {
1272 qb_list_init(&data->logger_subsys_items_head);
1273 data->subsys = NULL;
1274 data->logging_daemon_name = NULL;
1275 }
1276 if (strcmp(path, "uidgid") == 0) {
1278 }
1279 if (strcmp(path, "totem.interface.member") == 0) {
1281 }
1282 if (strcmp(path, "quorum") == 0) {
1284 }
1285 if (strcmp(path, "quorum.device") == 0) {
1287 }
1288 if (strcmp(path, "nodelist") == 0) {
1290 data->node_number = 0;
1291 }
1292 if (strcmp(path, "nodelist.node") == 0) {
1294 }
1295 if (strcmp(path, "resources") == 0) {
1297 }
1298 if (strcmp(path, "resources.system") == 0) {
1300 }
1301 if (strcmp(path, "resources.system.memory_used") == 0) {
1303 }
1304 if (strcmp(path, "resources.process") == 0) {
1306 }
1307 if (strcmp(path, "resources.process.memory_used") == 0) {
1309 }
1310
1311 if (*state == MAIN_CP_CB_DATA_STATE_UIDGID && strcmp(path, "uidgid") != 0) {
1312 *error_string = "Subsections are not allowed within uidgid section";
1313
1314 return (0);
1315 };
1316
1317 if (*state == MAIN_CP_CB_DATA_STATE_MEMBER && strcmp(path, "totem.interface.member") != 0) {
1318 *error_string = "Subsections are not allowed within totem.interface.member section";
1319
1320 return (0);
1321 };
1322 break;
1324 switch (*state) {
1326 if (strcmp(path, "totem.interface") != 0) {
1327 /*
1328 * Process only end of totem.interface section, not subsections
1329 */
1330 break;
1331 }
1332
1333 /*
1334 * Create new interface section
1335 */
1336 if (data->bindnetaddr != NULL) {
1337 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1338 data->linknumber);
1339 cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1340
1341 free(data->bindnetaddr);
1342 data->bindnetaddr = NULL;
1343
1344 if (cs_err != CS_OK) {
1345 goto icmap_set_error;
1346 }
1347 }
1348
1349 if (data->mcastaddr != NULL) {
1350 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1351 data->linknumber);
1352 cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1353
1354 free(data->mcastaddr);
1355 data->mcastaddr = NULL;
1356
1357 if (cs_err != CS_OK) {
1358 goto icmap_set_error;
1359 }
1360 }
1361
1362 if (data->broadcast != NULL) {
1363 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1364 data->linknumber);
1365 cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1366
1367 free(data->broadcast);
1368 data->broadcast = NULL;
1369
1370 if (cs_err != CS_OK) {
1371 goto icmap_set_error;
1372 }
1373 }
1374
1375 if (data->mcastport > -1) {
1376 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1377 data->linknumber);
1378 if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1379 data->mcastport)) != CS_OK) {
1380 goto icmap_set_error;
1381 }
1382 }
1383
1384 if (data->ttl > -1) {
1385 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1386 data->linknumber);
1387 if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1388 goto icmap_set_error;
1389 }
1390 }
1391 if (data->knet_link_priority > -1) {
1392 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1393 data->linknumber);
1394 if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1395 data->knet_link_priority)) != CS_OK) {
1396 goto icmap_set_error;
1397 }
1398 }
1399 if (data->knet_ping_interval > -1) {
1400 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1401 data->linknumber);
1402 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1403 data->knet_ping_interval)) != CS_OK) {
1404 goto icmap_set_error;
1405 }
1406 }
1407 if (data->knet_ping_timeout > -1) {
1408 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1409 data->linknumber);
1410 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1411 data->knet_ping_timeout)) != CS_OK) {
1412 goto icmap_set_error;
1413 }
1414 }
1415 if (data->knet_ping_precision > -1) {
1416 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1417 data->linknumber);
1418 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1419 data->knet_ping_precision)) != CS_OK) {
1420 goto icmap_set_error;
1421 }
1422 }
1423 if (data->knet_pong_count > -1) {
1424 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1425 data->linknumber);
1426 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1427 data->knet_pong_count)) != CS_OK) {
1428 goto icmap_set_error;
1429 }
1430 }
1431 if (data->knet_transport) {
1432 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1433 data->linknumber);
1434 cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1435 free(data->knet_transport);
1436 data->knet_transport = NULL;
1437
1438 if (cs_err != CS_OK) {
1439 goto icmap_set_error;
1440 }
1441 }
1442
1443 ii = 0;
1444
1445 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1446 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1447 qb_list_del(&kv_item->list);
1448
1449 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1450 data->linknumber, ii);
1451 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1452
1453 free(kv_item->value);
1454 free(kv_item->key);
1455 free(kv_item);
1456 ii++;
1457
1458 if (cs_err != CS_OK) {
1459 goto icmap_set_error;
1460 }
1461 }
1462
1463 qb_list_init(&data->member_items_head);
1464
1465 break;
1467 if (strcmp(path, "logging.logger_subsys") != 0) {
1468 /*
1469 * Process only end of logging.logger_subsys section, not subsections
1470 */
1471 break;
1472 }
1473
1474 if (data->subsys == NULL) {
1475 *error_string = "No subsys key in logger_subsys directive";
1476
1477 return (0);
1478 }
1479
1480 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1481 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1482 qb_list_del(&kv_item->list);
1483
1484 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1485 data->subsys, kv_item->key);
1486 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1487
1488 free(kv_item->value);
1489 free(kv_item->key);
1490 free(kv_item);
1491
1492 if (cs_err != CS_OK) {
1493 goto icmap_set_error;
1494 }
1495 }
1496
1497 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1498 data->subsys);
1499 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1500
1501 qb_list_init(&data->logger_subsys_items_head);
1502 free(data->subsys);
1503 data->subsys = NULL;
1504
1505 if (cs_err != CS_OK) {
1506 goto icmap_set_error;
1507 }
1508 break;
1510 if (strcmp(path, "logging.logging_daemon") != 0) {
1511 /*
1512 * Process only end of logging.logging_daemon section, not subsections
1513 */
1514 break;
1515 }
1516
1517 if (data->logging_daemon_name == NULL) {
1518 *error_string = "No name key in logging_daemon directive";
1519
1520 return (0);
1521 }
1522
1523 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1524 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1525 qb_list_del(&kv_item->list);
1526
1527 if (data->subsys == NULL) {
1528 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1529 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1530 "logging.%s",
1531 kv_item->key);
1532 } else {
1533 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1534 "logging.logging_daemon.%s.%s",
1535 data->logging_daemon_name, kv_item->key);
1536 }
1537 } else {
1538 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1539 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1540 "logging.logger_subsys.%s.%s",
1541 data->subsys,
1542 kv_item->key);
1543 } else {
1544 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1545 "logging.logging_daemon.%s.%s.%s",
1546 data->logging_daemon_name, data->subsys,
1547 kv_item->key);
1548 }
1549 }
1550 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1551
1552 free(kv_item->value);
1553 free(kv_item->key);
1554 free(kv_item);
1555
1556 if (cs_err != CS_OK) {
1557 goto icmap_set_error;
1558 }
1559 }
1560
1561 if (data->subsys == NULL) {
1562 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1563 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1564 data->logging_daemon_name);
1565 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1566 }
1567 } else {
1568 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1569 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1570 data->subsys);
1571 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1572
1573 } else {
1574 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1575 data->logging_daemon_name, data->subsys);
1576 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1577
1578 if (cs_err != CS_OK) {
1579 goto icmap_set_error;
1580 }
1581 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1582 data->logging_daemon_name, data->subsys);
1583 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1584 }
1585 }
1586
1587 qb_list_init(&data->logger_subsys_items_head);
1588 free(data->subsys);
1589 data->subsys = NULL;
1590 free(data->logging_daemon_name);
1591 data->logging_daemon_name = NULL;
1592
1593 if (cs_err != CS_OK) {
1594 goto icmap_set_error;
1595 }
1596 break;
1598 if (strcmp(path, "nodelist.node") != 0) {
1599 /*
1600 * Process only end of nodelist.node section, not subsections
1601 */
1602 break;
1603 }
1604
1605 data->node_number++;
1606 break;
1621 break;
1622 }
1623 break;
1624 }
1625
1626 return (1);
1627
1628safe_atoq_error:
1629 /*
1630 * For integers supported by safe_atoq display range
1631 */
1632 min_val = max_val = 0;
1633 /*
1634 * This is really assert, because developer ether doesn't set val_type correctly or
1635 * we've got here after some nasty memory overwrite
1636 */
1637 assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1638
1639 if (snprintf(formated_err, sizeof(formated_err),
1640 "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1641 key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1642 *error_string = "Can't format parser error message";
1643 } else {
1644 *error_string = formated_err;
1645 }
1646
1647 return (0);
1648
1649str_to_ull_error:
1650 /*
1651 * For integers not supported by safe_atoq (64-bit int)
1652 */
1653 if (snprintf(formated_err, sizeof(formated_err),
1654 "Value of key \"%s\" is expected to be unsigned integer, but \"%s\" was given",
1655 key_name, value) >= sizeof(formated_err)) {
1656 *error_string = "Can't format parser error message";
1657 } else {
1658 *error_string = formated_err;
1659 }
1660
1661 return (0);
1662
1663str_to_dscp_error:
1664 if (snprintf(formated_err, sizeof(formated_err),
1665 "Value of key \"%s\" is expected to be number (0..63) or symbolical dscp value, "
1666 "but \"%s\" was given", key_name, value) >= sizeof(formated_err)) {
1667 *error_string = "Can't format parser error message";
1668 } else {
1669 *error_string = formated_err;
1670 }
1671
1672 return (0);
1673
1674icmap_set_error:
1675 if (snprintf(formated_err, sizeof(formated_err),
1676 "Can't store key \"%s\" into icmap, returned error is %s",
1677 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1678 *error_string = "Can't format parser error message";
1679 } else {
1680 *error_string = formated_err;
1681 }
1682
1683 return (0);
1684}
1685
1686static int uidgid_config_parser_cb(const char *path,
1687 char *key,
1688 char *value,
1689 enum main_cp_cb_data_state *state,
1690 enum parser_cb_type type,
1691 const char **error_string,
1692 icmap_map_t config_map,
1693 void *user_data)
1694{
1695 char key_name[ICMAP_KEYNAME_MAXLEN];
1696 int uid, gid;
1697 static char formated_err[256];
1698 cs_error_t cs_err;
1699
1700 switch (type) {
1701 case PARSER_CB_START:
1702 break;
1703 case PARSER_CB_END:
1704 break;
1705 case PARSER_CB_CLEANUP:
1706 break;
1707 case PARSER_CB_ITEM:
1708 if (strcmp(path, "uidgid.uid") == 0) {
1709 uid = uid_determine(value);
1710 if (uid == -1) {
1711 *error_string = error_string_response;
1712 return (0);
1713 }
1714 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1715 uid);
1716 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1717 goto icmap_set_error;
1718 }
1719 } else if (strcmp(path, "uidgid.gid") == 0) {
1720 gid = gid_determine(value);
1721 if (gid == -1) {
1722 *error_string = error_string_response;
1723 return (0);
1724 }
1725 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1726 gid);
1727 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1728 goto icmap_set_error;
1729 }
1730 } else {
1731 *error_string = "uidgid: Only uid and gid are allowed items";
1732 return (0);
1733 }
1734 break;
1736 if (strcmp(path, "uidgid") != 0) {
1737 *error_string = "uidgid: Can't add subsection different than uidgid";
1738 return (0);
1739 };
1740 break;
1742 break;
1743 }
1744
1745 return (1);
1746
1747icmap_set_error:
1748 if (snprintf(formated_err, sizeof(formated_err),
1749 "Can't store key \"%s\" into icmap, returned error is %s",
1750 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1751 *error_string = "Can't format parser error message";
1752 } else {
1753 *error_string = formated_err;
1754 }
1755
1756 return (0);
1757}
1758
1759static int read_uidgid_files_into_icmap(
1760 const char **error_string,
1761 icmap_map_t config_map)
1762{
1763 FILE *fp;
1764 char *dirname_res;
1765 DIR *dp;
1766 struct dirent *dirent;
1767 char filename[PATH_MAX + FILENAME_MAX + 1];
1768 char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1769 int res = 0;
1770 struct stat stat_buf;
1772 char key_name[ICMAP_KEYNAME_MAXLEN];
1773 int line_no;
1774
1775 /*
1776 * Build uidgid directory based on corosync.conf file location
1777 */
1778 res = snprintf(filename, sizeof(filename), "%s",
1780 if (res >= sizeof(filename)) {
1781 *error_string = "uidgid.d path too long";
1782
1783 return (-1);
1784 }
1785
1786 dirname_res = dirname(filename);
1787
1788 res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1789 dirname_res, "uidgid.d");
1790 if (res >= sizeof(uidgid_dirname)) {
1791 *error_string = "uidgid.d path too long";
1792
1793 return (-1);
1794 }
1795
1796 dp = opendir (uidgid_dirname);
1797
1798 if (dp == NULL)
1799 return 0;
1800
1801 for (dirent = readdir(dp);
1802 dirent != NULL;
1803 dirent = readdir(dp)) {
1804
1805 res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1806 if (res >= sizeof(filename)) {
1807 res = -1;
1808 *error_string = "uidgid.d dirname path too long";
1809
1810 goto error_exit;
1811 }
1812 // coverity[TOCTOU:SUPPRESS] not really problem
1813 res = stat (filename, &stat_buf);
1814 if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1815
1816 fp = fopen (filename, "r");
1817 if (fp == NULL) continue;
1818
1819 key_name[0] = 0;
1820
1821 line_no = 0;
1822 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1823 uidgid_config_parser_cb, config_map, NULL);
1824
1825 fclose (fp);
1826
1827 if (res != 0) {
1828 goto error_exit;
1829 }
1830 }
1831 }
1832
1833error_exit:
1834 closedir(dp);
1835
1836 return res;
1837}
1838
1839/* Read config file and load into icmap */
1840static int read_config_file_into_icmap(
1841 const char **error_string,
1842 icmap_map_t config_map)
1843{
1844 FILE *fp;
1845 const char *filename;
1846 char *error_reason = error_string_response;
1847 int res;
1848 char key_name[ICMAP_KEYNAME_MAXLEN];
1849 struct main_cp_cb_data data;
1851 int line_no;
1852
1853 filename = corosync_get_config_file();
1854
1855 fp = fopen (filename, "r");
1856 if (fp == NULL) {
1857 char error_str[100];
1858 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1859 snprintf (error_reason, sizeof(error_string_response),
1860 "Can't read file %s: %s",
1861 filename, error_ptr);
1862 *error_string = error_reason;
1863 return -1;
1864 }
1865
1866 key_name[0] = 0;
1867
1868 line_no = 0;
1869 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1870 main_config_parser_cb, config_map, &data);
1871
1872 fclose(fp);
1873
1874 if (res == 0) {
1875 res = read_uidgid_files_into_icmap(error_string, config_map);
1876 }
1877
1878 if (res == 0) {
1879 snprintf (error_reason, sizeof(error_string_response),
1880 "Successfully read main configuration file '%s'.", filename);
1881 *error_string = error_reason;
1882 }
1883
1884 return res;
1885}
int(* parser_cb_f)(const char *path, char *key, char *value, enum main_cp_cb_data_state *state, enum parser_cb_type type, const char **error_string, icmap_map_t config_map, void *user_data)
Definition coroparse.c:97
main_cp_cb_data_state
Definition coroparse.c:76
@ MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON
Definition coroparse.c:82
@ MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED
Definition coroparse.c:94
@ MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED
Definition coroparse.c:93
@ MAIN_CP_CB_DATA_STATE_MEMBER
Definition coroparse.c:83
@ MAIN_CP_CB_DATA_STATE_UIDGID
Definition coroparse.c:81
@ MAIN_CP_CB_DATA_STATE_INTERFACE
Definition coroparse.c:79
@ MAIN_CP_CB_DATA_STATE_NORMAL
Definition coroparse.c:77
@ MAIN_CP_CB_DATA_STATE_PLOAD
Definition coroparse.c:88
@ MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS
Definition coroparse.c:80
@ MAIN_CP_CB_DATA_STATE_TOTEM
Definition coroparse.c:78
@ MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS
Definition coroparse.c:92
@ MAIN_CP_CB_DATA_STATE_SYSTEM
Definition coroparse.c:89
@ MAIN_CP_CB_DATA_STATE_QUORUM
Definition coroparse.c:84
@ MAIN_CP_CB_DATA_STATE_QDEVICE
Definition coroparse.c:85
@ MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM
Definition coroparse.c:91
@ MAIN_CP_CB_DATA_STATE_NODELIST_NODE
Definition coroparse.c:87
@ MAIN_CP_CB_DATA_STATE_RESOURCES
Definition coroparse.c:90
@ MAIN_CP_CB_DATA_STATE_NODELIST
Definition coroparse.c:86
int coroparse_configparse(icmap_map_t config_map, const char **error_string)
Definition coroparse.c:260
parser_cb_type
Definition coroparse.c:67
@ PARSER_CB_START
Definition coroparse.c:68
@ PARSER_CB_SECTION_START
Definition coroparse.c:70
@ PARSER_CB_ITEM
Definition coroparse.c:72
@ PARSER_CB_CLEANUP
Definition coroparse.c:73
@ PARSER_CB_SECTION_END
Definition coroparse.c:71
@ PARSER_CB_END
Definition coroparse.c:69
const char * cs_strerror(cs_error_t err)
cs_strerror
cs_error_t
The cs_error_t enum.
Definition corotypes.h:98
@ CS_OK
Definition corotypes.h:99
uint32_t value
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
Definition icmap.c:519
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
Definition icmap.c:531
struct icmap_map * icmap_map_t
icmap type.
Definition icmap.h:118
icmap_value_types_t
Possible types of value.
Definition icmap.h:58
@ ICMAP_VALUETYPE_BINARY
Definition icmap.h:70
@ ICMAP_VALUETYPE_UINT8
Definition icmap.h:60
@ ICMAP_VALUETYPE_INT8
Definition icmap.h:59
@ ICMAP_VALUETYPE_INT16
Definition icmap.h:61
@ ICMAP_VALUETYPE_UINT32
Definition icmap.h:64
@ ICMAP_VALUETYPE_UINT16
Definition icmap.h:62
@ ICMAP_VALUETYPE_INT32
Definition icmap.h:63
cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
Definition icmap.c:507
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
Definition icmap.c:543
cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
Definition icmap.c:525
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
Definition icmap.c:561
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
Definition icmap.h:48
const char * corosync_get_config_file(void)
Definition main.c:212
void * user_data
Definition sam.c:127
struct qb_list_head list
Definition coroparse.c:109
int knet_ping_precision
Definition coroparse.c:122
unsigned int knet_mtu
Definition coroparse.c:125
int knet_pmtud_interval
Definition coroparse.c:124
char * bindnetaddr
Definition coroparse.c:114
struct qb_list_head logger_subsys_items_head
Definition coroparse.c:128
char * knet_transport
Definition coroparse.c:126
char * logging_daemon_name
Definition coroparse.c:130
struct qb_list_head member_items_head
Definition coroparse.c:131
char type
Definition totem.h:2
int util_is_valid_knet_crypto_model(const char *val, const char **list_str, int machine_parseable_str, const char *error_string_prefix, const char **error_string)
Definition util.c:225
int util_is_valid_knet_compress_model(const char *val, const char **list_str, int machine_parseable_str, const char *error_string_prefix, const char **error_string)
Definition util.c:291