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