corosync  3.1.0
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  break;
812 
814  if (strcmp(path, "totem.interface.linknumber") == 0) {
815  val_type = ICMAP_VALUETYPE_UINT8;
816  if (safe_atoq(value, &val, val_type) != 0) {
817  goto atoi_error;
818  }
819 
820  data->linknumber = val;
821  add_as_string = 0;
822  }
823  if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
824  data->bindnetaddr = strdup(value);
825  add_as_string = 0;
826  }
827  if (strcmp(path, "totem.interface.mcastaddr") == 0) {
828  data->mcastaddr = strdup(value);
829  add_as_string = 0;
830  }
831  if (strcmp(path, "totem.interface.broadcast") == 0) {
832  data->broadcast = strdup(value);
833  add_as_string = 0;
834  }
835  if (strcmp(path, "totem.interface.mcastport") == 0) {
836  val_type = ICMAP_VALUETYPE_UINT16;
837  if (safe_atoq(value, &val, val_type) != 0) {
838  goto atoi_error;
839  }
840  data->mcastport = val;
841  add_as_string = 0;
842  }
843  if (strcmp(path, "totem.interface.ttl") == 0) {
844  val_type = ICMAP_VALUETYPE_UINT8;
845  if (safe_atoq(value, &val, val_type) != 0) {
846  goto atoi_error;
847  }
848  data->ttl = val;
849  add_as_string = 0;
850  }
851  if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
852  val_type = ICMAP_VALUETYPE_UINT8;
853  if (safe_atoq(value, &val, val_type) != 0) {
854  goto atoi_error;
855  }
856  data->knet_link_priority = val;
857  add_as_string = 0;
858  }
859  if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
860  val_type = ICMAP_VALUETYPE_UINT32;
861  if (safe_atoq(value, &val, val_type) != 0) {
862  goto atoi_error;
863  }
864  data->knet_ping_interval = val;
865  add_as_string = 0;
866  }
867  if (strcmp(path, "totem.interface.knet_ping_timeout") == 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_timeout = val;
873  add_as_string = 0;
874  }
875  if (strcmp(path, "totem.interface.knet_ping_precision") == 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_precision = val;
881  add_as_string = 0;
882  }
883  if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
884  val_type = ICMAP_VALUETYPE_UINT32;
885  if (safe_atoq(value, &val, val_type) != 0) {
886  goto atoi_error;
887  }
888  data->knet_pong_count = val;
889  add_as_string = 0;
890  }
891  if (strcmp(path, "totem.interface.knet_transport") == 0) {
892  val_type = ICMAP_VALUETYPE_STRING;
893  data->knet_transport = strdup(value);
894  add_as_string = 0;
895  }
896  break;
898  if (strcmp(key, "subsys") == 0) {
899  data->subsys = strdup(value);
900  if (data->subsys == NULL) {
901  *error_string = "Can't alloc memory";
902 
903  return (0);
904  }
905  } else {
906  kv_item = malloc(sizeof(*kv_item));
907  if (kv_item == NULL) {
908  *error_string = "Can't alloc memory";
909 
910  return (0);
911  }
912  memset(kv_item, 0, sizeof(*kv_item));
913 
914  kv_item->key = strdup(key);
915  kv_item->value = strdup(value);
916  if (kv_item->key == NULL || kv_item->value == NULL) {
917  free(kv_item);
918  *error_string = "Can't alloc memory";
919 
920  return (0);
921  }
922  qb_list_init(&kv_item->list);
923  qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
924  }
925  add_as_string = 0;
926  break;
928  if (strcmp(key, "subsys") == 0) {
929  data->subsys = strdup(value);
930  if (data->subsys == NULL) {
931  *error_string = "Can't alloc memory";
932 
933  return (0);
934  }
935  } else if (strcmp(key, "name") == 0) {
936  data->logging_daemon_name = strdup(value);
937  if (data->logging_daemon_name == NULL) {
938  *error_string = "Can't alloc memory";
939 
940  return (0);
941  }
942  } else {
943  kv_item = malloc(sizeof(*kv_item));
944  if (kv_item == NULL) {
945  *error_string = "Can't alloc memory";
946 
947  return (0);
948  }
949  memset(kv_item, 0, sizeof(*kv_item));
950 
951  kv_item->key = strdup(key);
952  kv_item->value = strdup(value);
953  if (kv_item->key == NULL || kv_item->value == NULL) {
954  free(kv_item);
955  *error_string = "Can't alloc memory";
956 
957  return (0);
958  }
959  qb_list_init(&kv_item->list);
960  qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
961  }
962  add_as_string = 0;
963  break;
965  if (strcmp(key, "uid") == 0) {
966  uid = uid_determine(value);
967  if (uid == -1) {
968  *error_string = error_string_response;
969  return (0);
970  }
971  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
972  uid);
973  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
974  goto icmap_set_error;
975  }
976  add_as_string = 0;
977  } else if (strcmp(key, "gid") == 0) {
978  gid = gid_determine(value);
979  if (gid == -1) {
980  *error_string = error_string_response;
981  return (0);
982  }
983  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
984  gid);
985  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
986  goto icmap_set_error;
987  }
988  add_as_string = 0;
989  } else {
990  *error_string = "uidgid: Only uid and gid are allowed items";
991  return (0);
992  }
993  break;
995  if (strcmp(key, "memberaddr") != 0) {
996  *error_string = "Only memberaddr is allowed in member section";
997 
998  return (0);
999  }
1000 
1001  kv_item = malloc(sizeof(*kv_item));
1002  if (kv_item == NULL) {
1003  *error_string = "Can't alloc memory";
1004 
1005  return (0);
1006  }
1007  memset(kv_item, 0, sizeof(*kv_item));
1008 
1009  kv_item->key = strdup(key);
1010  kv_item->value = strdup(value);
1011  if (kv_item->key == NULL || kv_item->value == NULL) {
1012  free(kv_item);
1013  *error_string = "Can't alloc memory";
1014 
1015  return (0);
1016  }
1017  qb_list_init(&kv_item->list);
1018  qb_list_add(&kv_item->list, &data->member_items_head);
1019  add_as_string = 0;
1020  break;
1022  break;
1024  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
1025  if ((strcmp(key, "nodeid") == 0) ||
1026  (strcmp(key, "quorum_votes") == 0)) {
1027  val_type = ICMAP_VALUETYPE_UINT32;
1028  if (safe_atoq(value, &val, val_type) != 0) {
1029  goto atoi_error;
1030  }
1031 
1032  if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
1033  goto icmap_set_error;
1034  }
1035  add_as_string = 0;
1036  }
1037 
1038  if (add_as_string) {
1039  if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
1040  goto icmap_set_error;
1041  };
1042  add_as_string = 0;
1043  }
1044  break;
1046  if (strcmp(key, "watchdog_timeout") == 0) {
1047  val_type = ICMAP_VALUETYPE_UINT32;
1048  if (safe_atoq(value, &val, val_type) != 0) {
1049  goto atoi_error;
1050  }
1051  if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
1052  goto icmap_set_error;
1053  }
1054  add_as_string = 0;
1055  }
1056  break;
1059  if (strcmp(key, "poll_period") == 0) {
1060  if (str_to_ull(value, &ull) != 0) {
1061  goto atoi_error;
1062  }
1063  if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1064  goto icmap_set_error;
1065  }
1066  add_as_string = 0;
1067  }
1068  break;
1071  if (strcmp(key, "poll_period") == 0) {
1072  if (str_to_ull(value, &ull) != 0) {
1073  goto atoi_error;
1074  }
1075  if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
1076  goto icmap_set_error;
1077  }
1078  add_as_string = 0;
1079  }
1080  break;
1081  }
1082 
1083  if (add_as_string) {
1084  if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
1085  goto icmap_set_error;
1086  }
1087  }
1088  break;
1090  if (strcmp(path, "totem.interface") == 0) {
1092  data->linknumber = 0;
1093  data->mcastport = -1;
1094  data->ttl = -1;
1095  data->knet_link_priority = -1;
1096  data->knet_ping_interval = -1;
1097  data->knet_ping_timeout = -1;
1098  data->knet_ping_precision = -1;
1099  data->knet_pong_count = -1;
1100  data->knet_transport = NULL;
1101  qb_list_init(&data->member_items_head);
1102  };
1103  if (strcmp(path, "totem") == 0) {
1104  *state = MAIN_CP_CB_DATA_STATE_TOTEM;
1105  };
1106  if (strcmp(path, "system") == 0) {
1108  }
1109  if (strcmp(path, "logging.logger_subsys") == 0) {
1111  qb_list_init(&data->logger_subsys_items_head);
1112  data->subsys = NULL;
1113  }
1114  if (strcmp(path, "logging.logging_daemon") == 0) {
1116  qb_list_init(&data->logger_subsys_items_head);
1117  data->subsys = NULL;
1118  data->logging_daemon_name = NULL;
1119  }
1120  if (strcmp(path, "uidgid") == 0) {
1122  }
1123  if (strcmp(path, "totem.interface.member") == 0) {
1125  }
1126  if (strcmp(path, "quorum") == 0) {
1128  }
1129  if (strcmp(path, "quorum.device") == 0) {
1131  }
1132  if (strcmp(path, "nodelist") == 0) {
1134  data->node_number = 0;
1135  }
1136  if (strcmp(path, "nodelist.node") == 0) {
1138  }
1139  if (strcmp(path, "resources") == 0) {
1141  }
1142  if (strcmp(path, "resources.system") == 0) {
1144  }
1145  if (strcmp(path, "resources.system.memory_used") == 0) {
1147  }
1148  if (strcmp(path, "resources.process") == 0) {
1150  }
1151  if (strcmp(path, "resources.process.memory_used") == 0) {
1153  }
1154  break;
1155  case PARSER_CB_SECTION_END:
1156  switch (*state) {
1158  /*
1159  * Create new interface section
1160  */
1161  if (data->bindnetaddr != NULL) {
1162  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
1163  data->linknumber);
1164  cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
1165 
1166  free(data->bindnetaddr);
1167  data->bindnetaddr = NULL;
1168 
1169  if (cs_err != CS_OK) {
1170  goto icmap_set_error;
1171  }
1172  }
1173 
1174  if (data->mcastaddr != NULL) {
1175  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
1176  data->linknumber);
1177  cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
1178 
1179  free(data->mcastaddr);
1180  data->mcastaddr = NULL;
1181 
1182  if (cs_err != CS_OK) {
1183  goto icmap_set_error;
1184  }
1185  }
1186 
1187  if (data->broadcast != NULL) {
1188  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
1189  data->linknumber);
1190  cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
1191 
1192  free(data->broadcast);
1193  data->broadcast = NULL;
1194 
1195  if (cs_err != CS_OK) {
1196  goto icmap_set_error;
1197  }
1198  }
1199 
1200  if (data->mcastport > -1) {
1201  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
1202  data->linknumber);
1203  if ((cs_err = icmap_set_uint16_r(config_map, key_name,
1204  data->mcastport)) != CS_OK) {
1205  goto icmap_set_error;
1206  }
1207  }
1208 
1209  if (data->ttl > -1) {
1210  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
1211  data->linknumber);
1212  if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
1213  goto icmap_set_error;
1214  }
1215  }
1216  if (data->knet_link_priority > -1) {
1217  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
1218  data->linknumber);
1219  if ((cs_err = icmap_set_uint8_r(config_map, key_name,
1220  data->knet_link_priority)) != CS_OK) {
1221  goto icmap_set_error;
1222  }
1223  }
1224  if (data->knet_ping_interval > -1) {
1225  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
1226  data->linknumber);
1227  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1228  data->knet_ping_interval)) != CS_OK) {
1229  goto icmap_set_error;
1230  }
1231  }
1232  if (data->knet_ping_timeout > -1) {
1233  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
1234  data->linknumber);
1235  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1236  data->knet_ping_timeout)) != CS_OK) {
1237  goto icmap_set_error;
1238  }
1239  }
1240  if (data->knet_ping_precision > -1) {
1241  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
1242  data->linknumber);
1243  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1244  data->knet_ping_precision)) != CS_OK) {
1245  goto icmap_set_error;
1246  }
1247  }
1248  if (data->knet_pong_count > -1) {
1249  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
1250  data->linknumber);
1251  if ((cs_err = icmap_set_uint32_r(config_map, key_name,
1252  data->knet_pong_count)) != CS_OK) {
1253  goto icmap_set_error;
1254  }
1255  }
1256  if (data->knet_transport) {
1257  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
1258  data->linknumber);
1259  cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
1260  free(data->knet_transport);
1261 
1262  if (cs_err != CS_OK) {
1263  goto icmap_set_error;
1264  }
1265  }
1266 
1267  ii = 0;
1268 
1269  qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
1270  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1271 
1272  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
1273  data->linknumber, ii);
1274  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1275 
1276  free(kv_item->value);
1277  free(kv_item->key);
1278  free(kv_item);
1279  ii++;
1280 
1281  if (cs_err != CS_OK) {
1282  goto icmap_set_error;
1283  }
1284  }
1285 
1286  break;
1288  if (data->subsys == NULL) {
1289  *error_string = "No subsys key in logger_subsys directive";
1290 
1291  return (0);
1292  }
1293 
1294  qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1295  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1296 
1297  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
1298  data->subsys, kv_item->key);
1299  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1300 
1301  free(kv_item->value);
1302  free(kv_item->key);
1303  free(kv_item);
1304 
1305  if (cs_err != CS_OK) {
1306  goto icmap_set_error;
1307  }
1308  }
1309 
1310  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1311  data->subsys);
1312  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1313 
1314  free(data->subsys);
1315 
1316  if (cs_err != CS_OK) {
1317  goto icmap_set_error;
1318  }
1319  break;
1321  if (data->logging_daemon_name == NULL) {
1322  *error_string = "No name key in logging_daemon directive";
1323 
1324  return (0);
1325  }
1326 
1327  qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
1328  kv_item = qb_list_entry(iter, struct key_value_list_item, list);
1329 
1330  if (data->subsys == NULL) {
1331  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1332  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1333  "logging.%s",
1334  kv_item->key);
1335  } else {
1336  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1337  "logging.logging_daemon.%s.%s",
1338  data->logging_daemon_name, kv_item->key);
1339  }
1340  } else {
1341  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1342  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1343  "logging.logger_subsys.%s.%s",
1344  data->subsys,
1345  kv_item->key);
1346  } else {
1347  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1348  "logging.logging_daemon.%s.%s.%s",
1349  data->logging_daemon_name, data->subsys,
1350  kv_item->key);
1351  }
1352  }
1353  cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
1354 
1355  free(kv_item->value);
1356  free(kv_item->key);
1357  free(kv_item);
1358 
1359  if (cs_err != CS_OK) {
1360  goto icmap_set_error;
1361  }
1362  }
1363 
1364  if (data->subsys == NULL) {
1365  if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1366  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1367  data->logging_daemon_name);
1368  cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1369  }
1370  } else {
1371  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1372  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1373  data->subsys);
1374  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1375 
1376  } else {
1377  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1378  data->logging_daemon_name, data->subsys);
1379  cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
1380 
1381  if (cs_err != CS_OK) {
1382  free(data->subsys);
1383  free(data->logging_daemon_name);
1384 
1385  goto icmap_set_error;
1386  }
1387  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1388  data->logging_daemon_name, data->subsys);
1389  cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1390  }
1391  }
1392 
1393  free(data->subsys);
1394  free(data->logging_daemon_name);
1395 
1396  if (cs_err != CS_OK) {
1397  goto icmap_set_error;
1398  }
1399  break;
1401  data->node_number++;
1402  break;
1412  break;
1415  break;
1418  break;
1421  break;
1424  break;
1427  break;
1428  }
1429  break;
1430  }
1431 
1432  return (1);
1433 
1434 atoi_error:
1435  min_val = max_val = 0;
1436  /*
1437  * This is really assert, because developer ether doesn't set val_type correctly or
1438  * we've got here after some nasty memory overwrite
1439  */
1440  assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1441 
1442  if (snprintf(formated_err, sizeof(formated_err),
1443  "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1444  key_name, min_val, max_val, value) >= sizeof(formated_err)) {
1445  *error_string = "Can't format parser error message";
1446  } else {
1447  *error_string = formated_err;
1448  }
1449 
1450  return (0);
1451 
1452 icmap_set_error:
1453  if (snprintf(formated_err, sizeof(formated_err),
1454  "Can't store key \"%s\" into icmap, returned error is %s",
1455  key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1456  *error_string = "Can't format parser error message";
1457  } else {
1458  *error_string = formated_err;
1459  }
1460 
1461  return (0);
1462 }
1463 
1464 static int uidgid_config_parser_cb(const char *path,
1465  char *key,
1466  char *value,
1467  enum main_cp_cb_data_state *state,
1468  enum parser_cb_type type,
1469  const char **error_string,
1470  icmap_map_t config_map,
1471  void *user_data)
1472 {
1473  char key_name[ICMAP_KEYNAME_MAXLEN];
1474  int uid, gid;
1475  static char formated_err[256];
1476  cs_error_t cs_err;
1477 
1478  switch (type) {
1479  case PARSER_CB_START:
1480  break;
1481  case PARSER_CB_END:
1482  break;
1483  case PARSER_CB_ITEM:
1484  if (strcmp(path, "uidgid.uid") == 0) {
1485  uid = uid_determine(value);
1486  if (uid == -1) {
1487  *error_string = error_string_response;
1488  return (0);
1489  }
1490  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
1491  uid);
1492  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1493  goto icmap_set_error;
1494  }
1495  } else if (strcmp(path, "uidgid.gid") == 0) {
1496  gid = gid_determine(value);
1497  if (gid == -1) {
1498  *error_string = error_string_response;
1499  return (0);
1500  }
1501  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
1502  gid);
1503  if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
1504  goto icmap_set_error;
1505  }
1506  } else {
1507  *error_string = "uidgid: Only uid and gid are allowed items";
1508  return (0);
1509  }
1510  break;
1512  if (strcmp(path, "uidgid") != 0) {
1513  *error_string = "uidgid: Can't add subsection different than uidgid";
1514  return (0);
1515  };
1516  break;
1517  case PARSER_CB_SECTION_END:
1518  break;
1519  }
1520 
1521  return (1);
1522 
1523 icmap_set_error:
1524  if (snprintf(formated_err, sizeof(formated_err),
1525  "Can't store key \"%s\" into icmap, returned error is %s",
1526  key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
1527  *error_string = "Can't format parser error message";
1528  } else {
1529  *error_string = formated_err;
1530  }
1531 
1532  return (0);
1533 }
1534 
1535 static int read_uidgid_files_into_icmap(
1536  const char **error_string,
1537  icmap_map_t config_map)
1538 {
1539  FILE *fp;
1540  char *dirname_res;
1541  DIR *dp;
1542  struct dirent *dirent;
1543  char filename[PATH_MAX + FILENAME_MAX + 1];
1544  char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
1545  int res = 0;
1546  struct stat stat_buf;
1548  char key_name[ICMAP_KEYNAME_MAXLEN];
1549  int line_no;
1550 
1551  /*
1552  * Build uidgid directory based on corosync.conf file location
1553  */
1554  res = snprintf(filename, sizeof(filename), "%s",
1556  if (res >= sizeof(filename)) {
1557  *error_string = "uidgid.d path too long";
1558 
1559  return (-1);
1560  }
1561 
1562  dirname_res = dirname(filename);
1563 
1564  res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
1565  dirname_res, "uidgid.d");
1566  if (res >= sizeof(uidgid_dirname)) {
1567  *error_string = "uidgid.d path too long";
1568 
1569  return (-1);
1570  }
1571 
1572  dp = opendir (uidgid_dirname);
1573 
1574  if (dp == NULL)
1575  return 0;
1576 
1577  for (dirent = readdir(dp);
1578  dirent != NULL;
1579  dirent = readdir(dp)) {
1580 
1581  res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
1582  if (res >= sizeof(filename)) {
1583  res = -1;
1584  *error_string = "uidgid.d dirname path too long";
1585 
1586  goto error_exit;
1587  }
1588  res = stat (filename, &stat_buf);
1589  if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1590 
1591  fp = fopen (filename, "r");
1592  if (fp == NULL) continue;
1593 
1594  key_name[0] = 0;
1595 
1596  line_no = 0;
1597  res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1598  uidgid_config_parser_cb, config_map, NULL);
1599 
1600  fclose (fp);
1601 
1602  if (res != 0) {
1603  goto error_exit;
1604  }
1605  }
1606  }
1607 
1608 error_exit:
1609  closedir(dp);
1610 
1611  return res;
1612 }
1613 
1614 /* Read config file and load into icmap */
1615 static int read_config_file_into_icmap(
1616  const char **error_string,
1617  icmap_map_t config_map)
1618 {
1619  FILE *fp;
1620  const char *filename;
1621  char *error_reason = error_string_response;
1622  int res;
1623  char key_name[ICMAP_KEYNAME_MAXLEN];
1624  struct main_cp_cb_data data;
1626  int line_no;
1627 
1628  filename = corosync_get_config_file();
1629 
1630  fp = fopen (filename, "r");
1631  if (fp == NULL) {
1632  char error_str[100];
1633  const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1634  snprintf (error_reason, sizeof(error_string_response),
1635  "Can't read file %s: %s",
1636  filename, error_ptr);
1637  *error_string = error_reason;
1638  return -1;
1639  }
1640 
1641  key_name[0] = 0;
1642 
1643  line_no = 0;
1644  res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
1645  main_config_parser_cb, config_map, &data);
1646 
1647  fclose(fp);
1648 
1649  if (res == 0) {
1650  res = read_uidgid_files_into_icmap(error_string, config_map);
1651  }
1652 
1653  if (res == 0) {
1654  snprintf (error_reason, sizeof(error_string_response),
1655  "Successfully read main configuration file '%s'.", filename);
1656  *error_string = error_reason;
1657  }
1658 
1659  return res;
1660 }
char * logging_daemon_name
Definition: coroparse.c:128
struct qb_list_head member_items_head
Definition: coroparse.c:129
struct qb_list_head list
Definition: coroparse.c:108
uint32_t value
const char * cs_strerror(cs_error_t err)
cs_strerror
int knet_ping_timeout
Definition: coroparse.c:120
int coroparse_configparse(icmap_map_t config_map, const char **error_string)
Definition: coroparse.c:258
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
Definition: icmap.c:539
struct qb_list_head logger_subsys_items_head
Definition: coroparse.c:126
int knet_pmtud_interval
Definition: coroparse.c:123
char * mcastaddr
Definition: coroparse.c:114
char * bindnetaddr
Definition: coroparse.c:113
cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
Definition: icmap.c:521
int knet_ping_precision
Definition: coroparse.c:121
int knet_ping_interval
Definition: coroparse.c:119
parser_cb_type
Definition: coroparse.c:67
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
Definition: icmap.c:557
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
Definition: icmap.h:48
cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
Definition: icmap.c:503
const char * corosync_get_config_file(void)
Definition: main.c:204
void * user_data
Definition: sam.c:127
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
Definition: icmap.c:527
char * broadcast
Definition: coroparse.c:115
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:97
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
Definition: icmap.c:515
char * knet_transport
Definition: coroparse.c:124
main_cp_cb_data_state
Definition: coroparse.c:75
char type
Definition: totem.h:55
int(* parser_cb_f)(const char *path, char *key, char *value, enum main_cp_cb_data_state *state, enum parser_cb_type type, const char **error_string, icmap_map_t config_map, void *user_data)
Definition: coroparse.c:96
int knet_link_priority
Definition: coroparse.c:118
icmap_value_types_t
Possible types of value.
Definition: icmap.h:58