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