corosync
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_crypto_cipher(const char *val, const char **error_string)
618{
619
620 if (util_is_valid_knet_crypto_cipher(val, NULL, 0,
621 "Invalid cipher type. Should be ", error_string) == 1) {
622 return (0);
623 } else {
624 return (-1);
625 }
626}
627
628static int handle_crypto_hash(const char *val, const char **error_string)
629{
630
631 if (util_is_valid_knet_crypto_hash(val, NULL, 0,
632 "Invalid hash type. Should be ", error_string) == 1) {
633 return (0);
634 } else {
635 return (-1);
636 }
637}
638
639static int handle_compress_model(const char *val, const char **error_string)
640{
641
642 if (util_is_valid_knet_compress_model(val, NULL, 0,
643 "Invalid compression model. Should be ", error_string) == 1) {
644 return (0);
645 } else {
646 return (-1);
647 }
648}
649
650static int main_config_parser_cb(const char *path,
651 char *key,
652 char *value,
653 enum main_cp_cb_data_state *state,
654 enum parser_cb_type type,
655 const char **error_string,
656 icmap_map_t config_map,
657 void *user_data)
658{
659 int ii;
660 long long int val;
661 long long int min_val, max_val;
663 unsigned long long int ull;
664 int add_as_string;
665 char key_name[ICMAP_KEYNAME_MAXLEN + 1];
666 static char formated_err[256];
667 struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
668 struct key_value_list_item *kv_item;
669 struct qb_list_head *iter, *tmp_iter;
670 int uid, gid, dscp;
671 cs_error_t cs_err;
672 const char *path_prefix;
673
674 cs_err = CS_OK;
675
676 /*
677 * Formally this check is not needed because length is checked by parse_section
678 */
679 if (strlen(path) >= sizeof(key_name)) {
680 *error_string = "main_config_parser_cb path is longer than key_name";
681
682 return (0);
683 }
684 /*
685 * Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
686 * are using path, so initialize key_name to valid value
687 */
688 strncpy(key_name, path, sizeof(key_name) - 1);
689
690 switch (type) {
691 case PARSER_CB_START:
692 memset(data, 0, sizeof(struct main_cp_cb_data));
693 qb_list_init(&data->logger_subsys_items_head);
694 qb_list_init(&data->member_items_head);
696 break;
697 case PARSER_CB_END:
698 break;
700 free(data->bindnetaddr);
701 free(data->mcastaddr);
702 free(data->broadcast);
703 free(data->knet_transport);
704
705 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
706 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
707 qb_list_del(&kv_item->list);
708
709 free(kv_item->value);
710 free(kv_item->key);
711 free(kv_item);
712 }
713
714 free(data->subsys);
715 free(data->logging_daemon_name);
716
717 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
718 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
719 qb_list_del(&kv_item->list);
720
721 free(kv_item->value);
722 free(kv_item->key);
723 free(kv_item);
724 }
725 break;
726 case PARSER_CB_ITEM:
727 add_as_string = 1;
728
729 switch (*state) {
731 break;
733 if ((strcmp(path, "pload.count") == 0) ||
734 (strcmp(path, "pload.size") == 0)) {
735 val_type = ICMAP_VALUETYPE_UINT32;
736 if (safe_atoq(value, &val, val_type) != 0) {
737 goto safe_atoq_error;
738 }
739 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
740 goto icmap_set_error;
741 }
742 add_as_string = 0;
743 }
744 break;
746 if ((strcmp(path, "quorum.expected_votes") == 0) ||
747 (strcmp(path, "quorum.votes") == 0) ||
748 (strcmp(path, "quorum.last_man_standing_window") == 0) ||
749 (strcmp(path, "quorum.leaving_timeout") == 0)) {
750 val_type = ICMAP_VALUETYPE_UINT32;
751 if (safe_atoq(value, &val, val_type) != 0) {
752 goto safe_atoq_error;
753 }
754 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
755 goto icmap_set_error;
756 }
757 add_as_string = 0;
758 }
759
760 if ((strcmp(path, "quorum.two_node") == 0) ||
761 (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
762 (strcmp(path, "quorum.allow_downscale") == 0) ||
763 (strcmp(path, "quorum.wait_for_all") == 0) ||
764 (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
765 (strcmp(path, "quorum.last_man_standing") == 0)) {
766 val_type = ICMAP_VALUETYPE_UINT8;
767 if (safe_atoq(value, &val, val_type) != 0) {
768 goto safe_atoq_error;
769 }
770 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
771 goto icmap_set_error;
772 }
773 add_as_string = 0;
774 }
775 break;
777 if ((strcmp(path, "quorum.device.timeout") == 0) ||
778 (strcmp(path, "quorum.device.sync_timeout") == 0) ||
779 (strcmp(path, "quorum.device.votes") == 0)) {
780 val_type = ICMAP_VALUETYPE_UINT32;
781 if (safe_atoq(value, &val, val_type) != 0) {
782 goto safe_atoq_error;
783 }
784 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
785 goto icmap_set_error;
786 }
787 add_as_string = 0;
788 }
789 if ((strcmp(path, "quorum.device.master_wins") == 0)) {
790 val_type = ICMAP_VALUETYPE_UINT8;
791 if (safe_atoq(value, &val, val_type) != 0) {
792 goto safe_atoq_error;
793 }
794 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
795 goto icmap_set_error;
796 }
797 add_as_string = 0;
798 }
799 break;
801 if ((strcmp(path, "totem.version") == 0) ||
802 (strcmp(path, "totem.nodeid") == 0) ||
803 (strcmp(path, "totem.threads") == 0) ||
804 (strcmp(path, "totem.token") == 0) ||
805 (strcmp(path, "totem.token_coefficient") == 0) ||
806 (strcmp(path, "totem.token_retransmit") == 0) ||
807 (strcmp(path, "totem.token_warning") == 0) ||
808 (strcmp(path, "totem.hold") == 0) ||
809 (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
810 (strcmp(path, "totem.join") == 0) ||
811 (strcmp(path, "totem.send_join") == 0) ||
812 (strcmp(path, "totem.consensus") == 0) ||
813 (strcmp(path, "totem.merge") == 0) ||
814 (strcmp(path, "totem.downcheck") == 0) ||
815 (strcmp(path, "totem.fail_recv_const") == 0) ||
816 (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
817 (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
818 (strcmp(path, "totem.max_network_delay") == 0) ||
819 (strcmp(path, "totem.window_size") == 0) ||
820 (strcmp(path, "totem.max_messages") == 0) ||
821 (strcmp(path, "totem.miss_count_const") == 0) ||
822 (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
823 (strcmp(path, "totem.knet_mtu") == 0) ||
824 (strcmp(path, "totem.knet_compression_threshold") == 0) ||
825 (strcmp(path, "totem.netmtu") == 0)) {
826 val_type = ICMAP_VALUETYPE_UINT32;
827 if (safe_atoq(value, &val, val_type) != 0) {
828 goto safe_atoq_error;
829 }
830 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
831 goto icmap_set_error;
832 }
833 add_as_string = 0;
834 }
835 if (strcmp(path, "totem.knet_compression_level") == 0) {
836 val_type = ICMAP_VALUETYPE_INT32;
837 if (safe_atoq(value, &val, val_type) != 0) {
838 goto safe_atoq_error;
839 }
840 if ((cs_err = icmap_set_int32_r(config_map, path, val)) != CS_OK) {
841 goto icmap_set_error;
842 }
843 add_as_string = 0;
844 }
845 if (strcmp(path, "totem.config_version") == 0) {
846 if (str_to_ull(value, &ull) != 0) {
847 goto str_to_ull_error;
848 }
849 if ((cs_err = icmap_set_uint64_r(config_map, path, ull)) != CS_OK) {
850 goto icmap_set_error;
851 }
852 add_as_string = 0;
853 }
854 if (strcmp(path, "totem.ip_version") == 0) {
855 if ((strcmp(value, "ipv4") != 0) &&
856 (strcmp(value, "ipv6") != 0) &&
857 (strcmp(value, "ipv6-4") != 0) &&
858 (strcmp(value, "ipv4-6") != 0)) {
859 *error_string = "Invalid ip_version type";
860
861 return (0);
862 }
863 }
864 if (strcmp(path, "totem.crypto_model") == 0) {
865 if (handle_crypto_model(value, error_string) != 0) {
866 return (0);
867 }
868 }
869
870 if (strcmp(path, "totem.crypto_cipher") == 0) {
871 if (handle_crypto_cipher(value, error_string) != 0) {
872 return (0);
873 }
874 }
875 if (strcmp(path, "totem.crypto_hash") == 0) {
876 if (handle_crypto_hash(value, error_string) != 0) {
877 return (0);
878 }
879 }
880
881 if (strcmp(path, "totem.knet_compression_model") == 0) {
882 if (handle_compress_model(value, error_string) != 0) {
883 return (0);
884 }
885 }
886
887 if (strcmp(path, "totem.ip_dscp") == 0) {
888 if (get_dscp_value(value, &dscp) != 0) {
889 goto str_to_dscp_error;
890 }
891 if ((cs_err = icmap_set_uint8_r(config_map, path, dscp)) != CS_OK) {
892 goto icmap_set_error;
893 }
894 add_as_string = 0;
895 }
896
897 break;
898
900 if (strcmp(path, "system.qb_ipc_type") == 0) {
901 if ((strcmp(value, "native") != 0) &&
902 (strcmp(value, "shm") != 0) &&
903 (strcmp(value, "socket") != 0)) {
904 *error_string = "Invalid system.qb_ipc_type";
905
906 return (0);
907 }
908 }
909 if (strcmp(path, "system.sched_rr") == 0) {
910 if ((strcmp(value, "yes") != 0) &&
911 (strcmp(value, "no") != 0)) {
912 *error_string = "Invalid system.sched_rr value";
913
914 return (0);
915 }
916 }
917 if (strcmp(path, "system.move_to_root_cgroup") == 0) {
918 if ((strcmp(value, "yes") != 0) &&
919 (strcmp(value, "no") != 0) &&
920 (strcmp(value, "auto") != 0)) {
921 *error_string = "Invalid system.move_to_root_cgroup";
922
923 return (0);
924 }
925 }
926 if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
927 if ((strcmp(value, "yes") != 0) &&
928 (strcmp(value, "no") != 0)) {
929 *error_string = "Invalid system.allow_knet_handle_fallback";
930
931 return (0);
932 }
933 }
934 break;
935
937 if (strcmp(path, "totem.interface.linknumber") == 0) {
938 val_type = ICMAP_VALUETYPE_UINT8;
939 if (safe_atoq(value, &val, val_type) != 0) {
940 goto safe_atoq_error;
941 }
942
943 data->linknumber = val;
944 add_as_string = 0;
945 }
946 if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
947 free(data->bindnetaddr);
948 data->bindnetaddr = strdup(value);
949 add_as_string = 0;
950 }
951 if (strcmp(path, "totem.interface.mcastaddr") == 0) {
952 free(data->mcastaddr);
953 data->mcastaddr = strdup(value);
954 add_as_string = 0;
955 }
956 if (strcmp(path, "totem.interface.broadcast") == 0) {
957 free(data->broadcast);
958 data->broadcast = strdup(value);
959 add_as_string = 0;
960 }
961 if (strcmp(path, "totem.interface.mcastport") == 0) {
962 val_type = ICMAP_VALUETYPE_UINT16;
963 if (safe_atoq(value, &val, val_type) != 0) {
964 goto safe_atoq_error;
965 }
966 data->mcastport = val;
967 add_as_string = 0;
968 }
969 if (strcmp(path, "totem.interface.ttl") == 0) {
970 val_type = ICMAP_VALUETYPE_UINT8;
971 if (safe_atoq(value, &val, val_type) != 0) {
972 goto safe_atoq_error;
973 }
974 data->ttl = val;
975 add_as_string = 0;
976 }
977 if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
978 val_type = ICMAP_VALUETYPE_UINT8;
979 if (safe_atoq(value, &val, val_type) != 0) {
980 goto safe_atoq_error;
981 }
982 data->knet_link_priority = val;
983 add_as_string = 0;
984 }
985 if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
986 val_type = ICMAP_VALUETYPE_UINT32;
987 if (safe_atoq(value, &val, val_type) != 0) {
988 goto safe_atoq_error;
989 }
990 data->knet_ping_interval = val;
991 add_as_string = 0;
992 }
993 if (strcmp(path, "totem.interface.knet_ping_timeout") == 0) {
994 val_type = ICMAP_VALUETYPE_UINT32;
995 if (safe_atoq(value, &val, val_type) != 0) {
996 goto safe_atoq_error;
997 }
998 data->knet_ping_timeout = val;
999 add_as_string = 0;
1000 }
1001 if (strcmp(path, "totem.interface.knet_ping_precision") == 0) {
1002 val_type = ICMAP_VALUETYPE_UINT32;
1003 if (safe_atoq(value, &val, val_type) != 0) {
1004 goto safe_atoq_error;
1005 }
1006 data->knet_ping_precision = val;
1007 add_as_string = 0;
1008 }
1009 if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
1010 val_type = ICMAP_VALUETYPE_UINT32;
1011 if (safe_atoq(value, &val, val_type) != 0) {
1012 goto safe_atoq_error;
1013 }
1014 data->knet_pong_count = val;
1015 add_as_string = 0;
1016 }
1017 if (strcmp(path, "totem.interface.knet_transport") == 0) {
1018 free(data->knet_transport);
1019 data->knet_transport = strdup(value);
1020 add_as_string = 0;
1021 }
1022 break;
1024 if (strcmp(path, "logging.logger_subsys.subsys") == 0) {
1025 free(data->subsys);
1026 data->subsys = strdup(value);
1027 if (data->subsys == NULL) {
1028 *error_string = "Can't alloc memory";
1029
1030 return (0);
1031 }
1032 } else {
1033 path_prefix = "logging.logger_subsys.";
1034 if (strlen(path) < strlen(path_prefix) ||
1035 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1036 *error_string = "Internal error - incorrect path prefix for logger subsys state";
1037
1038 return (0);
1039 }
1040
1041 kv_item = malloc(sizeof(*kv_item));
1042 if (kv_item == NULL) {
1043 *error_string = "Can't alloc memory";
1044
1045 return (0);
1046 }
1047 memset(kv_item, 0, sizeof(*kv_item));
1048
1049 kv_item->key = strdup(path + strlen(path_prefix));
1050 kv_item->value = strdup(value);
1051 if (kv_item->key == NULL || kv_item->value == NULL) {
1052 free(kv_item->key);
1053 free(kv_item->value);
1054 free(kv_item);
1055 *error_string = "Can't alloc memory";
1056
1057 return (0);
1058 }
1059 qb_list_init(&kv_item->list);
1060 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
1061 }
1062 add_as_string = 0;
1063 break;
1065 if (strcmp(path, "logging.logging_daemon.subsys") == 0) {
1066 free(data->subsys);
1067 data->subsys = strdup(value);
1068 if (data->subsys == NULL) {
1069 *error_string = "Can't alloc memory";
1070
1071 return (0);
1072 }
1073 } else if (strcmp(path, "logging.logging_daemon.name") == 0) {
1074 free(data->logging_daemon_name);
1075 data->logging_daemon_name = strdup(value);
1076 if (data->logging_daemon_name == NULL) {
1077 *error_string = "Can't alloc memory";
1078
1079 return (0);
1080 }
1081 } else {
1082 path_prefix = "logging.logging_daemon.";
1083 if (strlen(path) < strlen(path_prefix) ||
1084 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1085 *error_string = "Internal error - incorrect path prefix for logging daemon state";
1086
1087 return (0);
1088 }
1089
1090 kv_item = malloc(sizeof(*kv_item));
1091 if (kv_item == NULL) {
1092 *error_string = "Can't alloc memory";
1093
1094 return (0);
1095 }
1096 memset(kv_item, 0, sizeof(*kv_item));
1097
1098 kv_item->key = strdup(path + strlen(path_prefix));
1099 kv_item->value = strdup(value);
1100 if (kv_item->key == NULL || kv_item->value == NULL) {
1101 free(kv_item->key);
1102 free(kv_item->value);
1103 free(kv_item);
1104 *error_string = "Can't alloc memory";
1105
1106 return (0);
1107 }
1108 qb_list_init(&kv_item->list);
1109 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
1110 }
1111 add_as_string = 0;
1112 break;
1114 if (strcmp(path, "uidgid.uid") == 0) {
1115 uid = uid_determine(value);
1116 if (uid == -1) {
1117 *error_string = error_string_response;
1118 return (0);
1119 }
1120 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1121 uid);
1122 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1123 goto icmap_set_error;
1124 }
1125 add_as_string = 0;
1126 } else if (strcmp(path, "uidgid.gid") == 0) {
1127 gid = gid_determine(value);
1128 if (gid == -1) {
1129 *error_string = error_string_response;
1130 return (0);
1131 }
1132 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1133 gid);
1134 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1135 goto icmap_set_error;
1136 }
1137 add_as_string = 0;
1138 } else {
1139 *error_string = "uidgid: Only uid and gid are allowed items";
1140 return (0);
1141 }
1142 break;
1144 if (strcmp(path, "totem.interface.member.memberaddr") != 0) {
1145 *error_string = "Only memberaddr is allowed in member section";
1146
1147 return (0);
1148 }
1149
1150 kv_item = malloc(sizeof(*kv_item));
1151 if (kv_item == NULL) {
1152 *error_string = "Can't alloc memory";
1153
1154 return (0);
1155 }
1156 memset(kv_item, 0, sizeof(*kv_item));
1157
1158 kv_item->key = strdup(key);
1159 kv_item->value = strdup(value);
1160 if (kv_item->key == NULL || kv_item->value == NULL) {
1161 free(kv_item->key);
1162 free(kv_item->value);
1163 free(kv_item);
1164 *error_string = "Can't alloc memory";
1165
1166 return (0);
1167 }
1168 qb_list_init(&kv_item->list);
1169 qb_list_add(&kv_item->list, &data->member_items_head);
1170 add_as_string = 0;
1171 break;
1173 break;
1175 path_prefix = "nodelist.node.";
1176 if (strlen(path) < strlen(path_prefix) ||
1177 strncmp(path, path_prefix, strlen(path_prefix)) != 0) {
1178 *error_string = "Internal error - incorrect path prefix for nodelist node state";
1179
1180 return (0);
1181 }
1182
1183 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number,
1184 path + strlen(path_prefix));
1185 if ((strcmp(path, "nodelist.node.nodeid") == 0) ||
1186 (strcmp(path, "nodelist.node.quorum_votes") == 0)) {
1187 val_type = ICMAP_VALUETYPE_UINT32;
1188 if (safe_atoq(value, &val, val_type) != 0) {
1189 goto safe_atoq_error;
1190 }
1191
1192 if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1193 goto icmap_set_error;
1194 }
1195 add_as_string = 0;
1196 }
1197
1198 if (add_as_string) {
1199 if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1200 goto icmap_set_error;
1201 };
1202 add_as_string = 0;
1203 }
1204 break;
1206 if (strcmp(key, "watchdog_timeout") == 0) {
1207 val_type = ICMAP_VALUETYPE_UINT32;
1208 if (safe_atoq(value, &val, val_type) != 0) {
1209 goto safe_atoq_error;
1210 }
1211 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1212 goto icmap_set_error;
1213 }
1214 add_as_string = 0;
1215 }
1216 break;
1219 if (strcmp(key, "poll_period") == 0) {
1220 if (str_to_ull(value, &ull) != 0) {
1221 goto str_to_ull_error;
1222 }
1223 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1224 goto icmap_set_error;
1225 }
1226 add_as_string = 0;
1227 }
1228 break;
1231 if (strcmp(key, "poll_period") == 0) {
1232 if (str_to_ull(value, &ull) != 0) {
1233 goto str_to_ull_error;
1234 }
1235 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1236 goto icmap_set_error;
1237 }
1238 add_as_string = 0;
1239 }
1240 break;
1241 }
1242
1243 if (add_as_string) {
1244 if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1245 goto icmap_set_error;
1246 }
1247 }
1248 break;
1250 if (strcmp(path, "totem.interface") == 0) {
1252 data->linknumber = 0;
1253 data->mcastport = -1;
1254 data->ttl = -1;
1255 data->knet_link_priority = -1;
1256 data->knet_ping_interval = -1;
1257 data->knet_ping_timeout = -1;
1258 data->knet_ping_precision = -1;
1259 data->knet_pong_count = -1;
1260 data->knet_transport = NULL;
1261 qb_list_init(&data->member_items_head);
1262 };
1263 if (strcmp(path, "totem") == 0) {
1265 };
1266 if (strcmp(path, "system") == 0) {
1268 }
1269 if (strcmp(path, "logging.logger_subsys") == 0) {
1271 qb_list_init(&data->logger_subsys_items_head);
1272 data->subsys = NULL;
1273 }
1274 if (strcmp(path, "logging.logging_daemon") == 0) {
1276 qb_list_init(&data->logger_subsys_items_head);
1277 data->subsys = NULL;
1278 data->logging_daemon_name = NULL;
1279 }
1280 if (strcmp(path, "uidgid") == 0) {
1282 }
1283 if (strcmp(path, "totem.interface.member") == 0) {
1285 }
1286 if (strcmp(path, "quorum") == 0) {
1288 }
1289 if (strcmp(path, "quorum.device") == 0) {
1291 }
1292 if (strcmp(path, "nodelist") == 0) {
1294 data->node_number = 0;
1295 }
1296 if (strcmp(path, "nodelist.node") == 0) {
1298 }
1299 if (strcmp(path, "resources") == 0) {
1301 }
1302 if (strcmp(path, "resources.system") == 0) {
1304 }
1305 if (strcmp(path, "resources.system.memory_used") == 0) {
1307 }
1308 if (strcmp(path, "resources.process") == 0) {
1310 }
1311 if (strcmp(path, "resources.process.memory_used") == 0) {
1313 }
1314
1315 if (*state == MAIN_CP_CB_DATA_STATE_UIDGID && strcmp(path, "uidgid") != 0) {
1316 *error_string = "Subsections are not allowed within uidgid section";
1317
1318 return (0);
1319 };
1320
1321 if (*state == MAIN_CP_CB_DATA_STATE_MEMBER && strcmp(path, "totem.interface.member") != 0) {
1322 *error_string = "Subsections are not allowed within totem.interface.member section";
1323
1324 return (0);
1325 };
1326 break;
1328 switch (*state) {
1330 if (strcmp(path, "totem.interface") != 0) {
1331 /*
1332 * Process only end of totem.interface section, not subsections
1333 */
1334 break;
1335 }
1336
1337 /*
1338 * Create new interface section
1339 */
1340 if (data->bindnetaddr != NULL) {
1341 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1342 data->linknumber);
1343 cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1344
1345 free(data->bindnetaddr);
1346 data->bindnetaddr = NULL;
1347
1348 if (cs_err != CS_OK) {
1349 goto icmap_set_error;
1350 }
1351 }
1352
1353 if (data->mcastaddr != NULL) {
1354 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1355 data->linknumber);
1356 cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1357
1358 free(data->mcastaddr);
1359 data->mcastaddr = NULL;
1360
1361 if (cs_err != CS_OK) {
1362 goto icmap_set_error;
1363 }
1364 }
1365
1366 if (data->broadcast != NULL) {
1367 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1368 data->linknumber);
1369 cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1370
1371 free(data->broadcast);
1372 data->broadcast = NULL;
1373
1374 if (cs_err != CS_OK) {
1375 goto icmap_set_error;
1376 }
1377 }
1378
1379 if (data->mcastport > -1) {
1380 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1381 data->linknumber);
1382 if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1383 data->mcastport)) != CS_OK) {
1384 goto icmap_set_error;
1385 }
1386 }
1387
1388 if (data->ttl > -1) {
1389 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1390 data->linknumber);
1391 if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1392 goto icmap_set_error;
1393 }
1394 }
1395 if (data->knet_link_priority > -1) {
1396 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1397 data->linknumber);
1398 if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1399 data->knet_link_priority)) != CS_OK) {
1400 goto icmap_set_error;
1401 }
1402 }
1403 if (data->knet_ping_interval > -1) {
1404 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1405 data->linknumber);
1406 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1407 data->knet_ping_interval)) != CS_OK) {
1408 goto icmap_set_error;
1409 }
1410 }
1411 if (data->knet_ping_timeout > -1) {
1412 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1413 data->linknumber);
1414 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1415 data->knet_ping_timeout)) != CS_OK) {
1416 goto icmap_set_error;
1417 }
1418 }
1419 if (data->knet_ping_precision > -1) {
1420 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1421 data->linknumber);
1422 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1423 data->knet_ping_precision)) != CS_OK) {
1424 goto icmap_set_error;
1425 }
1426 }
1427 if (data->knet_pong_count > -1) {
1428 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1429 data->linknumber);
1430 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1431 data->knet_pong_count)) != CS_OK) {
1432 goto icmap_set_error;
1433 }
1434 }
1435 if (data->knet_transport) {
1436 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1437 data->linknumber);
1438 cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1439 free(data->knet_transport);
1440 data->knet_transport = NULL;
1441
1442 if (cs_err != CS_OK) {
1443 goto icmap_set_error;
1444 }
1445 }
1446
1447 ii = 0;
1448
1449 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1450 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1451 qb_list_del(&kv_item->list);
1452
1453 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1454 data->linknumber, ii);
1455 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1456
1457 free(kv_item->value);
1458 free(kv_item->key);
1459 free(kv_item);
1460 ii++;
1461
1462 if (cs_err != CS_OK) {
1463 goto icmap_set_error;
1464 }
1465 }
1466
1467 qb_list_init(&data->member_items_head);
1468
1469 break;
1471 if (strcmp(path, "logging.logger_subsys") != 0) {
1472 /*
1473 * Process only end of logging.logger_subsys section, not subsections
1474 */
1475 break;
1476 }
1477
1478 if (data->subsys == NULL) {
1479 *error_string = "No subsys key in logger_subsys directive";
1480
1481 return (0);
1482 }
1483
1484 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1485 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1486 qb_list_del(&kv_item->list);
1487
1488 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1489 data->subsys, kv_item->key);
1490 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1491
1492 free(kv_item->value);
1493 free(kv_item->key);
1494 free(kv_item);
1495
1496 if (cs_err != CS_OK) {
1497 goto icmap_set_error;
1498 }
1499 }
1500
1501 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1502 data->subsys);
1503 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1504
1505 qb_list_init(&data->logger_subsys_items_head);
1506 free(data->subsys);
1507 data->subsys = NULL;
1508
1509 if (cs_err != CS_OK) {
1510 goto icmap_set_error;
1511 }
1512 break;
1514 if (strcmp(path, "logging.logging_daemon") != 0) {
1515 /*
1516 * Process only end of logging.logging_daemon section, not subsections
1517 */
1518 break;
1519 }
1520
1521 if (data->logging_daemon_name == NULL) {
1522 *error_string = "No name key in logging_daemon directive";
1523
1524 return (0);
1525 }
1526
1527 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1528 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1529 qb_list_del(&kv_item->list);
1530
1531 if (data->subsys == NULL) {
1532 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1533 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1534 "logging.%s",
1535 kv_item->key);
1536 } else {
1537 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1538 "logging.logging_daemon.%s.%s",
1539 data->logging_daemon_name, kv_item->key);
1540 }
1541 } else {
1542 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1543 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1544 "logging.logger_subsys.%s.%s",
1545 data->subsys,
1546 kv_item->key);
1547 } else {
1548 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1549 "logging.logging_daemon.%s.%s.%s",
1550 data->logging_daemon_name, data->subsys,
1551 kv_item->key);
1552 }
1553 }
1554 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1555
1556 free(kv_item->value);
1557 free(kv_item->key);
1558 free(kv_item);
1559
1560 if (cs_err != CS_OK) {
1561 goto icmap_set_error;
1562 }
1563 }
1564
1565 if (data->subsys == NULL) {
1566 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1567 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1568 data->logging_daemon_name);
1569 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1570 }
1571 } else {
1572 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1573 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1574 data->subsys);
1575 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1576
1577 } else {
1578 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1579 data->logging_daemon_name, data->subsys);
1580 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1581
1582 if (cs_err != CS_OK) {
1583 goto icmap_set_error;
1584 }
1585 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1586 data->logging_daemon_name, data->subsys);
1587 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1588 }
1589 }
1590
1591 qb_list_init(&data->logger_subsys_items_head);
1592 free(data->subsys);
1593 data->subsys = NULL;
1594 free(data->logging_daemon_name);
1595 data->logging_daemon_name = NULL;
1596
1597 if (cs_err != CS_OK) {
1598 goto icmap_set_error;
1599 }
1600 break;
1602 if (strcmp(path, "nodelist.node") != 0) {
1603 /*
1604 * Process only end of nodelist.node section, not subsections
1605 */
1606 break;
1607 }
1608
1609 data->node_number++;
1610 break;
1625 break;
1626 }
1627 break;
1628 }
1629
1630 return (1);
1631
1632safe_atoq_error:
1633 /*
1634 * For integers supported by safe_atoq display range
1635 */
1636 min_val = max_val = 0;
1637 /*
1638 * This is really assert, because developer ether doesn't set val_type correctly or
1639 * we've got here after some nasty memory overwrite
1640 */
1641 assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1642
1643 if (snprintf(formated_err, sizeof(formated_err),
1644 "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1645 key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1646 *error_string = "Can't format parser error message";
1647 } else {
1648 *error_string = formated_err;
1649 }
1650
1651 return (0);
1652
1653str_to_ull_error:
1654 /*
1655 * For integers not supported by safe_atoq (64-bit int)
1656 */
1657 if (snprintf(formated_err, sizeof(formated_err),
1658 "Value of key \"%s\" is expected to be unsigned integer, but \"%s\" was given",
1659 key_name, value) >= sizeof(formated_err)) {
1660 *error_string = "Can't format parser error message";
1661 } else {
1662 *error_string = formated_err;
1663 }
1664
1665 return (0);
1666
1667str_to_dscp_error:
1668 if (snprintf(formated_err, sizeof(formated_err),
1669 "Value of key \"%s\" is expected to be number (0..63) or symbolical dscp value, "
1670 "but \"%s\" was given", key_name, value) >= sizeof(formated_err)) {
1671 *error_string = "Can't format parser error message";
1672 } else {
1673 *error_string = formated_err;
1674 }
1675
1676 return (0);
1677
1678icmap_set_error:
1679 if (snprintf(formated_err, sizeof(formated_err),
1680 "Can't store key \"%s\" into icmap, returned error is %s",
1681 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1682 *error_string = "Can't format parser error message";
1683 } else {
1684 *error_string = formated_err;
1685 }
1686
1687 return (0);
1688}
1689
1690static int uidgid_config_parser_cb(const char *path,
1691 char *key,
1692 char *value,
1693 enum main_cp_cb_data_state *state,
1694 enum parser_cb_type type,
1695 const char **error_string,
1696 icmap_map_t config_map,
1697 void *user_data)
1698{
1699 char key_name[ICMAP_KEYNAME_MAXLEN];
1700 int uid, gid;
1701 static char formated_err[256];
1702 cs_error_t cs_err;
1703
1704 switch (type) {
1705 case PARSER_CB_START:
1706 break;
1707 case PARSER_CB_END:
1708 break;
1709 case PARSER_CB_CLEANUP:
1710 break;
1711 case PARSER_CB_ITEM:
1712 if (strcmp(path, "uidgid.uid") == 0) {
1713 uid = uid_determine(value);
1714 if (uid == -1) {
1715 *error_string = error_string_response;
1716 return (0);
1717 }
1718 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1719 uid);
1720 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1721 goto icmap_set_error;
1722 }
1723 } else if (strcmp(path, "uidgid.gid") == 0) {
1724 gid = gid_determine(value);
1725 if (gid == -1) {
1726 *error_string = error_string_response;
1727 return (0);
1728 }
1729 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1730 gid);
1731 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1732 goto icmap_set_error;
1733 }
1734 } else {
1735 *error_string = "uidgid: Only uid and gid are allowed items";
1736 return (0);
1737 }
1738 break;
1740 if (strcmp(path, "uidgid") != 0) {
1741 *error_string = "uidgid: Can't add subsection different than uidgid";
1742 return (0);
1743 };
1744 break;
1746 break;
1747 }
1748
1749 return (1);
1750
1751icmap_set_error:
1752 if (snprintf(formated_err, sizeof(formated_err),
1753 "Can't store key \"%s\" into icmap, returned error is %s",
1754 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1755 *error_string = "Can't format parser error message";
1756 } else {
1757 *error_string = formated_err;
1758 }
1759
1760 return (0);
1761}
1762
1763static int read_uidgid_files_into_icmap(
1764 const char **error_string,
1765 icmap_map_t config_map)
1766{
1767 FILE *fp;
1768 char *dirname_res;
1769 DIR *dp;
1770 struct dirent *dirent;
1771 char filename[PATH_MAX + FILENAME_MAX + 1];
1772 char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1773 int res = 0;
1774 struct stat stat_buf;
1776 char key_name[ICMAP_KEYNAME_MAXLEN];
1777 int line_no;
1778
1779 /*
1780 * Build uidgid directory based on corosync.conf file location
1781 */
1782 res = snprintf(filename, sizeof(filename), "%s",
1784 if (res >= sizeof(filename)) {
1785 *error_string = "uidgid.d path too long";
1786
1787 return (-1);
1788 }
1789
1790 dirname_res = dirname(filename);
1791
1792 res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1793 dirname_res, "uidgid.d");
1794 if (res >= sizeof(uidgid_dirname)) {
1795 *error_string = "uidgid.d path too long";
1796
1797 return (-1);
1798 }
1799
1800 dp = opendir (uidgid_dirname);
1801
1802 if (dp == NULL)
1803 return 0;
1804
1805 for (dirent = readdir(dp);
1806 dirent != NULL;
1807 dirent = readdir(dp)) {
1808
1809 res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1810 if (res >= sizeof(filename)) {
1811 res = -1;
1812 *error_string = "uidgid.d dirname path too long";
1813
1814 goto error_exit;
1815 }
1816 // coverity[TOCTOU:SUPPRESS] not really problem
1817 res = stat (filename, &stat_buf);
1818 if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1819
1820 fp = fopen (filename, "r");
1821 if (fp == NULL) continue;
1822
1823 key_name[0] = 0;
1824
1825 line_no = 0;
1826 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1827 uidgid_config_parser_cb, config_map, NULL);
1828
1829 fclose (fp);
1830
1831 if (res != 0) {
1832 goto error_exit;
1833 }
1834 }
1835 }
1836
1837error_exit:
1838 closedir(dp);
1839
1840 return res;
1841}
1842
1843/* Read config file and load into icmap */
1844static int read_config_file_into_icmap(
1845 const char **error_string,
1846 icmap_map_t config_map)
1847{
1848 FILE *fp;
1849 const char *filename;
1850 char *error_reason = error_string_response;
1851 int res;
1852 char key_name[ICMAP_KEYNAME_MAXLEN];
1853 struct main_cp_cb_data data;
1855 int line_no;
1856
1857 filename = corosync_get_config_file();
1858
1859 fp = fopen (filename, "r");
1860 if (fp == NULL) {
1861 char error_str[100];
1862 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1863 snprintf (error_reason, sizeof(error_string_response),
1864 "Can't read file %s: %s",
1865 filename, error_ptr);
1866 *error_string = error_reason;
1867 return -1;
1868 }
1869
1870 key_name[0] = 0;
1871
1872 line_no = 0;
1873 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1874 main_config_parser_cb, config_map, &data);
1875
1876 fclose(fp);
1877
1878 if (res == 0) {
1879 res = read_uidgid_files_into_icmap(error_string, config_map);
1880 }
1881
1882 if (res == 0) {
1883 snprintf (error_reason, sizeof(error_string_response),
1884 "Successfully read main configuration file '%s'.", filename);
1885 *error_string = error_reason;
1886 }
1887
1888 return res;
1889}
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
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:286
int util_is_valid_knet_crypto_cipher(const char *val, const char **list_str, int machine_parseable_str, const char *error_string_prefix, const char **error_string)
Definition util.c:356
int util_is_valid_knet_crypto_hash(const char *val, const char **list_str, int machine_parseable_str, const char *error_string_prefix, const char **error_string)
Definition util.c:404
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:321