corosync 3.1.7
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
73};
74
94};
95
96typedef int (*parser_cb_f)(const char *path,
97 char *key,
98 char *value,
99 enum main_cp_cb_data_state *state,
100 enum parser_cb_type type,
101 const char **error_string,
102 icmap_map_t config_map,
103 void *user_data);
104
106 char *key;
107 char *value;
108 struct qb_list_head list;
109};
110
117 int ttl;
124 unsigned int knet_mtu;
126
127 struct qb_list_head logger_subsys_items_head;
128 char *subsys;
130 struct qb_list_head member_items_head;
131
133};
134
135static int read_config_file_into_icmap(
136 const char **error_string, icmap_map_t config_map);
137static char error_string_response[512];
138
139static int uid_determine (const char *req_user)
140{
141 int pw_uid = 0;
142 struct passwd passwd;
143 struct passwd* pwdptr = &passwd;
144 struct passwd* temp_pwd_pt;
145 char *pwdbuffer;
146 int pwdlinelen, rc;
147 long int id;
148 char *ep;
149
150 id = strtol(req_user, &ep, 10);
151 if (*req_user != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
152 return (id);
153 }
154
155 pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
156
157 if (pwdlinelen == -1) {
158 pwdlinelen = 256;
159 }
160
161 pwdbuffer = malloc (pwdlinelen);
162
163 while ((rc = getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) == ERANGE) {
164 char *n;
165
166 pwdlinelen *= 2;
167 if (pwdlinelen <= 32678) {
168 n = realloc (pwdbuffer, pwdlinelen);
169 if (n != NULL) {
170 pwdbuffer = n;
171 continue;
172 }
173 }
174 }
175 if (rc != 0) {
176 free (pwdbuffer);
177 sprintf (error_string_response, "getpwnam_r(): %s", strerror(rc));
178 return (-1);
179 }
180 if (temp_pwd_pt == NULL) {
181 free (pwdbuffer);
182 sprintf (error_string_response,
183 "The '%s' user is not found in /etc/passwd, please read the documentation.",
184 req_user);
185 return (-1);
186 }
187 pw_uid = passwd.pw_uid;
188 free (pwdbuffer);
189
190 return pw_uid;
191}
192
193static int gid_determine (const char *req_group)
194{
195 int corosync_gid = 0;
196 struct group group;
197 struct group * grpptr = &group;
198 struct group * temp_grp_pt;
199 char *grpbuffer;
200 int grplinelen, rc;
201 long int id;
202 char *ep;
203
204 id = strtol(req_group, &ep, 10);
205 if (*req_group != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
206 return (id);
207 }
208
209 grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
210
211 if (grplinelen == -1) {
212 grplinelen = 256;
213 }
214
215 grpbuffer = malloc (grplinelen);
216
217 while ((rc = getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) == ERANGE) {
218 char *n;
219
220 grplinelen *= 2;
221 if (grplinelen <= 32678) {
222 n = realloc (grpbuffer, grplinelen);
223 if (n != NULL) {
224 grpbuffer = n;
225 continue;
226 }
227 }
228 }
229 if (rc != 0) {
230 free (grpbuffer);
231 sprintf (error_string_response, "getgrnam_r(): %s", strerror(rc));
232 return (-1);
233 }
234 if (temp_grp_pt == NULL) {
235 free (grpbuffer);
236 sprintf (error_string_response,
237 "The '%s' group is not found in /etc/group, please read the documentation.",
238 req_group);
239 return (-1);
240 }
241 corosync_gid = group.gr_gid;
242 free (grpbuffer);
243
244 return corosync_gid;
245}
246static char *strchr_rs (const char *haystack, int byte)
247{
248 const char *end_address = strchr (haystack, byte);
249 if (end_address) {
250 end_address += 1; /* skip past { or = */
251
252 while (*end_address == ' ' || *end_address == '\t')
253 end_address++;
254 }
255
256 return ((char *) end_address);
257}
258
259int coroparse_configparse (icmap_map_t config_map, const char **error_string)
260{
261 if (read_config_file_into_icmap(error_string, config_map)) {
262 return -1;
263 }
264
265 return 0;
266}
267
268static char *remove_whitespace(char *string, int remove_colon_and_brace)
269{
270 char *start;
271 char *end;
272
273 start = string;
274 while (*start == ' ' || *start == '\t')
275 start++;
276
277 end = start+(strlen(start))-1;
278 while ((*end == ' ' || *end == '\t' || (remove_colon_and_brace && (*end == ':' || *end == '{'))) && end > start)
279 end--;
280 if (*end != '\0')
281 *(end + 1) = '\0';
282
283 return start;
284}
285
286
287
288static int parse_section(FILE *fp,
289 const char *fname,
290 int *line_no,
291 char *path,
292 const char **error_string,
293 int depth,
294 enum main_cp_cb_data_state state,
295 parser_cb_f parser_cb,
296 icmap_map_t config_map,
297 void *user_data)
298{
299 char line[512];
300 int i;
301 char *loc;
302 int ignore_line;
303 char new_keyname[ICMAP_KEYNAME_MAXLEN];
304 static char formated_err[384];
305 const char *tmp_error_string;
306
307 if (strcmp(path, "") == 0) {
308 parser_cb("", NULL, NULL, &state, PARSER_CB_START, error_string, config_map, user_data);
309 }
310
311 tmp_error_string = NULL;
312
313 while (fgets (line, sizeof (line), fp)) {
314 (*line_no)++;
315
316 if (strlen(line) > 0) {
317 /*
318 * Check if complete line was read. Use feof to handle files
319 * without ending \n at the end of the file
320 */
321 if ((line[strlen(line) - 1] != '\n') && !feof(fp)) {
322 tmp_error_string = "Line too long";
323 goto parse_error;
324 }
325
326 if (line[strlen(line) - 1] == '\n')
327 line[strlen(line) - 1] = '\0';
328 if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
329 line[strlen(line) - 1] = '\0';
330 }
331 /*
332 * Clear out white space and tabs
333 */
334 for (i = strlen (line) - 1; i > -1; i--) {
335 if (line[i] == '\t' || line[i] == ' ') {
336 line[i] = '\0';
337 } else {
338 break;
339 }
340 }
341
342 ignore_line = 1;
343 for (i = 0; i < strlen (line); i++) {
344 if (line[i] != '\t' && line[i] != ' ') {
345 if (line[i] != '#')
346 ignore_line = 0;
347
348 break;
349 }
350 }
351 /*
352 * Clear out comments and empty lines
353 */
354 if (ignore_line) {
355 continue;
356 }
357
358 /* New section ? */
359 if ((loc = strchr_rs (line, '{'))) {
360 char *section;
361 char *after_section;
362 enum main_cp_cb_data_state newstate;
363
364 *(loc-1) = '\0';
365 section = remove_whitespace(line, 1);
366 after_section = remove_whitespace(loc, 0);
367
368 if (strcmp(section, "") == 0) {
369 tmp_error_string = "Missing section name before opening bracket '{'";
370 goto parse_error;
371 }
372
373 if (strcmp(after_section, "") != 0) {
374 tmp_error_string = "Extra characters after opening bracket '{'";
375 goto parse_error;
376 }
377
378 if (strlen(path) + strlen(section) + 1 >= ICMAP_KEYNAME_MAXLEN) {
379 tmp_error_string = "Start of section makes total cmap path too long";
380 goto parse_error;
381 }
382 strcpy(new_keyname, path);
383 if (strcmp(path, "") != 0) {
384 strcat(new_keyname, ".");
385 }
386 strcat(new_keyname, section);
387
388 /* Only use the new state for items further down the stack */
389 newstate = state;
390 if (!parser_cb(new_keyname, NULL, NULL, &newstate, PARSER_CB_SECTION_START,
391 &tmp_error_string, config_map, user_data)) {
392 goto parse_error;
393 }
394
395 if (parse_section(fp, fname, line_no, new_keyname, error_string, depth + 1, newstate,
396 parser_cb, config_map, user_data))
397 return -1;
398
399 continue ;
400 }
401
402 /* New key/value */
403 if ((loc = strchr_rs (line, ':'))) {
404 char *key;
405 char *value;
406
407 *(loc-1) = '\0';
408 key = remove_whitespace(line, 1);
409 value = remove_whitespace(loc, 0);
410
411 if (strlen(path) + strlen(key) + 1 >= ICMAP_KEYNAME_MAXLEN) {
412 tmp_error_string = "New key makes total cmap path too long";
413 goto parse_error;
414 }
415 strcpy(new_keyname, path);
416 if (strcmp(path, "") != 0) {
417 strcat(new_keyname, ".");
418 }
419 strcat(new_keyname, key);
420
421 if (!parser_cb(new_keyname, key, value, &state, PARSER_CB_ITEM, &tmp_error_string,
422 config_map, user_data)) {
423 goto parse_error;
424 }
425
426 continue ;
427 }
428
429 if (strchr_rs (line, '}')) {
430 char *trimmed_line;
431 trimmed_line = remove_whitespace(line, 0);
432
433 if (strcmp(trimmed_line, "}") != 0) {
434 tmp_error_string = "Extra characters before or after closing bracket '}'";
435 goto parse_error;
436 }
437
438 if (depth == 0) {
439 tmp_error_string = "Unexpected closing brace";
440
441 goto parse_error;
442 }
443
444 if (!parser_cb(path, NULL, NULL, &state, PARSER_CB_SECTION_END, &tmp_error_string,
445 config_map, user_data)) {
446 goto parse_error;
447 }
448
449 return 0;
450 }
451
452 /*
453 * Line is not opening section, ending section or value -> error
454 */
455 tmp_error_string = "Line is not opening or closing section or key value";
456 goto parse_error;
457 }
458
459 if (strcmp(path, "") != 0) {
460 tmp_error_string = "Missing closing brace";
461 goto parse_error;
462 }
463
464 if (strcmp(path, "") == 0) {
465 parser_cb("", NULL, NULL, &state, PARSER_CB_END, error_string, config_map, user_data);
466 }
467
468 return 0;
469
470parse_error:
471 if (snprintf(formated_err, sizeof(formated_err), "parser error: %s:%u: %s", fname, *line_no,
472 tmp_error_string) >= sizeof(formated_err)) {
473 *error_string = "Can't format parser error message";
474 } else {
475 *error_string = formated_err;
476 }
477
478 return -1;
479}
480
481static int safe_atoq_range(icmap_value_types_t value_type, long long int *min_val, long long int *max_val)
482{
483 switch (value_type) {
484 case ICMAP_VALUETYPE_INT8: *min_val = INT8_MIN; *max_val = INT8_MAX; break;
485 case ICMAP_VALUETYPE_UINT8: *min_val = 0; *max_val = UINT8_MAX; break;
486 case ICMAP_VALUETYPE_INT16: *min_val = INT16_MIN; *max_val = INT16_MAX; break;
487 case ICMAP_VALUETYPE_UINT16: *min_val = 0; *max_val = UINT16_MAX; break;
488 case ICMAP_VALUETYPE_INT32: *min_val = INT32_MIN; *max_val = INT32_MAX; break;
489 case ICMAP_VALUETYPE_UINT32: *min_val = 0; *max_val = UINT32_MAX; break;
490 default:
491 return (-1);
492 }
493
494 return (0);
495}
496
497/*
498 * Convert string str to long long int res. Type of result is target_type and currently only
499 * ICMAP_VALUETYPE_[U]INT[8|16|32] is supported.
500 * Return 0 on success, -1 on failure.
501 */
502static int safe_atoq(const char *str, long long int *res, icmap_value_types_t target_type)
503{
504 long long int val;
505 long long int min_val, max_val;
506 char *endptr;
507
508 errno = 0;
509
510 val = strtoll(str, &endptr, 10);
511 if (errno == ERANGE) {
512 return (-1);
513 }
514
515 if (endptr == str) {
516 return (-1);
517 }
518
519 if (*endptr != '\0') {
520 return (-1);
521 }
522
523 if (safe_atoq_range(target_type, &min_val, &max_val) != 0) {
524 return (-1);
525 }
526
527 if (val < min_val || val > max_val) {
528 return (-1);
529 }
530
531 *res = val;
532 return (0);
533}
534
535static int str_to_ull(const char *str, unsigned long long int *res)
536{
537 unsigned long long int val;
538 char *endptr;
539
540 errno = 0;
541
542 val = strtoull(str, &endptr, 10);
543 if (errno == ERANGE) {
544 return (-1);
545 }
546
547 if (endptr == str) {
548 return (-1);
549 }
550
551 if (*endptr != '\0') {
552 return (-1);
553 }
554
555 *res = val;
556 return (0);
557}
558
559static int handle_crypto_model(const char *val, const char **error_string)
560{
561
562 if (util_is_valid_knet_crypto_model(val, NULL, 0,
563 "Invalid crypto model. Should be ", error_string) == 1) {
564 return (0);
565 } else {
566 return (-1);
567 }
568}
569
570static int handle_compress_model(const char *val, const char **error_string)
571{
572
573 if (util_is_valid_knet_compress_model(val, NULL, 0,
574 "Invalid compression model. Should be ", error_string) == 1) {
575 return (0);
576 } else {
577 return (-1);
578 }
579}
580
581static int main_config_parser_cb(const char *path,
582 char *key,
583 char *value,
584 enum main_cp_cb_data_state *state,
585 enum parser_cb_type type,
586 const char **error_string,
587 icmap_map_t config_map,
588 void *user_data)
589{
590 int ii;
591 long long int val;
592 long long int min_val, max_val;
594 unsigned long long int ull;
595 int add_as_string;
596 char key_name[ICMAP_KEYNAME_MAXLEN + 1];
597 static char formated_err[256];
598 struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
599 struct key_value_list_item *kv_item;
600 struct qb_list_head *iter, *tmp_iter;
601 int uid, gid;
602 cs_error_t cs_err;
603
604 cs_err = CS_OK;
605
606 /*
607 * Formally this check is not needed because length is checked by parse_section
608 */
609 if (strlen(path) >= sizeof(key_name)) {
610 if (snprintf(formated_err, sizeof(formated_err),
611 "Can't store path \"%s\" into key_name", path) >= sizeof(formated_err)) {
612 *error_string = "Can't format path into key_name error message";
613 } else {
614 *error_string = formated_err;
615 }
616 return (0);
617 }
618 /*
619 * Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
620 * are using path, so initialize key_name to valid value
621 */
622 strncpy(key_name, path, sizeof(key_name) - 1);
623
624 switch (type) {
625 case PARSER_CB_START:
626 memset(data, 0, sizeof(struct main_cp_cb_data));
628 break;
629 case PARSER_CB_END:
630 break;
631 case PARSER_CB_ITEM:
632 add_as_string = 1;
633
634 switch (*state) {
636 break;
638 if ((strcmp(path, "pload.count") == 0) ||
639 (strcmp(path, "pload.size") == 0)) {
640 val_type = ICMAP_VALUETYPE_UINT32;
641 if (safe_atoq(value, &val, val_type) != 0) {
642 goto atoi_error;
643 }
644 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
645 goto icmap_set_error;
646 }
647 add_as_string = 0;
648 }
649 break;
651 if ((strcmp(path, "quorum.expected_votes") == 0) ||
652 (strcmp(path, "quorum.votes") == 0) ||
653 (strcmp(path, "quorum.last_man_standing_window") == 0) ||
654 (strcmp(path, "quorum.leaving_timeout") == 0)) {
655 val_type = ICMAP_VALUETYPE_UINT32;
656 if (safe_atoq(value, &val, val_type) != 0) {
657 goto atoi_error;
658 }
659 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
660 goto icmap_set_error;
661 }
662 add_as_string = 0;
663 }
664
665 if ((strcmp(path, "quorum.two_node") == 0) ||
666 (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
667 (strcmp(path, "quorum.allow_downscale") == 0) ||
668 (strcmp(path, "quorum.wait_for_all") == 0) ||
669 (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
670 (strcmp(path, "quorum.last_man_standing") == 0)) {
671 val_type = ICMAP_VALUETYPE_UINT8;
672 if (safe_atoq(value, &val, val_type) != 0) {
673 goto atoi_error;
674 }
675 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
676 goto icmap_set_error;
677 }
678 add_as_string = 0;
679 }
680 break;
682 if ((strcmp(path, "quorum.device.timeout") == 0) ||
683 (strcmp(path, "quorum.device.sync_timeout") == 0) ||
684 (strcmp(path, "quorum.device.votes") == 0)) {
685 val_type = ICMAP_VALUETYPE_UINT32;
686 if (safe_atoq(value, &val, val_type) != 0) {
687 goto atoi_error;
688 }
689 if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
690 goto icmap_set_error;
691 }
692 add_as_string = 0;
693 }
694 if ((strcmp(path, "quorum.device.master_wins") == 0)) {
695 val_type = ICMAP_VALUETYPE_UINT8;
696 if (safe_atoq(value, &val, val_type) != 0) {
697 goto atoi_error;
698 }
699 if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
700 goto icmap_set_error;
701 }
702 add_as_string = 0;
703 }
704 break;
706 if ((strcmp(path, "totem.version") == 0) ||
707 (strcmp(path, "totem.nodeid") == 0) ||
708 (strcmp(path, "totem.threads") == 0) ||
709 (strcmp(path, "totem.token") == 0) ||
710 (strcmp(path, "totem.token_coefficient") == 0) ||
711 (strcmp(path, "totem.token_retransmit") == 0) ||
712 (strcmp(path, "totem.token_warning") == 0) ||
713 (strcmp(path, "totem.hold") == 0) ||
714 (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
715 (strcmp(path, "totem.join") == 0) ||
716 (strcmp(path, "totem.send_join") == 0) ||
717 (strcmp(path, "totem.consensus") == 0) ||
718 (strcmp(path, "totem.merge") == 0) ||
719 (strcmp(path, "totem.downcheck") == 0) ||
720 (strcmp(path, "totem.fail_recv_const") == 0) ||
721 (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
722 (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
723 (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
724 (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
725 (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
726 (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
727 (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
728 (strcmp(path, "totem.max_network_delay") == 0) ||
729 (strcmp(path, "totem.window_size") == 0) ||
730 (strcmp(path, "totem.max_messages") == 0) ||
731 (strcmp(path, "totem.miss_count_const") == 0) ||
732 (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
733 (strcmp(path, "totem.knet_mtu") == 0) ||
734 (strcmp(path, "totem.knet_compression_threshold") == 0) ||
735 (strcmp(path, "totem.netmtu") == 0)) {
736 val_type = ICMAP_VALUETYPE_UINT32;
737 if (safe_atoq(value, &val, val_type) != 0) {
738 goto atoi_error;
739 }
740 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
741 goto icmap_set_error;
742 }
743 add_as_string = 0;
744 }
745 if (strcmp(path, "totem.knet_compression_level") == 0) {
746 val_type = ICMAP_VALUETYPE_INT32;
747 if (safe_atoq(value, &val, val_type) != 0) {
748 goto atoi_error;
749 }
750 if ((cs_err = icmap_set_int32_r(config_map, path, val)) != CS_OK) {
751 goto icmap_set_error;
752 }
753 add_as_string = 0;
754 }
755 if (strcmp(path, "totem.config_version") == 0) {
756 if (str_to_ull(value, &ull) != 0) {
757 goto atoi_error;
758 }
759 if ((cs_err = icmap_set_uint64_r(config_map, path, ull)) != CS_OK) {
760 goto icmap_set_error;
761 }
762 add_as_string = 0;
763 }
764 if (strcmp(path, "totem.ip_version") == 0) {
765 if ((strcmp(value, "ipv4") != 0) &&
766 (strcmp(value, "ipv6") != 0) &&
767 (strcmp(value, "ipv6-4") != 0) &&
768 (strcmp(value, "ipv4-6") != 0)) {
769 *error_string = "Invalid ip_version type";
770
771 return (0);
772 }
773 }
774 if (strcmp(path, "totem.crypto_model") == 0) {
775 if (handle_crypto_model(value, error_string) != 0) {
776 return (0);
777 }
778 }
779
780 if (strcmp(path, "totem.crypto_cipher") == 0) {
781 if ((strcmp(value, "none") != 0) &&
782 (strcmp(value, "aes256") != 0) &&
783 (strcmp(value, "aes192") != 0) &&
784 (strcmp(value, "aes128") != 0)) {
785 *error_string = "Invalid cipher type. "
786 "Should be none, aes256, aes192 or aes128";
787
788 return (0);
789 }
790 }
791 if (strcmp(path, "totem.crypto_hash") == 0) {
792 if ((strcmp(value, "none") != 0) &&
793 (strcmp(value, "md5") != 0) &&
794 (strcmp(value, "sha1") != 0) &&
795 (strcmp(value, "sha256") != 0) &&
796 (strcmp(value, "sha384") != 0) &&
797 (strcmp(value, "sha512") != 0)) {
798 *error_string = "Invalid hash type. "
799 "Should be none, md5, sha1, sha256, sha384 or sha512";
800
801 return (0);
802 }
803 }
804
805 if (strcmp(path, "totem.knet_compression_model") == 0) {
806 if (handle_compress_model(value, error_string) != 0) {
807 return (0);
808 }
809 }
810
811 break;
812
814 if (strcmp(path, "system.qb_ipc_type") == 0) {
815 if ((strcmp(value, "native") != 0) &&
816 (strcmp(value, "shm") != 0) &&
817 (strcmp(value, "socket") != 0)) {
818 *error_string = "Invalid system.qb_ipc_type";
819
820 return (0);
821 }
822 }
823 if (strcmp(path, "system.sched_rr") == 0) {
824 if ((strcmp(value, "yes") != 0) &&
825 (strcmp(value, "no") != 0)) {
826 *error_string = "Invalid system.sched_rr value";
827
828 return (0);
829 }
830 }
831 if (strcmp(path, "system.move_to_root_cgroup") == 0) {
832 if ((strcmp(value, "yes") != 0) &&
833 (strcmp(value, "no") != 0) &&
834 (strcmp(value, "auto") != 0)) {
835 *error_string = "Invalid system.move_to_root_cgroup";
836
837 return (0);
838 }
839 }
840 if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
841 if ((strcmp(value, "yes") != 0) &&
842 (strcmp(value, "no") != 0)) {
843 *error_string = "Invalid system.allow_knet_handle_fallback";
844
845 return (0);
846 }
847 }
848 break;
849
851 if (strcmp(path, "totem.interface.linknumber") == 0) {
852 val_type = ICMAP_VALUETYPE_UINT8;
853 if (safe_atoq(value, &val, val_type) != 0) {
854 goto atoi_error;
855 }
856
857 data->linknumber = val;
858 add_as_string = 0;
859 }
860 if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
861 data->bindnetaddr = strdup(value);
862 add_as_string = 0;
863 }
864 if (strcmp(path, "totem.interface.mcastaddr") == 0) {
865 data->mcastaddr = strdup(value);
866 add_as_string = 0;
867 }
868 if (strcmp(path, "totem.interface.broadcast") == 0) {
869 data->broadcast = strdup(value);
870 add_as_string = 0;
871 }
872 if (strcmp(path, "totem.interface.mcastport") == 0) {
873 val_type = ICMAP_VALUETYPE_UINT16;
874 if (safe_atoq(value, &val, val_type) != 0) {
875 goto atoi_error;
876 }
877 data->mcastport = val;
878 add_as_string = 0;
879 }
880 if (strcmp(path, "totem.interface.ttl") == 0) {
881 val_type = ICMAP_VALUETYPE_UINT8;
882 if (safe_atoq(value, &val, val_type) != 0) {
883 goto atoi_error;
884 }
885 data->ttl = val;
886 add_as_string = 0;
887 }
888 if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
889 val_type = ICMAP_VALUETYPE_UINT8;
890 if (safe_atoq(value, &val, val_type) != 0) {
891 goto atoi_error;
892 }
893 data->knet_link_priority = val;
894 add_as_string = 0;
895 }
896 if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
897 val_type = ICMAP_VALUETYPE_UINT32;
898 if (safe_atoq(value, &val, val_type) != 0) {
899 goto atoi_error;
900 }
901 data->knet_ping_interval = val;
902 add_as_string = 0;
903 }
904 if (strcmp(path, "totem.interface.knet_ping_timeout") == 0) {
905 val_type = ICMAP_VALUETYPE_UINT32;
906 if (safe_atoq(value, &val, val_type) != 0) {
907 goto atoi_error;
908 }
909 data->knet_ping_timeout = val;
910 add_as_string = 0;
911 }
912 if (strcmp(path, "totem.interface.knet_ping_precision") == 0) {
913 val_type = ICMAP_VALUETYPE_UINT32;
914 if (safe_atoq(value, &val, val_type) != 0) {
915 goto atoi_error;
916 }
917 data->knet_ping_precision = val;
918 add_as_string = 0;
919 }
920 if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
921 val_type = ICMAP_VALUETYPE_UINT32;
922 if (safe_atoq(value, &val, val_type) != 0) {
923 goto atoi_error;
924 }
925 data->knet_pong_count = val;
926 add_as_string = 0;
927 }
928 if (strcmp(path, "totem.interface.knet_transport") == 0) {
929 val_type = ICMAP_VALUETYPE_STRING;
930 data->knet_transport = strdup(value);
931 add_as_string = 0;
932 }
933 break;
935 if (strcmp(key, "subsys") == 0) {
936 data->subsys = strdup(value);
937 if (data->subsys == NULL) {
938 *error_string = "Can't alloc memory";
939
940 return (0);
941 }
942 } else {
943 kv_item = malloc(sizeof(*kv_item));
944 if (kv_item == NULL) {
945 *error_string = "Can't alloc memory";
946
947 return (0);
948 }
949 memset(kv_item, 0, sizeof(*kv_item));
950
951 kv_item->key = strdup(key);
952 kv_item->value = strdup(value);
953 if (kv_item->key == NULL || kv_item->value == NULL) {
954 free(kv_item);
955 *error_string = "Can't alloc memory";
956
957 return (0);
958 }
959 qb_list_init(&kv_item->list);
960 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
961 }
962 add_as_string = 0;
963 break;
965 if (strcmp(key, "subsys") == 0) {
966 data->subsys = strdup(value);
967 if (data->subsys == NULL) {
968 *error_string = "Can't alloc memory";
969
970 return (0);
971 }
972 } else if (strcmp(key, "name") == 0) {
973 data->logging_daemon_name = strdup(value);
974 if (data->logging_daemon_name == NULL) {
975 *error_string = "Can't alloc memory";
976
977 return (0);
978 }
979 } else {
980 kv_item = malloc(sizeof(*kv_item));
981 if (kv_item == NULL) {
982 *error_string = "Can't alloc memory";
983
984 return (0);
985 }
986 memset(kv_item, 0, sizeof(*kv_item));
987
988 kv_item->key = strdup(key);
989 kv_item->value = strdup(value);
990 if (kv_item->key == NULL || kv_item->value == NULL) {
991 free(kv_item);
992 *error_string = "Can't alloc memory";
993
994 return (0);
995 }
996 qb_list_init(&kv_item->list);
997 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
998 }
999 add_as_string = 0;
1000 break;
1002 if (strcmp(key, "uid") == 0) {
1003 uid = uid_determine(value);
1004 if (uid == -1) {
1005 *error_string = error_string_response;
1006 return (0);
1007 }
1008 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1009 uid);
1010 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1011 goto icmap_set_error;
1012 }
1013 add_as_string = 0;
1014 } else if (strcmp(key, "gid") == 0) {
1015 gid = gid_determine(value);
1016 if (gid == -1) {
1017 *error_string = error_string_response;
1018 return (0);
1019 }
1020 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1021 gid);
1022 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1023 goto icmap_set_error;
1024 }
1025 add_as_string = 0;
1026 } else {
1027 *error_string = "uidgid: Only uid and gid are allowed items";
1028 return (0);
1029 }
1030 break;
1032 if (strcmp(key, "memberaddr") != 0) {
1033 *error_string = "Only memberaddr is allowed in member section";
1034
1035 return (0);
1036 }
1037
1038 kv_item = malloc(sizeof(*kv_item));
1039 if (kv_item == NULL) {
1040 *error_string = "Can't alloc memory";
1041
1042 return (0);
1043 }
1044 memset(kv_item, 0, sizeof(*kv_item));
1045
1046 kv_item->key = strdup(key);
1047 kv_item->value = strdup(value);
1048 if (kv_item->key == NULL || kv_item->value == NULL) {
1049 free(kv_item);
1050 *error_string = "Can't alloc memory";
1051
1052 return (0);
1053 }
1054 qb_list_init(&kv_item->list);
1055 qb_list_add(&kv_item->list, &data->member_items_head);
1056 add_as_string = 0;
1057 break;
1059 break;
1061 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
1062 if ((strcmp(key, "nodeid") == 0) ||
1063 (strcmp(key, "quorum_votes") == 0)) {
1064 val_type = ICMAP_VALUETYPE_UINT32;
1065 if (safe_atoq(value, &val, val_type) != 0) {
1066 goto atoi_error;
1067 }
1068
1069 if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1070 goto icmap_set_error;
1071 }
1072 add_as_string = 0;
1073 }
1074
1075 if (add_as_string) {
1076 if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1077 goto icmap_set_error;
1078 };
1079 add_as_string = 0;
1080 }
1081 break;
1083 if (strcmp(key, "watchdog_timeout") == 0) {
1084 val_type = ICMAP_VALUETYPE_UINT32;
1085 if (safe_atoq(value, &val, val_type) != 0) {
1086 goto atoi_error;
1087 }
1088 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1089 goto icmap_set_error;
1090 }
1091 add_as_string = 0;
1092 }
1093 break;
1096 if (strcmp(key, "poll_period") == 0) {
1097 if (str_to_ull(value, &ull) != 0) {
1098 goto atoi_error;
1099 }
1100 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1101 goto icmap_set_error;
1102 }
1103 add_as_string = 0;
1104 }
1105 break;
1108 if (strcmp(key, "poll_period") == 0) {
1109 if (str_to_ull(value, &ull) != 0) {
1110 goto atoi_error;
1111 }
1112 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1113 goto icmap_set_error;
1114 }
1115 add_as_string = 0;
1116 }
1117 break;
1118 }
1119
1120 if (add_as_string) {
1121 if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1122 goto icmap_set_error;
1123 }
1124 }
1125 break;
1127 if (strcmp(path, "totem.interface") == 0) {
1129 data->linknumber = 0;
1130 data->mcastport = -1;
1131 data->ttl = -1;
1132 data->knet_link_priority = -1;
1133 data->knet_ping_interval = -1;
1134 data->knet_ping_timeout = -1;
1135 data->knet_ping_precision = -1;
1136 data->knet_pong_count = -1;
1137 data->knet_transport = NULL;
1138 qb_list_init(&data->member_items_head);
1139 };
1140 if (strcmp(path, "totem") == 0) {
1142 };
1143 if (strcmp(path, "system") == 0) {
1145 }
1146 if (strcmp(path, "logging.logger_subsys") == 0) {
1148 qb_list_init(&data->logger_subsys_items_head);
1149 data->subsys = NULL;
1150 }
1151 if (strcmp(path, "logging.logging_daemon") == 0) {
1153 qb_list_init(&data->logger_subsys_items_head);
1154 data->subsys = NULL;
1155 data->logging_daemon_name = NULL;
1156 }
1157 if (strcmp(path, "uidgid") == 0) {
1159 }
1160 if (strcmp(path, "totem.interface.member") == 0) {
1162 }
1163 if (strcmp(path, "quorum") == 0) {
1165 }
1166 if (strcmp(path, "quorum.device") == 0) {
1168 }
1169 if (strcmp(path, "nodelist") == 0) {
1171 data->node_number = 0;
1172 }
1173 if (strcmp(path, "nodelist.node") == 0) {
1175 }
1176 if (strcmp(path, "resources") == 0) {
1178 }
1179 if (strcmp(path, "resources.system") == 0) {
1181 }
1182 if (strcmp(path, "resources.system.memory_used") == 0) {
1184 }
1185 if (strcmp(path, "resources.process") == 0) {
1187 }
1188 if (strcmp(path, "resources.process.memory_used") == 0) {
1190 }
1191 break;
1193 switch (*state) {
1195 /*
1196 * Create new interface section
1197 */
1198 if (data->bindnetaddr != NULL) {
1199 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1200 data->linknumber);
1201 cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1202
1203 free(data->bindnetaddr);
1204 data->bindnetaddr = NULL;
1205
1206 if (cs_err != CS_OK) {
1207 goto icmap_set_error;
1208 }
1209 }
1210
1211 if (data->mcastaddr != NULL) {
1212 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1213 data->linknumber);
1214 cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1215
1216 free(data->mcastaddr);
1217 data->mcastaddr = NULL;
1218
1219 if (cs_err != CS_OK) {
1220 goto icmap_set_error;
1221 }
1222 }
1223
1224 if (data->broadcast != NULL) {
1225 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1226 data->linknumber);
1227 cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1228
1229 free(data->broadcast);
1230 data->broadcast = NULL;
1231
1232 if (cs_err != CS_OK) {
1233 goto icmap_set_error;
1234 }
1235 }
1236
1237 if (data->mcastport > -1) {
1238 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1239 data->linknumber);
1240 if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1241 data->mcastport)) != CS_OK) {
1242 goto icmap_set_error;
1243 }
1244 }
1245
1246 if (data->ttl > -1) {
1247 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1248 data->linknumber);
1249 if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1250 goto icmap_set_error;
1251 }
1252 }
1253 if (data->knet_link_priority > -1) {
1254 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1255 data->linknumber);
1256 if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1257 data->knet_link_priority)) != CS_OK) {
1258 goto icmap_set_error;
1259 }
1260 }
1261 if (data->knet_ping_interval > -1) {
1262 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1263 data->linknumber);
1264 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1265 data->knet_ping_interval)) != CS_OK) {
1266 goto icmap_set_error;
1267 }
1268 }
1269 if (data->knet_ping_timeout > -1) {
1270 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1271 data->linknumber);
1272 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1273 data->knet_ping_timeout)) != CS_OK) {
1274 goto icmap_set_error;
1275 }
1276 }
1277 if (data->knet_ping_precision > -1) {
1278 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1279 data->linknumber);
1280 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1281 data->knet_ping_precision)) != CS_OK) {
1282 goto icmap_set_error;
1283 }
1284 }
1285 if (data->knet_pong_count > -1) {
1286 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1287 data->linknumber);
1288 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1289 data->knet_pong_count)) != CS_OK) {
1290 goto icmap_set_error;
1291 }
1292 }
1293 if (data->knet_transport) {
1294 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1295 data->linknumber);
1296 cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1297 free(data->knet_transport);
1298
1299 if (cs_err != CS_OK) {
1300 goto icmap_set_error;
1301 }
1302 }
1303
1304 ii = 0;
1305
1306 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1307 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1308
1309 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1310 data->linknumber, ii);
1311 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1312
1313 free(kv_item->value);
1314 free(kv_item->key);
1315 free(kv_item);
1316 ii++;
1317
1318 if (cs_err != CS_OK) {
1319 goto icmap_set_error;
1320 }
1321 }
1322
1323 break;
1325 if (data->subsys == NULL) {
1326 *error_string = "No subsys key in logger_subsys directive";
1327
1328 return (0);
1329 }
1330
1331 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1332 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1333
1334 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1335 data->subsys, kv_item->key);
1336 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1337
1338 free(kv_item->value);
1339 free(kv_item->key);
1340 free(kv_item);
1341
1342 if (cs_err != CS_OK) {
1343 goto icmap_set_error;
1344 }
1345 }
1346
1347 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1348 data->subsys);
1349 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1350
1351 free(data->subsys);
1352
1353 if (cs_err != CS_OK) {
1354 goto icmap_set_error;
1355 }
1356 break;
1358 if (data->logging_daemon_name == NULL) {
1359 *error_string = "No name key in logging_daemon directive";
1360
1361 return (0);
1362 }
1363
1364 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1365 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1366
1367 if (data->subsys == NULL) {
1368 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1369 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1370 "logging.%s",
1371 kv_item->key);
1372 } else {
1373 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1374 "logging.logging_daemon.%s.%s",
1375 data->logging_daemon_name, kv_item->key);
1376 }
1377 } else {
1378 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1379 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1380 "logging.logger_subsys.%s.%s",
1381 data->subsys,
1382 kv_item->key);
1383 } else {
1384 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1385 "logging.logging_daemon.%s.%s.%s",
1386 data->logging_daemon_name, data->subsys,
1387 kv_item->key);
1388 }
1389 }
1390 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1391
1392 free(kv_item->value);
1393 free(kv_item->key);
1394 free(kv_item);
1395
1396 if (cs_err != CS_OK) {
1397 goto icmap_set_error;
1398 }
1399 }
1400
1401 if (data->subsys == NULL) {
1402 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1403 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1404 data->logging_daemon_name);
1405 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1406 }
1407 } else {
1408 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1409 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1410 data->subsys);
1411 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1412
1413 } else {
1414 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1415 data->logging_daemon_name, data->subsys);
1416 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1417
1418 if (cs_err != CS_OK) {
1419 free(data->subsys);
1420 free(data->logging_daemon_name);
1421
1422 goto icmap_set_error;
1423 }
1424 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1425 data->logging_daemon_name, data->subsys);
1426 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1427 }
1428 }
1429
1430 free(data->subsys);
1431 free(data->logging_daemon_name);
1432
1433 if (cs_err != CS_OK) {
1434 goto icmap_set_error;
1435 }
1436 break;
1438 data->node_number++;
1439 break;
1449 break;
1452 break;
1455 break;
1458 break;
1461 break;
1464 break;
1465 }
1466 break;
1467 }
1468
1469 return (1);
1470
1471atoi_error:
1472 min_val = max_val = 0;
1473 /*
1474 * This is really assert, because developer ether doesn't set val_type correctly or
1475 * we've got here after some nasty memory overwrite
1476 */
1477 assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1478
1479 if (snprintf(formated_err, sizeof(formated_err),
1480 "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1481 key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1482 *error_string = "Can't format parser error message";
1483 } else {
1484 *error_string = formated_err;
1485 }
1486
1487 return (0);
1488
1489icmap_set_error:
1490 if (snprintf(formated_err, sizeof(formated_err),
1491 "Can't store key \"%s\" into icmap, returned error is %s",
1492 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1493 *error_string = "Can't format parser error message";
1494 } else {
1495 *error_string = formated_err;
1496 }
1497
1498 return (0);
1499}
1500
1501static int uidgid_config_parser_cb(const char *path,
1502 char *key,
1503 char *value,
1504 enum main_cp_cb_data_state *state,
1505 enum parser_cb_type type,
1506 const char **error_string,
1507 icmap_map_t config_map,
1508 void *user_data)
1509{
1510 char key_name[ICMAP_KEYNAME_MAXLEN];
1511 int uid, gid;
1512 static char formated_err[256];
1513 cs_error_t cs_err;
1514
1515 switch (type) {
1516 case PARSER_CB_START:
1517 break;
1518 case PARSER_CB_END:
1519 break;
1520 case PARSER_CB_ITEM:
1521 if (strcmp(path, "uidgid.uid") == 0) {
1522 uid = uid_determine(value);
1523 if (uid == -1) {
1524 *error_string = error_string_response;
1525 return (0);
1526 }
1527 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1528 uid);
1529 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1530 goto icmap_set_error;
1531 }
1532 } else if (strcmp(path, "uidgid.gid") == 0) {
1533 gid = gid_determine(value);
1534 if (gid == -1) {
1535 *error_string = error_string_response;
1536 return (0);
1537 }
1538 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1539 gid);
1540 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1541 goto icmap_set_error;
1542 }
1543 } else {
1544 *error_string = "uidgid: Only uid and gid are allowed items";
1545 return (0);
1546 }
1547 break;
1549 if (strcmp(path, "uidgid") != 0) {
1550 *error_string = "uidgid: Can't add subsection different than uidgid";
1551 return (0);
1552 };
1553 break;
1555 break;
1556 }
1557
1558 return (1);
1559
1560icmap_set_error:
1561 if (snprintf(formated_err, sizeof(formated_err),
1562 "Can't store key \"%s\" into icmap, returned error is %s",
1563 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1564 *error_string = "Can't format parser error message";
1565 } else {
1566 *error_string = formated_err;
1567 }
1568
1569 return (0);
1570}
1571
1572static int read_uidgid_files_into_icmap(
1573 const char **error_string,
1574 icmap_map_t config_map)
1575{
1576 FILE *fp;
1577 char *dirname_res;
1578 DIR *dp;
1579 struct dirent *dirent;
1580 char filename[PATH_MAX + FILENAME_MAX + 1];
1581 char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1582 int res = 0;
1583 struct stat stat_buf;
1585 char key_name[ICMAP_KEYNAME_MAXLEN];
1586 int line_no;
1587
1588 /*
1589 * Build uidgid directory based on corosync.conf file location
1590 */
1591 res = snprintf(filename, sizeof(filename), "%s",
1593 if (res >= sizeof(filename)) {
1594 *error_string = "uidgid.d path too long";
1595
1596 return (-1);
1597 }
1598
1599 dirname_res = dirname(filename);
1600
1601 res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1602 dirname_res, "uidgid.d");
1603 if (res >= sizeof(uidgid_dirname)) {
1604 *error_string = "uidgid.d path too long";
1605
1606 return (-1);
1607 }
1608
1609 dp = opendir (uidgid_dirname);
1610
1611 if (dp == NULL)
1612 return 0;
1613
1614 for (dirent = readdir(dp);
1615 dirent != NULL;
1616 dirent = readdir(dp)) {
1617
1618 res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1619 if (res >= sizeof(filename)) {
1620 res = -1;
1621 *error_string = "uidgid.d dirname path too long";
1622
1623 goto error_exit;
1624 }
1625 res = stat (filename, &stat_buf);
1626 if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1627
1628 fp = fopen (filename, "r");
1629 if (fp == NULL) continue;
1630
1631 key_name[0] = 0;
1632
1633 line_no = 0;
1634 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1635 uidgid_config_parser_cb, config_map, NULL);
1636
1637 fclose (fp);
1638
1639 if (res != 0) {
1640 goto error_exit;
1641 }
1642 }
1643 }
1644
1645error_exit:
1646 closedir(dp);
1647
1648 return res;
1649}
1650
1651/* Read config file and load into icmap */
1652static int read_config_file_into_icmap(
1653 const char **error_string,
1654 icmap_map_t config_map)
1655{
1656 FILE *fp;
1657 const char *filename;
1658 char *error_reason = error_string_response;
1659 int res;
1660 char key_name[ICMAP_KEYNAME_MAXLEN];
1661 struct main_cp_cb_data data;
1663 int line_no;
1664
1665 filename = corosync_get_config_file();
1666
1667 fp = fopen (filename, "r");
1668 if (fp == NULL) {
1669 char error_str[100];
1670 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1671 snprintf (error_reason, sizeof(error_string_response),
1672 "Can't read file %s: %s",
1673 filename, error_ptr);
1674 *error_string = error_reason;
1675 return -1;
1676 }
1677
1678 key_name[0] = 0;
1679
1680 line_no = 0;
1681 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1682 main_config_parser_cb, config_map, &data);
1683
1684 fclose(fp);
1685
1686 if (res == 0) {
1687 res = read_uidgid_files_into_icmap(error_string, config_map);
1688 }
1689
1690 if (res == 0) {
1691 snprintf (error_reason, sizeof(error_string_response),
1692 "Successfully read main configuration file '%s'.", filename);
1693 *error_string = error_reason;
1694 }
1695
1696 return res;
1697}
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:96
main_cp_cb_data_state
Definition: coroparse.c:75
@ MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON
Definition: coroparse.c:81
@ MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED
Definition: coroparse.c:93
@ MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED
Definition: coroparse.c:92
@ MAIN_CP_CB_DATA_STATE_MEMBER
Definition: coroparse.c:82
@ MAIN_CP_CB_DATA_STATE_UIDGID
Definition: coroparse.c:80
@ MAIN_CP_CB_DATA_STATE_INTERFACE
Definition: coroparse.c:78
@ MAIN_CP_CB_DATA_STATE_NORMAL
Definition: coroparse.c:76
@ MAIN_CP_CB_DATA_STATE_PLOAD
Definition: coroparse.c:87
@ MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS
Definition: coroparse.c:79
@ MAIN_CP_CB_DATA_STATE_TOTEM
Definition: coroparse.c:77
@ MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS
Definition: coroparse.c:91
@ MAIN_CP_CB_DATA_STATE_SYSTEM
Definition: coroparse.c:88
@ MAIN_CP_CB_DATA_STATE_QUORUM
Definition: coroparse.c:83
@ MAIN_CP_CB_DATA_STATE_QDEVICE
Definition: coroparse.c:84
@ MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM
Definition: coroparse.c:90
@ MAIN_CP_CB_DATA_STATE_NODELIST_NODE
Definition: coroparse.c:86
@ MAIN_CP_CB_DATA_STATE_RESOURCES
Definition: coroparse.c:89
@ MAIN_CP_CB_DATA_STATE_NODELIST
Definition: coroparse.c:85
int coroparse_configparse(icmap_map_t config_map, const char **error_string)
Definition: coroparse.c:259
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_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:515
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
Definition: icmap.c:527
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_STRING
Definition: icmap.h:69
@ 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:503
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
Definition: icmap.c:539
cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
Definition: icmap.c:521
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
Definition: icmap.c:557
#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:108
char * mcastaddr
Definition: coroparse.c:114
int knet_ping_precision
Definition: coroparse.c:121
unsigned int knet_mtu
Definition: coroparse.c:124
int knet_pmtud_interval
Definition: coroparse.c:123
int knet_ping_interval
Definition: coroparse.c:119
char * bindnetaddr
Definition: coroparse.c:113
struct qb_list_head logger_subsys_items_head
Definition: coroparse.c:127
char * knet_transport
Definition: coroparse.c:125
char * logging_daemon_name
Definition: coroparse.c:129
int knet_link_priority
Definition: coroparse.c:118
int knet_ping_timeout
Definition: coroparse.c:120
char * broadcast
Definition: coroparse.c:115
struct qb_list_head member_items_head
Definition: coroparse.c:130
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:213
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:279