corosync  3.1.6
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 
96 typedef 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 
113  char *bindnetaddr;
114  char *mcastaddr;
115  char *broadcast;
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 
134 static int read_config_file_into_icmap(
135  const char **error_string, icmap_map_t config_map);
136 static char error_string_response[512];
137 
138 static 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 
192 static 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 }
245 static 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 
258 int 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 
267 static 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 
287 static 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 
469 parse_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 
480 static 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  */
501 static 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 
534 static 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 
558 static 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 
569 static 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 
580 static 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) {
1139  *state = MAIN_CP_CB_DATA_STATE_TOTEM;
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;
1190  case PARSER_CB_SECTION_END:
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 
1469 atoi_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 
1487 icmap_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 
1499 static 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;
1552  case PARSER_CB_SECTION_END:
1553  break;
1554  }
1555 
1556  return (1);
1557 
1558 icmap_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 
1570 static 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 
1643 error_exit:
1644  closedir(dp);
1645 
1646  return res;
1647 }
1648 
1649 /* Read config file and load into icmap */
1650 static 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
char * mcastaddr
Definition: coroparse.c:114
int knet_ping_precision
Definition: coroparse.c:121
int knet_pmtud_interval
Definition: coroparse.c:123
int knet_ping_interval
Definition: coroparse.c:119
char * bindnetaddr
Definition: coroparse.c:113
struct qb_list_head logger_subsys_items_head
Definition: coroparse.c:126
char * knet_transport
Definition: coroparse.c:124
char * logging_daemon_name
Definition: coroparse.c:128
int knet_link_priority
Definition: coroparse.c:118
int knet_ping_timeout
Definition: coroparse.c:120
char * broadcast
Definition: coroparse.c:115
struct qb_list_head member_items_head
Definition: coroparse.c: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