corosync  3.1.2
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 main_config_parser_cb(const char *path,
559  char *key,
560  char *value,
561  enum main_cp_cb_data_state *state,
562  enum parser_cb_type type,
563  const char **error_string,
564  icmap_map_t config_map,
565  void *user_data)
566 {
567  int ii;
568  long long int val;
569  long long int min_val, max_val;
571  unsigned long long int ull;
572  int add_as_string;
573  char key_name[ICMAP_KEYNAME_MAXLEN + 1];
574  static char formated_err[256];
575  struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
576  struct key_value_list_item *kv_item;
577  struct qb_list_head *iter, *tmp_iter;
578  int uid, gid;
579  cs_error_t cs_err;
580 
581  cs_err = CS_OK;
582 
583  /*
584  * Formally this check is not needed because length is checked by parse_section
585  */
586  if (strlen(path) >= sizeof(key_name)) {
587  if (snprintf(formated_err, sizeof(formated_err),
588  "Can't store path \"%s\" into key_name", path) >= sizeof(formated_err)) {
589  *error_string = "Can't format path into key_name error message";
590  } else {
591  *error_string = formated_err;
592  }
593  return (0);
594  }
595  /*
596  * Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
597  * are using path, so initialize key_name to valid value
598  */
599  strncpy(key_name, path, sizeof(key_name) - 1);
600 
601  switch (type) {
602  case PARSER_CB_START:
603  memset(data, 0, sizeof(struct main_cp_cb_data));
605  break;
606  case PARSER_CB_END:
607  break;
608  case PARSER_CB_ITEM:
609  add_as_string = 1;
610 
611  switch (*state) {
613  break;
615  if ((strcmp(path, "pload.count") == 0) ||
616  (strcmp(path, "pload.size") == 0)) {
617  val_type = ICMAP_VALUETYPE_UINT32;
618  if (safe_atoq(value, &val, val_type) != 0) {
619  goto atoi_error;
620  }
621  if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
622  goto icmap_set_error;
623  }
624  add_as_string = 0;
625  }
626  break;
628  if ((strcmp(path, "quorum.expected_votes") == 0) ||
629  (strcmp(path, "quorum.votes") == 0) ||
630  (strcmp(path, "quorum.last_man_standing_window") == 0) ||
631  (strcmp(path, "quorum.leaving_timeout") == 0)) {
632  val_type = ICMAP_VALUETYPE_UINT32;
633  if (safe_atoq(value, &val, val_type) != 0) {
634  goto atoi_error;
635  }
636  if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
637  goto icmap_set_error;
638  }
639  add_as_string = 0;
640  }
641 
642  if ((strcmp(path, "quorum.two_node") == 0) ||
643  (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
644  (strcmp(path, "quorum.allow_downscale") == 0) ||
645  (strcmp(path, "quorum.wait_for_all") == 0) ||
646  (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
647  (strcmp(path, "quorum.last_man_standing") == 0)) {
648  val_type = ICMAP_VALUETYPE_UINT8;
649  if (safe_atoq(value, &val, val_type) != 0) {
650  goto atoi_error;
651  }
652  if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
653  goto icmap_set_error;
654  }
655  add_as_string = 0;
656  }
657  break;
659  if ((strcmp(path, "quorum.device.timeout") == 0) ||
660  (strcmp(path, "quorum.device.sync_timeout") == 0) ||
661  (strcmp(path, "quorum.device.votes") == 0)) {
662  val_type = ICMAP_VALUETYPE_UINT32;
663  if (safe_atoq(value, &val, val_type) != 0) {
664  goto atoi_error;
665  }
666  if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
667  goto icmap_set_error;
668  }
669  add_as_string = 0;
670  }
671  if ((strcmp(path, "quorum.device.master_wins") == 0)) {
672  val_type = ICMAP_VALUETYPE_UINT8;
673  if (safe_atoq(value, &val, val_type) != 0) {
674  goto atoi_error;
675  }
676  if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
677  goto icmap_set_error;
678  }
679  add_as_string = 0;
680  }
681  break;
683  if ((strcmp(path, "totem.version") == 0) ||
684  (strcmp(path, "totem.nodeid") == 0) ||
685  (strcmp(path, "totem.threads") == 0) ||
686  (strcmp(path, "totem.token") == 0) ||
687  (strcmp(path, "totem.token_coefficient") == 0) ||
688  (strcmp(path, "totem.token_retransmit") == 0) ||
689  (strcmp(path, "totem.token_warning") == 0) ||
690  (strcmp(path, "totem.hold") == 0) ||
691  (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
692  (strcmp(path, "totem.join") == 0) ||
693  (strcmp(path, "totem.send_join") == 0) ||
694  (strcmp(path, "totem.consensus") == 0) ||
695  (strcmp(path, "totem.merge") == 0) ||
696  (strcmp(path, "totem.downcheck") == 0) ||
697  (strcmp(path, "totem.fail_recv_const") == 0) ||
698  (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
699  (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
700  (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
701  (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
702  (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
703  (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
704  (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
705  (strcmp(path, "totem.max_network_delay") == 0) ||
706  (strcmp(path, "totem.window_size") == 0) ||
707  (strcmp(path, "totem.max_messages") == 0) ||
708  (strcmp(path, "totem.miss_count_const") == 0) ||
709  (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
710  (strcmp(path, "totem.knet_compression_threshold") == 0) ||
711  (strcmp(path, "totem.netmtu") == 0)) {
712  val_type = ICMAP_VALUETYPE_UINT32;
713  if (safe_atoq(value, &val, val_type) != 0) {
714  goto atoi_error;
715  }
716  if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
717  goto icmap_set_error;
718  }
719  add_as_string = 0;
720  }
721  if (strcmp(path, "totem.knet_compression_level") == 0) {
722  val_type = ICMAP_VALUETYPE_INT32;
723  if (safe_atoq(value, &val, val_type) != 0) {
724  goto atoi_error;
725  }
726  if ((cs_err = icmap_set_int32_r(config_map, path, val)) != CS_OK) {
727  goto icmap_set_error;
728  }
729  add_as_string = 0;
730  }
731  if (strcmp(path, "totem.config_version") == 0) {
732  if (str_to_ull(value, &ull) != 0) {
733  goto atoi_error;
734  }
735  if ((cs_err = icmap_set_uint64_r(config_map, path, ull)) != CS_OK) {
736  goto icmap_set_error;
737  }
738  add_as_string = 0;
739  }
740  if (strcmp(path, "totem.ip_version") == 0) {
741  if ((strcmp(value, "ipv4") != 0) &&
742  (strcmp(value, "ipv6") != 0) &&
743  (strcmp(value, "ipv6-4") != 0) &&
744  (strcmp(value, "ipv4-6") != 0)) {
745  *error_string = "Invalid ip_version type";
746 
747  return (0);
748  }
749  }
750  if (strcmp(path, "totem.crypto_model") == 0) {
751  if ((strcmp(value, "nss") != 0) &&
752  (strcmp(value, "openssl") != 0)) {
753  *error_string = "Invalid crypto model. "
754  "Should be nss or openssl";
755 
756  return (0);
757  }
758  }
759  if (strcmp(path, "totem.crypto_cipher") == 0) {
760  if ((strcmp(value, "none") != 0) &&
761  (strcmp(value, "aes256") != 0) &&
762  (strcmp(value, "aes192") != 0) &&
763  (strcmp(value, "aes128") != 0)) {
764  *error_string = "Invalid cipher type. "
765  "Should be none, aes256, aes192 or aes128";
766 
767  return (0);
768  }
769  }
770  if (strcmp(path, "totem.crypto_hash") == 0) {
771  if ((strcmp(value, "none") != 0) &&
772  (strcmp(value, "md5") != 0) &&
773  (strcmp(value, "sha1") != 0) &&
774  (strcmp(value, "sha256") != 0) &&
775  (strcmp(value, "sha384") != 0) &&
776  (strcmp(value, "sha512") != 0)) {
777  *error_string = "Invalid hash type. "
778  "Should be none, md5, sha1, sha256, sha384 or sha512";
779 
780  return (0);
781  }
782  }
783  break;
784 
786  if (strcmp(path, "system.qb_ipc_type") == 0) {
787  if ((strcmp(value, "native") != 0) &&
788  (strcmp(value, "shm") != 0) &&
789  (strcmp(value, "socket") != 0)) {
790  *error_string = "Invalid system.qb_ipc_type";
791 
792  return (0);
793  }
794  }
795  if (strcmp(path, "system.sched_rr") == 0) {
796  if ((strcmp(value, "yes") != 0) &&
797  (strcmp(value, "no") != 0)) {
798  *error_string = "Invalid system.sched_rr value";
799 
800  return (0);
801  }
802  }
803  if (strcmp(path, "system.move_to_root_cgroup") == 0) {
804  if ((strcmp(value, "yes") != 0) &&
805  (strcmp(value, "no") != 0)) {
806  *error_string = "Invalid system.move_to_root_cgroup";
807 
808  return (0);
809  }
810  }
811  if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
812  if ((strcmp(value, "yes") != 0) &&
813  (strcmp(value, "no") != 0)) {
814  *error_string = "Invalid system.allow_knet_handle_fallback";
815 
816  return (0);
817  }
818  }
819  break;
820 
822  if (strcmp(path, "totem.interface.linknumber") == 0) {
823  val_type = ICMAP_VALUETYPE_UINT8;
824  if (safe_atoq(value, &val, val_type) != 0) {
825  goto atoi_error;
826  }
827 
828  data->linknumber = val;
829  add_as_string = 0;
830  }
831  if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
832  data->bindnetaddr = strdup(value);
833  add_as_string = 0;
834  }
835  if (strcmp(path, "totem.interface.mcastaddr") == 0) {
836  data->mcastaddr = strdup(value);
837  add_as_string = 0;
838  }
839  if (strcmp(path, "totem.interface.broadcast") == 0) {
840  data->broadcast = strdup(value);
841  add_as_string = 0;
842  }
843  if (strcmp(path, "totem.interface.mcastport") == 0) {
844  val_type = ICMAP_VALUETYPE_UINT16;
845  if (safe_atoq(value, &val, val_type) != 0) {
846  goto atoi_error;
847  }
848  data->mcastport = val;
849  add_as_string = 0;
850  }
851  if (strcmp(path, "totem.interface.ttl") == 0) {
852  val_type = ICMAP_VALUETYPE_UINT8;
853  if (safe_atoq(value, &val, val_type) != 0) {
854  goto atoi_error;
855  }
856  data->ttl = val;
857  add_as_string = 0;
858  }
859  if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
860  val_type = ICMAP_VALUETYPE_UINT8;
861  if (safe_atoq(value, &val, val_type) != 0) {
862  goto atoi_error;
863  }
864  data->knet_link_priority = val;
865  add_as_string = 0;
866  }
867  if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
868  val_type = ICMAP_VALUETYPE_UINT32;
869  if (safe_atoq(value, &val, val_type) != 0) {
870  goto atoi_error;
871  }
872  data->knet_ping_interval = val;
873  add_as_string = 0;
874  }
875  if (strcmp(path, "totem.interface.knet_ping_timeout") == 0) {
876  val_type = ICMAP_VALUETYPE_UINT32;
877  if (safe_atoq(value, &val, val_type) != 0) {
878  goto atoi_error;
879  }
880  data->knet_ping_timeout = val;
881  add_as_string = 0;
882  }
883  if (strcmp(path, "totem.interface.knet_ping_precision") == 0) {
884  val_type = ICMAP_VALUETYPE_UINT32;
885  if (safe_atoq(value, &val, val_type) != 0) {
886  goto atoi_error;
887  }
888  data->knet_ping_precision = val;
889  add_as_string = 0;
890  }
891  if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
892  val_type = ICMAP_VALUETYPE_UINT32;
893  if (safe_atoq(value, &val, val_type) != 0) {
894  goto atoi_error;
895  }
896  data->knet_pong_count = val;
897  add_as_string = 0;
898  }
899  if (strcmp(path, "totem.interface.knet_transport") == 0) {
900  val_type = ICMAP_VALUETYPE_STRING;
901  data->knet_transport = strdup(value);
902  add_as_string = 0;
903  }
904  break;
906  if (strcmp(key, "subsys") == 0) {
907  data->subsys = strdup(value);
908  if (data->subsys == NULL) {
909  *error_string = "Can't alloc memory";
910 
911  return (0);
912  }
913  } else {
914  kv_item = malloc(sizeof(*kv_item));
915  if (kv_item == NULL) {
916  *error_string = "Can't alloc memory";
917 
918  return (0);
919  }
920  memset(kv_item, 0, sizeof(*kv_item));
921 
922  kv_item->key = strdup(key);
923  kv_item->value = strdup(value);
924  if (kv_item->key == NULL || kv_item->value == NULL) {
925  free(kv_item);
926  *error_string = "Can't alloc memory";
927 
928  return (0);
929  }
930  qb_list_init(&kv_item->list);
931  qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
932  }
933  add_as_string = 0;
934  break;
936  if (strcmp(key, "subsys") == 0) {
937  data->subsys = strdup(value);
938  if (data->subsys == NULL) {
939  *error_string = "Can't alloc memory";
940 
941  return (0);
942  }
943  } else if (strcmp(key, "name") == 0) {
944  data->logging_daemon_name = strdup(value);
945  if (data->logging_daemon_name == NULL) {
946  *error_string = "Can't alloc memory";
947 
948  return (0);
949  }
950  } else {
951  kv_item = malloc(sizeof(*kv_item));
952  if (kv_item == NULL) {
953  *error_string = "Can't alloc memory";
954 
955  return (0);
956  }
957  memset(kv_item, 0, sizeof(*kv_item));
958 
959  kv_item->key = strdup(key);
960  kv_item->value = strdup(value);
961  if (kv_item->key == NULL || kv_item->value == NULL) {
962  free(kv_item);
963  *error_string = "Can't alloc memory";
964 
965  return (0);
966  }
967  qb_list_init(&kv_item->list);
968  qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
969  }
970  add_as_string = 0;
971  break;
973  if (strcmp(key, "uid") == 0) {
974  uid = uid_determine(value);
975  if (uid == -1) {
976  *error_string = error_string_response;
977  return (0);
978  }
979  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
980  uid);
981  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
982  goto icmap_set_error;
983  }
984  add_as_string = 0;
985  } else if (strcmp(key, "gid") == 0) {
986  gid = gid_determine(value);
987  if (gid == -1) {
988  *error_string = error_string_response;
989  return (0);
990  }
991  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
992  gid);
993  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
994  goto icmap_set_error;
995  }
996  add_as_string = 0;
997  } else {
998  *error_string = "uidgid: Only uid and gid are allowed items";
999  return (0);
1000  }
1001  break;
1003  if (strcmp(key, "memberaddr") != 0) {
1004  *error_string = "Only memberaddr is allowed in member section";
1005 
1006  return (0);
1007  }
1008 
1009  kv_item = malloc(sizeof(*kv_item));
1010  if (kv_item == NULL) {
1011  *error_string = "Can't alloc memory";
1012 
1013  return (0);
1014  }
1015  memset(kv_item, 0, sizeof(*kv_item));
1016 
1017  kv_item->key = strdup(key);
1018  kv_item->value = strdup(value);
1019  if (kv_item->key == NULL || kv_item->value == NULL) {
1020  free(kv_item);
1021  *error_string = "Can't alloc memory";
1022 
1023  return (0);
1024  }
1025  qb_list_init(&kv_item->list);
1026  qb_list_add(&kv_item->list, &data->member_items_head);
1027  add_as_string = 0;
1028  break;
1030  break;
1032  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
1033  if ((strcmp(key, "nodeid") == 0) ||
1034  (strcmp(key, "quorum_votes") == 0)) {
1035  val_type = ICMAP_VALUETYPE_UINT32;
1036  if (safe_atoq(value, &val, val_type) != 0) {
1037  goto atoi_error;
1038  }
1039 
1040  if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1041  goto icmap_set_error;
1042  }
1043  add_as_string = 0;
1044  }
1045 
1046  if (add_as_string) {
1047  if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1048  goto icmap_set_error;
1049  };
1050  add_as_string = 0;
1051  }
1052  break;
1054  if (strcmp(key, "watchdog_timeout") == 0) {
1055  val_type = ICMAP_VALUETYPE_UINT32;
1056  if (safe_atoq(value, &val, val_type) != 0) {
1057  goto atoi_error;
1058  }
1059  if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1060  goto icmap_set_error;
1061  }
1062  add_as_string = 0;
1063  }
1064  break;
1067  if (strcmp(key, "poll_period") == 0) {
1068  if (str_to_ull(value, &ull) != 0) {
1069  goto atoi_error;
1070  }
1071  if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1072  goto icmap_set_error;
1073  }
1074  add_as_string = 0;
1075  }
1076  break;
1079  if (strcmp(key, "poll_period") == 0) {
1080  if (str_to_ull(value, &ull) != 0) {
1081  goto atoi_error;
1082  }
1083  if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1084  goto icmap_set_error;
1085  }
1086  add_as_string = 0;
1087  }
1088  break;
1089  }
1090 
1091  if (add_as_string) {
1092  if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1093  goto icmap_set_error;
1094  }
1095  }
1096  break;
1098  if (strcmp(path, "totem.interface") == 0) {
1100  data->linknumber = 0;
1101  data->mcastport = -1;
1102  data->ttl = -1;
1103  data->knet_link_priority = -1;
1104  data->knet_ping_interval = -1;
1105  data->knet_ping_timeout = -1;
1106  data->knet_ping_precision = -1;
1107  data->knet_pong_count = -1;
1108  data->knet_transport = NULL;
1109  qb_list_init(&data->member_items_head);
1110  };
1111  if (strcmp(path, "totem") == 0) {
1112  *state = MAIN_CP_CB_DATA_STATE_TOTEM;
1113  };
1114  if (strcmp(path, "system") == 0) {
1116  }
1117  if (strcmp(path, "logging.logger_subsys") == 0) {
1119  qb_list_init(&data->logger_subsys_items_head);
1120  data->subsys = NULL;
1121  }
1122  if (strcmp(path, "logging.logging_daemon") == 0) {
1124  qb_list_init(&data->logger_subsys_items_head);
1125  data->subsys = NULL;
1126  data->logging_daemon_name = NULL;
1127  }
1128  if (strcmp(path, "uidgid") == 0) {
1130  }
1131  if (strcmp(path, "totem.interface.member") == 0) {
1133  }
1134  if (strcmp(path, "quorum") == 0) {
1136  }
1137  if (strcmp(path, "quorum.device") == 0) {
1139  }
1140  if (strcmp(path, "nodelist") == 0) {
1142  data->node_number = 0;
1143  }
1144  if (strcmp(path, "nodelist.node") == 0) {
1146  }
1147  if (strcmp(path, "resources") == 0) {
1149  }
1150  if (strcmp(path, "resources.system") == 0) {
1152  }
1153  if (strcmp(path, "resources.system.memory_used") == 0) {
1155  }
1156  if (strcmp(path, "resources.process") == 0) {
1158  }
1159  if (strcmp(path, "resources.process.memory_used") == 0) {
1161  }
1162  break;
1163  case PARSER_CB_SECTION_END:
1164  switch (*state) {
1166  /*
1167  * Create new interface section
1168  */
1169  if (data->bindnetaddr != NULL) {
1170  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1171  data->linknumber);
1172  cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1173 
1174  free(data->bindnetaddr);
1175  data->bindnetaddr = NULL;
1176 
1177  if (cs_err != CS_OK) {
1178  goto icmap_set_error;
1179  }
1180  }
1181 
1182  if (data->mcastaddr != NULL) {
1183  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1184  data->linknumber);
1185  cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1186 
1187  free(data->mcastaddr);
1188  data->mcastaddr = NULL;
1189 
1190  if (cs_err != CS_OK) {
1191  goto icmap_set_error;
1192  }
1193  }
1194 
1195  if (data->broadcast != NULL) {
1196  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1197  data->linknumber);
1198  cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1199 
1200  free(data->broadcast);
1201  data->broadcast = NULL;
1202 
1203  if (cs_err != CS_OK) {
1204  goto icmap_set_error;
1205  }
1206  }
1207 
1208  if (data->mcastport > -1) {
1209  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1210  data->linknumber);
1211  if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1212  data->mcastport)) != CS_OK) {
1213  goto icmap_set_error;
1214  }
1215  }
1216 
1217  if (data->ttl > -1) {
1218  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1219  data->linknumber);
1220  if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1221  goto icmap_set_error;
1222  }
1223  }
1224  if (data->knet_link_priority > -1) {
1225  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1226  data->linknumber);
1227  if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1228  data->knet_link_priority)) != CS_OK) {
1229  goto icmap_set_error;
1230  }
1231  }
1232  if (data->knet_ping_interval > -1) {
1233  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1234  data->linknumber);
1235  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1236  data->knet_ping_interval)) != CS_OK) {
1237  goto icmap_set_error;
1238  }
1239  }
1240  if (data->knet_ping_timeout > -1) {
1241  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1242  data->linknumber);
1243  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1244  data->knet_ping_timeout)) != CS_OK) {
1245  goto icmap_set_error;
1246  }
1247  }
1248  if (data->knet_ping_precision > -1) {
1249  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1250  data->linknumber);
1251  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1252  data->knet_ping_precision)) != CS_OK) {
1253  goto icmap_set_error;
1254  }
1255  }
1256  if (data->knet_pong_count > -1) {
1257  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1258  data->linknumber);
1259  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1260  data->knet_pong_count)) != CS_OK) {
1261  goto icmap_set_error;
1262  }
1263  }
1264  if (data->knet_transport) {
1265  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1266  data->linknumber);
1267  cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1268  free(data->knet_transport);
1269 
1270  if (cs_err != CS_OK) {
1271  goto icmap_set_error;
1272  }
1273  }
1274 
1275  ii = 0;
1276 
1277  qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1278  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1279 
1280  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1281  data->linknumber, ii);
1282  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1283 
1284  free(kv_item->value);
1285  free(kv_item->key);
1286  free(kv_item);
1287  ii++;
1288 
1289  if (cs_err != CS_OK) {
1290  goto icmap_set_error;
1291  }
1292  }
1293 
1294  break;
1296  if (data->subsys == NULL) {
1297  *error_string = "No subsys key in logger_subsys directive";
1298 
1299  return (0);
1300  }
1301 
1302  qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1303  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1304 
1305  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1306  data->subsys, kv_item->key);
1307  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1308 
1309  free(kv_item->value);
1310  free(kv_item->key);
1311  free(kv_item);
1312 
1313  if (cs_err != CS_OK) {
1314  goto icmap_set_error;
1315  }
1316  }
1317 
1318  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1319  data->subsys);
1320  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1321 
1322  free(data->subsys);
1323 
1324  if (cs_err != CS_OK) {
1325  goto icmap_set_error;
1326  }
1327  break;
1329  if (data->logging_daemon_name == NULL) {
1330  *error_string = "No name key in logging_daemon directive";
1331 
1332  return (0);
1333  }
1334 
1335  qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1336  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1337 
1338  if (data->subsys == NULL) {
1339  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1340  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1341  "logging.%s",
1342  kv_item->key);
1343  } else {
1344  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1345  "logging.logging_daemon.%s.%s",
1346  data->logging_daemon_name, kv_item->key);
1347  }
1348  } else {
1349  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1350  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1351  "logging.logger_subsys.%s.%s",
1352  data->subsys,
1353  kv_item->key);
1354  } else {
1355  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1356  "logging.logging_daemon.%s.%s.%s",
1357  data->logging_daemon_name, data->subsys,
1358  kv_item->key);
1359  }
1360  }
1361  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1362 
1363  free(kv_item->value);
1364  free(kv_item->key);
1365  free(kv_item);
1366 
1367  if (cs_err != CS_OK) {
1368  goto icmap_set_error;
1369  }
1370  }
1371 
1372  if (data->subsys == NULL) {
1373  if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1374  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1375  data->logging_daemon_name);
1376  cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1377  }
1378  } else {
1379  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1380  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1381  data->subsys);
1382  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1383 
1384  } else {
1385  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1386  data->logging_daemon_name, data->subsys);
1387  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1388 
1389  if (cs_err != CS_OK) {
1390  free(data->subsys);
1391  free(data->logging_daemon_name);
1392 
1393  goto icmap_set_error;
1394  }
1395  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1396  data->logging_daemon_name, data->subsys);
1397  cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1398  }
1399  }
1400 
1401  free(data->subsys);
1402  free(data->logging_daemon_name);
1403 
1404  if (cs_err != CS_OK) {
1405  goto icmap_set_error;
1406  }
1407  break;
1409  data->node_number++;
1410  break;
1420  break;
1423  break;
1426  break;
1429  break;
1432  break;
1435  break;
1436  }
1437  break;
1438  }
1439 
1440  return (1);
1441 
1442 atoi_error:
1443  min_val = max_val = 0;
1444  /*
1445  * This is really assert, because developer ether doesn't set val_type correctly or
1446  * we've got here after some nasty memory overwrite
1447  */
1448  assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1449 
1450  if (snprintf(formated_err, sizeof(formated_err),
1451  "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1452  key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1453  *error_string = "Can't format parser error message";
1454  } else {
1455  *error_string = formated_err;
1456  }
1457 
1458  return (0);
1459 
1460 icmap_set_error:
1461  if (snprintf(formated_err, sizeof(formated_err),
1462  "Can't store key \"%s\" into icmap, returned error is %s",
1463  key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1464  *error_string = "Can't format parser error message";
1465  } else {
1466  *error_string = formated_err;
1467  }
1468 
1469  return (0);
1470 }
1471 
1472 static int uidgid_config_parser_cb(const char *path,
1473  char *key,
1474  char *value,
1475  enum main_cp_cb_data_state *state,
1476  enum parser_cb_type type,
1477  const char **error_string,
1478  icmap_map_t config_map,
1479  void *user_data)
1480 {
1481  char key_name[ICMAP_KEYNAME_MAXLEN];
1482  int uid, gid;
1483  static char formated_err[256];
1484  cs_error_t cs_err;
1485 
1486  switch (type) {
1487  case PARSER_CB_START:
1488  break;
1489  case PARSER_CB_END:
1490  break;
1491  case PARSER_CB_ITEM:
1492  if (strcmp(path, "uidgid.uid") == 0) {
1493  uid = uid_determine(value);
1494  if (uid == -1) {
1495  *error_string = error_string_response;
1496  return (0);
1497  }
1498  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1499  uid);
1500  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1501  goto icmap_set_error;
1502  }
1503  } else if (strcmp(path, "uidgid.gid") == 0) {
1504  gid = gid_determine(value);
1505  if (gid == -1) {
1506  *error_string = error_string_response;
1507  return (0);
1508  }
1509  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1510  gid);
1511  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1512  goto icmap_set_error;
1513  }
1514  } else {
1515  *error_string = "uidgid: Only uid and gid are allowed items";
1516  return (0);
1517  }
1518  break;
1520  if (strcmp(path, "uidgid") != 0) {
1521  *error_string = "uidgid: Can't add subsection different than uidgid";
1522  return (0);
1523  };
1524  break;
1525  case PARSER_CB_SECTION_END:
1526  break;
1527  }
1528 
1529  return (1);
1530 
1531 icmap_set_error:
1532  if (snprintf(formated_err, sizeof(formated_err),
1533  "Can't store key \"%s\" into icmap, returned error is %s",
1534  key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1535  *error_string = "Can't format parser error message";
1536  } else {
1537  *error_string = formated_err;
1538  }
1539 
1540  return (0);
1541 }
1542 
1543 static int read_uidgid_files_into_icmap(
1544  const char **error_string,
1545  icmap_map_t config_map)
1546 {
1547  FILE *fp;
1548  char *dirname_res;
1549  DIR *dp;
1550  struct dirent *dirent;
1551  char filename[PATH_MAX + FILENAME_MAX + 1];
1552  char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1553  int res = 0;
1554  struct stat stat_buf;
1556  char key_name[ICMAP_KEYNAME_MAXLEN];
1557  int line_no;
1558 
1559  /*
1560  * Build uidgid directory based on corosync.conf file location
1561  */
1562  res = snprintf(filename, sizeof(filename), "%s",
1564  if (res >= sizeof(filename)) {
1565  *error_string = "uidgid.d path too long";
1566 
1567  return (-1);
1568  }
1569 
1570  dirname_res = dirname(filename);
1571 
1572  res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1573  dirname_res, "uidgid.d");
1574  if (res >= sizeof(uidgid_dirname)) {
1575  *error_string = "uidgid.d path too long";
1576 
1577  return (-1);
1578  }
1579 
1580  dp = opendir (uidgid_dirname);
1581 
1582  if (dp == NULL)
1583  return 0;
1584 
1585  for (dirent = readdir(dp);
1586  dirent != NULL;
1587  dirent = readdir(dp)) {
1588 
1589  res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1590  if (res >= sizeof(filename)) {
1591  res = -1;
1592  *error_string = "uidgid.d dirname path too long";
1593 
1594  goto error_exit;
1595  }
1596  res = stat (filename, &stat_buf);
1597  if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1598 
1599  fp = fopen (filename, "r");
1600  if (fp == NULL) continue;
1601 
1602  key_name[0] = 0;
1603 
1604  line_no = 0;
1605  res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1606  uidgid_config_parser_cb, config_map, NULL);
1607 
1608  fclose (fp);
1609 
1610  if (res != 0) {
1611  goto error_exit;
1612  }
1613  }
1614  }
1615 
1616 error_exit:
1617  closedir(dp);
1618 
1619  return res;
1620 }
1621 
1622 /* Read config file and load into icmap */
1623 static int read_config_file_into_icmap(
1624  const char **error_string,
1625  icmap_map_t config_map)
1626 {
1627  FILE *fp;
1628  const char *filename;
1629  char *error_reason = error_string_response;
1630  int res;
1631  char key_name[ICMAP_KEYNAME_MAXLEN];
1632  struct main_cp_cb_data data;
1634  int line_no;
1635 
1636  filename = corosync_get_config_file();
1637 
1638  fp = fopen (filename, "r");
1639  if (fp == NULL) {
1640  char error_str[100];
1641  const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1642  snprintf (error_reason, sizeof(error_string_response),
1643  "Can't read file %s: %s",
1644  filename, error_ptr);
1645  *error_string = error_reason;
1646  return -1;
1647  }
1648 
1649  key_name[0] = 0;
1650 
1651  line_no = 0;
1652  res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1653  main_config_parser_cb, config_map, &data);
1654 
1655  fclose(fp);
1656 
1657  if (res == 0) {
1658  res = read_uidgid_files_into_icmap(error_string, config_map);
1659  }
1660 
1661  if (res == 0) {
1662  snprintf (error_reason, sizeof(error_string_response),
1663  "Successfully read main configuration file '%s'.", filename);
1664  *error_string = error_reason;
1665  }
1666 
1667  return res;
1668 }
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:97
@ CS_OK
Definition: corotypes.h:98
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:206
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