corosync 3.1.9
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
74
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
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' || (unsigned char)*end_address == 0xA0)
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' || (unsigned char)*start == 0xA0)
275 start++;
276
277 end = start+(strlen(start))-1;
278 while ((*end == ' ' || *end == '\t' || (unsigned char)*end == 0xA0 || (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] == ' ' || (unsigned char)line[i] == 0xA0) {
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] != ' ' && (unsigned char)line[i] != 0xA0) {
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->key);
955 free(kv_item->value);
956 free(kv_item);
957 *error_string = "Can't alloc memory";
958
959 return (0);
960 }
961 qb_list_init(&kv_item->list);
962 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
963 }
964 add_as_string = 0;
965 break;
967 if (strcmp(key, "subsys") == 0) {
968 data->subsys = strdup(value);
969 if (data->subsys == NULL) {
970 *error_string = "Can't alloc memory";
971
972 return (0);
973 }
974 } else if (strcmp(key, "name") == 0) {
975 data->logging_daemon_name = strdup(value);
976 if (data->logging_daemon_name == NULL) {
977 *error_string = "Can't alloc memory";
978
979 return (0);
980 }
981 } else {
982 kv_item = malloc(sizeof(*kv_item));
983 if (kv_item == NULL) {
984 *error_string = "Can't alloc memory";
985
986 return (0);
987 }
988 memset(kv_item, 0, sizeof(*kv_item));
989
990 kv_item->key = strdup(key);
991 kv_item->value = strdup(value);
992 if (kv_item->key == NULL || kv_item->value == NULL) {
993 free(kv_item->key);
994 free(kv_item->value);
995 free(kv_item);
996 *error_string = "Can't alloc memory";
997
998 return (0);
999 }
1000 qb_list_init(&kv_item->list);
1001 qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
1002 }
1003 add_as_string = 0;
1004 break;
1006 if (strcmp(key, "uid") == 0) {
1007 uid = uid_determine(value);
1008 if (uid == -1) {
1009 *error_string = error_string_response;
1010 return (0);
1011 }
1012 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1013 uid);
1014 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1015 goto icmap_set_error;
1016 }
1017 add_as_string = 0;
1018 } else if (strcmp(key, "gid") == 0) {
1019 gid = gid_determine(value);
1020 if (gid == -1) {
1021 *error_string = error_string_response;
1022 return (0);
1023 }
1024 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1025 gid);
1026 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1027 goto icmap_set_error;
1028 }
1029 add_as_string = 0;
1030 } else {
1031 *error_string = "uidgid: Only uid and gid are allowed items";
1032 return (0);
1033 }
1034 break;
1036 if (strcmp(key, "memberaddr") != 0) {
1037 *error_string = "Only memberaddr is allowed in member section";
1038
1039 return (0);
1040 }
1041
1042 kv_item = malloc(sizeof(*kv_item));
1043 if (kv_item == NULL) {
1044 *error_string = "Can't alloc memory";
1045
1046 return (0);
1047 }
1048 memset(kv_item, 0, sizeof(*kv_item));
1049
1050 kv_item->key = strdup(key);
1051 kv_item->value = strdup(value);
1052 if (kv_item->key == NULL || kv_item->value == NULL) {
1053 free(kv_item->key);
1054 free(kv_item->value);
1055 free(kv_item);
1056 *error_string = "Can't alloc memory";
1057
1058 return (0);
1059 }
1060 qb_list_init(&kv_item->list);
1061 qb_list_add(&kv_item->list, &data->member_items_head);
1062 add_as_string = 0;
1063 break;
1065 break;
1067 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
1068 if ((strcmp(key, "nodeid") == 0) ||
1069 (strcmp(key, "quorum_votes") == 0)) {
1070 val_type = ICMAP_VALUETYPE_UINT32;
1071 if (safe_atoq(value, &val, val_type) != 0) {
1072 goto atoi_error;
1073 }
1074
1075 if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1076 goto icmap_set_error;
1077 }
1078 add_as_string = 0;
1079 }
1080
1081 if (add_as_string) {
1082 if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1083 goto icmap_set_error;
1084 };
1085 add_as_string = 0;
1086 }
1087 break;
1089 if (strcmp(key, "watchdog_timeout") == 0) {
1090 val_type = ICMAP_VALUETYPE_UINT32;
1091 if (safe_atoq(value, &val, val_type) != 0) {
1092 goto atoi_error;
1093 }
1094 if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1095 goto icmap_set_error;
1096 }
1097 add_as_string = 0;
1098 }
1099 break;
1102 if (strcmp(key, "poll_period") == 0) {
1103 if (str_to_ull(value, &ull) != 0) {
1104 goto atoi_error;
1105 }
1106 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1107 goto icmap_set_error;
1108 }
1109 add_as_string = 0;
1110 }
1111 break;
1114 if (strcmp(key, "poll_period") == 0) {
1115 if (str_to_ull(value, &ull) != 0) {
1116 goto atoi_error;
1117 }
1118 if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1119 goto icmap_set_error;
1120 }
1121 add_as_string = 0;
1122 }
1123 break;
1124 }
1125
1126 if (add_as_string) {
1127 if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1128 goto icmap_set_error;
1129 }
1130 }
1131 break;
1133 if (strcmp(path, "totem.interface") == 0) {
1135 data->linknumber = 0;
1136 data->mcastport = -1;
1137 data->ttl = -1;
1138 data->knet_link_priority = -1;
1139 data->knet_ping_interval = -1;
1140 data->knet_ping_timeout = -1;
1141 data->knet_ping_precision = -1;
1142 data->knet_pong_count = -1;
1143 data->knet_transport = NULL;
1144 qb_list_init(&data->member_items_head);
1145 };
1146 if (strcmp(path, "totem") == 0) {
1148 };
1149 if (strcmp(path, "system") == 0) {
1151 }
1152 if (strcmp(path, "logging.logger_subsys") == 0) {
1154 qb_list_init(&data->logger_subsys_items_head);
1155 data->subsys = NULL;
1156 }
1157 if (strcmp(path, "logging.logging_daemon") == 0) {
1159 qb_list_init(&data->logger_subsys_items_head);
1160 data->subsys = NULL;
1161 data->logging_daemon_name = NULL;
1162 }
1163 if (strcmp(path, "uidgid") == 0) {
1165 }
1166 if (strcmp(path, "totem.interface.member") == 0) {
1168 }
1169 if (strcmp(path, "quorum") == 0) {
1171 }
1172 if (strcmp(path, "quorum.device") == 0) {
1174 }
1175 if (strcmp(path, "nodelist") == 0) {
1177 data->node_number = 0;
1178 }
1179 if (strcmp(path, "nodelist.node") == 0) {
1181 }
1182 if (strcmp(path, "resources") == 0) {
1184 }
1185 if (strcmp(path, "resources.system") == 0) {
1187 }
1188 if (strcmp(path, "resources.system.memory_used") == 0) {
1190 }
1191 if (strcmp(path, "resources.process") == 0) {
1193 }
1194 if (strcmp(path, "resources.process.memory_used") == 0) {
1196 }
1197 break;
1199 switch (*state) {
1201 /*
1202 * Create new interface section
1203 */
1204 if (data->bindnetaddr != NULL) {
1205 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1206 data->linknumber);
1207 cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1208
1209 free(data->bindnetaddr);
1210 data->bindnetaddr = NULL;
1211
1212 if (cs_err != CS_OK) {
1213 goto icmap_set_error;
1214 }
1215 }
1216
1217 if (data->mcastaddr != NULL) {
1218 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1219 data->linknumber);
1220 cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1221
1222 free(data->mcastaddr);
1223 data->mcastaddr = NULL;
1224
1225 if (cs_err != CS_OK) {
1226 goto icmap_set_error;
1227 }
1228 }
1229
1230 if (data->broadcast != NULL) {
1231 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1232 data->linknumber);
1233 cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1234
1235 free(data->broadcast);
1236 data->broadcast = NULL;
1237
1238 if (cs_err != CS_OK) {
1239 goto icmap_set_error;
1240 }
1241 }
1242
1243 if (data->mcastport > -1) {
1244 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1245 data->linknumber);
1246 if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1247 data->mcastport)) != CS_OK) {
1248 goto icmap_set_error;
1249 }
1250 }
1251
1252 if (data->ttl > -1) {
1253 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1254 data->linknumber);
1255 if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1256 goto icmap_set_error;
1257 }
1258 }
1259 if (data->knet_link_priority > -1) {
1260 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1261 data->linknumber);
1262 if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1263 data->knet_link_priority)) != CS_OK) {
1264 goto icmap_set_error;
1265 }
1266 }
1267 if (data->knet_ping_interval > -1) {
1268 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1269 data->linknumber);
1270 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1271 data->knet_ping_interval)) != CS_OK) {
1272 goto icmap_set_error;
1273 }
1274 }
1275 if (data->knet_ping_timeout > -1) {
1276 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1277 data->linknumber);
1278 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1279 data->knet_ping_timeout)) != CS_OK) {
1280 goto icmap_set_error;
1281 }
1282 }
1283 if (data->knet_ping_precision > -1) {
1284 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1285 data->linknumber);
1286 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1287 data->knet_ping_precision)) != CS_OK) {
1288 goto icmap_set_error;
1289 }
1290 }
1291 if (data->knet_pong_count > -1) {
1292 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1293 data->linknumber);
1294 if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1295 data->knet_pong_count)) != CS_OK) {
1296 goto icmap_set_error;
1297 }
1298 }
1299 if (data->knet_transport) {
1300 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1301 data->linknumber);
1302 cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1303 free(data->knet_transport);
1304
1305 if (cs_err != CS_OK) {
1306 goto icmap_set_error;
1307 }
1308 }
1309
1310 ii = 0;
1311
1312 qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1313 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1314
1315 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1316 data->linknumber, ii);
1317 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1318
1319 free(kv_item->value);
1320 free(kv_item->key);
1321 free(kv_item);
1322 ii++;
1323
1324 if (cs_err != CS_OK) {
1325 goto icmap_set_error;
1326 }
1327 }
1328
1329 break;
1331 if (data->subsys == NULL) {
1332 *error_string = "No subsys key in logger_subsys directive";
1333
1334 return (0);
1335 }
1336
1337 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1338 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1339
1340 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1341 data->subsys, kv_item->key);
1342 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1343
1344 free(kv_item->value);
1345 free(kv_item->key);
1346 free(kv_item);
1347
1348 if (cs_err != CS_OK) {
1349 goto icmap_set_error;
1350 }
1351 }
1352
1353 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1354 data->subsys);
1355 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1356
1357 free(data->subsys);
1358
1359 if (cs_err != CS_OK) {
1360 goto icmap_set_error;
1361 }
1362 break;
1364 if (data->logging_daemon_name == NULL) {
1365 *error_string = "No name key in logging_daemon directive";
1366
1367 return (0);
1368 }
1369
1370 qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1371 kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1372
1373 if (data->subsys == NULL) {
1374 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1375 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1376 "logging.%s",
1377 kv_item->key);
1378 } else {
1379 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1380 "logging.logging_daemon.%s.%s",
1381 data->logging_daemon_name, kv_item->key);
1382 }
1383 } else {
1384 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1385 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1386 "logging.logger_subsys.%s.%s",
1387 data->subsys,
1388 kv_item->key);
1389 } else {
1390 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1391 "logging.logging_daemon.%s.%s.%s",
1392 data->logging_daemon_name, data->subsys,
1393 kv_item->key);
1394 }
1395 }
1396 cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1397
1398 free(kv_item->value);
1399 free(kv_item->key);
1400 free(kv_item);
1401
1402 if (cs_err != CS_OK) {
1403 goto icmap_set_error;
1404 }
1405 }
1406
1407 if (data->subsys == NULL) {
1408 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1409 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1410 data->logging_daemon_name);
1411 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1412 }
1413 } else {
1414 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1415 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1416 data->subsys);
1417 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1418
1419 } else {
1420 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1421 data->logging_daemon_name, data->subsys);
1422 cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1423
1424 if (cs_err != CS_OK) {
1425 free(data->subsys);
1426 free(data->logging_daemon_name);
1427
1428 goto icmap_set_error;
1429 }
1430 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1431 data->logging_daemon_name, data->subsys);
1432 cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1433 }
1434 }
1435
1436 free(data->subsys);
1437 free(data->logging_daemon_name);
1438
1439 if (cs_err != CS_OK) {
1440 goto icmap_set_error;
1441 }
1442 break;
1444 data->node_number++;
1445 break;
1455 break;
1458 break;
1461 break;
1464 break;
1467 break;
1470 break;
1471 }
1472 break;
1473 }
1474
1475 return (1);
1476
1477atoi_error:
1478 min_val = max_val = 0;
1479 /*
1480 * This is really assert, because developer ether doesn't set val_type correctly or
1481 * we've got here after some nasty memory overwrite
1482 */
1483 assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1484
1485 if (snprintf(formated_err, sizeof(formated_err),
1486 "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1487 key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1488 *error_string = "Can't format parser error message";
1489 } else {
1490 *error_string = formated_err;
1491 }
1492
1493 return (0);
1494
1495icmap_set_error:
1496 if (snprintf(formated_err, sizeof(formated_err),
1497 "Can't store key \"%s\" into icmap, returned error is %s",
1498 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1499 *error_string = "Can't format parser error message";
1500 } else {
1501 *error_string = formated_err;
1502 }
1503
1504 return (0);
1505}
1506
1507static int uidgid_config_parser_cb(const char *path,
1508 char *key,
1509 char *value,
1510 enum main_cp_cb_data_state *state,
1511 enum parser_cb_type type,
1512 const char **error_string,
1513 icmap_map_t config_map,
1514 void *user_data)
1515{
1516 char key_name[ICMAP_KEYNAME_MAXLEN];
1517 int uid, gid;
1518 static char formated_err[256];
1519 cs_error_t cs_err;
1520
1521 switch (type) {
1522 case PARSER_CB_START:
1523 break;
1524 case PARSER_CB_END:
1525 break;
1526 case PARSER_CB_ITEM:
1527 if (strcmp(path, "uidgid.uid") == 0) {
1528 uid = uid_determine(value);
1529 if (uid == -1) {
1530 *error_string = error_string_response;
1531 return (0);
1532 }
1533 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1534 uid);
1535 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1536 goto icmap_set_error;
1537 }
1538 } else if (strcmp(path, "uidgid.gid") == 0) {
1539 gid = gid_determine(value);
1540 if (gid == -1) {
1541 *error_string = error_string_response;
1542 return (0);
1543 }
1544 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1545 gid);
1546 if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1547 goto icmap_set_error;
1548 }
1549 } else {
1550 *error_string = "uidgid: Only uid and gid are allowed items";
1551 return (0);
1552 }
1553 break;
1555 if (strcmp(path, "uidgid") != 0) {
1556 *error_string = "uidgid: Can't add subsection different than uidgid";
1557 return (0);
1558 };
1559 break;
1561 break;
1562 }
1563
1564 return (1);
1565
1566icmap_set_error:
1567 if (snprintf(formated_err, sizeof(formated_err),
1568 "Can't store key \"%s\" into icmap, returned error is %s",
1569 key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1570 *error_string = "Can't format parser error message";
1571 } else {
1572 *error_string = formated_err;
1573 }
1574
1575 return (0);
1576}
1577
1578static int read_uidgid_files_into_icmap(
1579 const char **error_string,
1580 icmap_map_t config_map)
1581{
1582 FILE *fp;
1583 char *dirname_res;
1584 DIR *dp;
1585 struct dirent *dirent;
1586 char filename[PATH_MAX + FILENAME_MAX + 1];
1587 char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1588 int res = 0;
1589 struct stat stat_buf;
1591 char key_name[ICMAP_KEYNAME_MAXLEN];
1592 int line_no;
1593
1594 /*
1595 * Build uidgid directory based on corosync.conf file location
1596 */
1597 res = snprintf(filename, sizeof(filename), "%s",
1599 if (res >= sizeof(filename)) {
1600 *error_string = "uidgid.d path too long";
1601
1602 return (-1);
1603 }
1604
1605 dirname_res = dirname(filename);
1606
1607 res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1608 dirname_res, "uidgid.d");
1609 if (res >= sizeof(uidgid_dirname)) {
1610 *error_string = "uidgid.d path too long";
1611
1612 return (-1);
1613 }
1614
1615 dp = opendir (uidgid_dirname);
1616
1617 if (dp == NULL)
1618 return 0;
1619
1620 for (dirent = readdir(dp);
1621 dirent != NULL;
1622 dirent = readdir(dp)) {
1623
1624 res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1625 if (res >= sizeof(filename)) {
1626 res = -1;
1627 *error_string = "uidgid.d dirname path too long";
1628
1629 goto error_exit;
1630 }
1631 res = stat (filename, &stat_buf);
1632 if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1633
1634 fp = fopen (filename, "r");
1635 if (fp == NULL) continue;
1636
1637 key_name[0] = 0;
1638
1639 line_no = 0;
1640 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1641 uidgid_config_parser_cb, config_map, NULL);
1642
1643 fclose (fp);
1644
1645 if (res != 0) {
1646 goto error_exit;
1647 }
1648 }
1649 }
1650
1651error_exit:
1652 closedir(dp);
1653
1654 return res;
1655}
1656
1657/* Read config file and load into icmap */
1658static int read_config_file_into_icmap(
1659 const char **error_string,
1660 icmap_map_t config_map)
1661{
1662 FILE *fp;
1663 const char *filename;
1664 char *error_reason = error_string_response;
1665 int res;
1666 char key_name[ICMAP_KEYNAME_MAXLEN];
1667 struct main_cp_cb_data data;
1669 int line_no;
1670
1671 filename = corosync_get_config_file();
1672
1673 fp = fopen (filename, "r");
1674 if (fp == NULL) {
1675 char error_str[100];
1676 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1677 snprintf (error_reason, sizeof(error_string_response),
1678 "Can't read file %s: %s",
1679 filename, error_ptr);
1680 *error_string = error_reason;
1681 return -1;
1682 }
1683
1684 key_name[0] = 0;
1685
1686 line_no = 0;
1687 res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1688 main_config_parser_cb, config_map, &data);
1689
1690 fclose(fp);
1691
1692 if (res == 0) {
1693 res = read_uidgid_files_into_icmap(error_string, config_map);
1694 }
1695
1696 if (res == 0) {
1697 snprintf (error_reason, sizeof(error_string_response),
1698 "Successfully read main configuration file '%s'.", filename);
1699 *error_string = error_reason;
1700 }
1701
1702 return res;
1703}
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: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_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: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:108
int knet_ping_precision
Definition coroparse.c:121
unsigned int knet_mtu
Definition coroparse.c:124
int knet_pmtud_interval
Definition coroparse.c:123
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
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