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