corosync  2.3.5
coroparse.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006-2013 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 <limits.h>
53 #include <stddef.h>
54 #include <grp.h>
55 #include <pwd.h>
56 
57 #include <corosync/list.h>
58 #include <qb/qbutil.h>
59 #define LOGSYS_UTILS_ONLY 1
60 #include <corosync/logsys.h>
61 #include <corosync/icmap.h>
62 
63 #include "main.h"
64 #include "util.h"
65 
72 };
73 
88 };
89 
90 typedef int (*parser_cb_f)(const char *path,
91  char *key,
92  char *value,
93  enum main_cp_cb_data_state *state,
94  enum parser_cb_type type,
95  const char **error_string,
96  icmap_map_t config_map,
97  void *user_data);
98 
100  char *key;
101  char *value;
102  struct list_head list;
103 };
104 
107  char *bindnetaddr;
108  char *mcastaddr;
109  char *broadcast;
111  int ttl;
112 
113  struct list_head logger_subsys_items_head;
114  char *subsys;
116  struct list_head member_items_head;
117 
120 };
121 
122 static int read_config_file_into_icmap(
123  const char **error_string, icmap_map_t config_map);
124 static char error_string_response[512];
125 
126 static int uid_determine (const char *req_user)
127 {
128  int pw_uid = 0;
129  struct passwd passwd;
130  struct passwd* pwdptr = &passwd;
131  struct passwd* temp_pwd_pt;
132  char *pwdbuffer;
133  int pwdlinelen, rc;
134  long int id;
135  char *ep;
136 
137  id = strtol(req_user, &ep, 10);
138  if (*ep == '\0' && id >= 0 && id <= UINT_MAX) {
139  return (id);
140  }
141 
142  pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
143 
144  if (pwdlinelen == -1) {
145  pwdlinelen = 256;
146  }
147 
148  pwdbuffer = malloc (pwdlinelen);
149 
150  while ((rc = getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) == ERANGE) {
151  char *n;
152 
153  pwdlinelen *= 2;
154  if (pwdlinelen <= 32678) {
155  n = realloc (pwdbuffer, pwdlinelen);
156  if (n != NULL) {
157  pwdbuffer = n;
158  continue;
159  }
160  }
161  }
162  if (rc != 0) {
163  free (pwdbuffer);
164  sprintf (error_string_response, "getpwnam_r(): %s", strerror(rc));
165  return (-1);
166  }
167  if (temp_pwd_pt == NULL) {
168  free (pwdbuffer);
169  sprintf (error_string_response,
170  "The '%s' user is not found in /etc/passwd, please read the documentation.",
171  req_user);
172  return (-1);
173  }
174  pw_uid = passwd.pw_uid;
175  free (pwdbuffer);
176 
177  return pw_uid;
178 }
179 
180 static int gid_determine (const char *req_group)
181 {
182  int corosync_gid = 0;
183  struct group group;
184  struct group * grpptr = &group;
185  struct group * temp_grp_pt;
186  char *grpbuffer;
187  int grplinelen, rc;
188  long int id;
189  char *ep;
190 
191  id = strtol(req_group, &ep, 10);
192  if (*ep == '\0' && id >= 0 && id <= UINT_MAX) {
193  return (id);
194  }
195 
196  grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
197 
198  if (grplinelen == -1) {
199  grplinelen = 256;
200  }
201 
202  grpbuffer = malloc (grplinelen);
203 
204  while ((rc = getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) == ERANGE) {
205  char *n;
206 
207  grplinelen *= 2;
208  if (grplinelen <= 32678) {
209  n = realloc (grpbuffer, grplinelen);
210  if (n != NULL) {
211  grpbuffer = n;
212  continue;
213  }
214  }
215  }
216  if (rc != 0) {
217  free (grpbuffer);
218  sprintf (error_string_response, "getgrnam_r(): %s", strerror(rc));
219  return (-1);
220  }
221  if (temp_grp_pt == NULL) {
222  free (grpbuffer);
223  sprintf (error_string_response,
224  "The '%s' group is not found in /etc/group, please read the documentation.",
225  req_group);
226  return (-1);
227  }
228  corosync_gid = group.gr_gid;
229  free (grpbuffer);
230 
231  return corosync_gid;
232 }
233 static char *strchr_rs (const char *haystack, int byte)
234 {
235  const char *end_address = strchr (haystack, byte);
236  if (end_address) {
237  end_address += 1; /* skip past { or = */
238 
239  while (*end_address == ' ' || *end_address == '\t')
240  end_address++;
241  }
242 
243  return ((char *) end_address);
244 }
245 
246 int coroparse_configparse (icmap_map_t config_map, const char **error_string)
247 {
248  if (read_config_file_into_icmap(error_string, config_map)) {
249  return -1;
250  }
251 
252  return 0;
253 }
254 
255 static char *remove_whitespace(char *string, int remove_colon_and_brace)
256 {
257  char *start;
258  char *end;
259 
260  start = string;
261  while (*start == ' ' || *start == '\t')
262  start++;
263 
264  end = start+(strlen(start))-1;
265  while ((*end == ' ' || *end == '\t' || (remove_colon_and_brace && (*end == ':' || *end == '{'))) && end > start)
266  end--;
267  if (end != start)
268  *(end+1) = '\0';
269 
270  return start;
271 }
272 
273 
274 
275 static int parse_section(FILE *fp,
276  char *path,
277  const char **error_string,
278  int depth,
279  enum main_cp_cb_data_state state,
280  parser_cb_f parser_cb,
281  icmap_map_t config_map,
282  void *user_data)
283 {
284  char line[512];
285  int i;
286  char *loc;
287  int ignore_line;
288  char new_keyname[ICMAP_KEYNAME_MAXLEN];
289 
290  if (strcmp(path, "") == 0) {
291  parser_cb("", NULL, NULL, &state, PARSER_CB_START, error_string, config_map, user_data);
292  }
293 
294  while (fgets (line, sizeof (line), fp)) {
295  if (strlen(line) > 0) {
296  if (line[strlen(line) - 1] == '\n')
297  line[strlen(line) - 1] = '\0';
298  if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
299  line[strlen(line) - 1] = '\0';
300  }
301  /*
302  * Clear out white space and tabs
303  */
304  for (i = strlen (line) - 1; i > -1; i--) {
305  if (line[i] == '\t' || line[i] == ' ') {
306  line[i] = '\0';
307  } else {
308  break;
309  }
310  }
311 
312  ignore_line = 1;
313  for (i = 0; i < strlen (line); i++) {
314  if (line[i] != '\t' && line[i] != ' ') {
315  if (line[i] != '#')
316  ignore_line = 0;
317 
318  break;
319  }
320  }
321  /*
322  * Clear out comments and empty lines
323  */
324  if (ignore_line) {
325  continue;
326  }
327 
328  /* New section ? */
329  if ((loc = strchr_rs (line, '{'))) {
330  char *section = remove_whitespace(line, 1);
331  enum main_cp_cb_data_state newstate;
332 
333  loc--;
334  *loc = '\0';
335 
336  if (strlen(path) + strlen(section) + 1 >= ICMAP_KEYNAME_MAXLEN) {
337  *error_string = "parser error: Start of section makes total cmap path too long";
338  return -1;
339  }
340  strcpy(new_keyname, path);
341  if (strcmp(path, "") != 0) {
342  strcat(new_keyname, ".");
343  }
344  strcat(new_keyname, section);
345 
346  /* Only use the new state for items further down the stack */
347  newstate = state;
348  if (!parser_cb(new_keyname, NULL, NULL, &newstate, PARSER_CB_SECTION_START, error_string, config_map, user_data)) {
349  return -1;
350  }
351 
352  if (parse_section(fp, new_keyname, error_string, depth + 1, newstate, parser_cb, config_map, user_data))
353  return -1;
354 
355  continue ;
356  }
357 
358  /* New key/value */
359  if ((loc = strchr_rs (line, ':'))) {
360  char *key;
361  char *value;
362 
363  *(loc-1) = '\0';
364  key = remove_whitespace(line, 1);
365  value = remove_whitespace(loc, 0);
366 
367  if (strlen(path) + strlen(key) + 1 >= ICMAP_KEYNAME_MAXLEN) {
368  *error_string = "parser error: New key makes total cmap path too long";
369  return -1;
370  }
371  strcpy(new_keyname, path);
372  if (strcmp(path, "") != 0) {
373  strcat(new_keyname, ".");
374  }
375  strcat(new_keyname, key);
376 
377  if (!parser_cb(new_keyname, key, value, &state, PARSER_CB_ITEM, error_string, config_map, user_data)) {
378  return -1;
379  }
380 
381  continue ;
382  }
383 
384  if (strchr_rs (line, '}')) {
385  if (depth == 0) {
386  *error_string = "parser error: Unexpected closing brace";
387 
388  return -1;
389  }
390 
391  if (!parser_cb(path, NULL, NULL, &state, PARSER_CB_SECTION_END, error_string, config_map, user_data)) {
392  return -1;
393  }
394 
395  return 0;
396  }
397  }
398 
399  if (strcmp(path, "") != 0) {
400  *error_string = "parser error: Missing closing brace";
401  return -1;
402  }
403 
404  if (strcmp(path, "") == 0) {
405  parser_cb("", NULL, NULL, &state, PARSER_CB_END, error_string, config_map, user_data);
406  }
407 
408  return 0;
409 }
410 
411 static int safe_atoq_range(icmap_value_types_t value_type, long long int *min_val, long long int *max_val)
412 {
413  switch (value_type) {
414  case ICMAP_VALUETYPE_INT8: *min_val = INT8_MIN; *max_val = INT8_MAX; break;
415  case ICMAP_VALUETYPE_UINT8: *min_val = 0; *max_val = UINT8_MAX; break;
416  case ICMAP_VALUETYPE_INT16: *min_val = INT16_MIN; *max_val = INT16_MAX; break;
417  case ICMAP_VALUETYPE_UINT16: *min_val = 0; *max_val = UINT16_MAX; break;
418  case ICMAP_VALUETYPE_INT32: *min_val = INT32_MIN; *max_val = INT32_MAX; break;
419  case ICMAP_VALUETYPE_UINT32: *min_val = 0; *max_val = UINT32_MAX; break;
420  default:
421  return (-1);
422  }
423 
424  return (0);
425 }
426 
427 /*
428  * Convert string str to long long int res. Type of result is target_type and currently only
429  * ICMAP_VALUETYPE_[U]INT[8|16|32] is supported.
430  * Return 0 on success, -1 on failure.
431  */
432 static int safe_atoq(const char *str, long long int *res, icmap_value_types_t target_type)
433 {
434  long long int val;
435  long long int min_val, max_val;
436  char *endptr;
437 
438  errno = 0;
439 
440  val = strtoll(str, &endptr, 10);
441  if (errno == ERANGE) {
442  return (-1);
443  }
444 
445  if (endptr == str) {
446  return (-1);
447  }
448 
449  if (*endptr != '\0') {
450  return (-1);
451  }
452 
453  if (safe_atoq_range(target_type, &min_val, &max_val) != 0) {
454  return (-1);
455  }
456 
457  if (val < min_val || val > max_val) {
458  return (-1);
459  }
460 
461  *res = val;
462  return (0);
463 }
464 
465 static int str_to_ull(const char *str, unsigned long long int *res)
466 {
467  unsigned long long int val;
468  char *endptr;
469 
470  errno = 0;
471 
472  val = strtoull(str, &endptr, 10);
473  if (errno == ERANGE) {
474  return (-1);
475  }
476 
477  if (endptr == str) {
478  return (-1);
479  }
480 
481  if (*endptr != '\0') {
482  return (-1);
483  }
484 
485  *res = val;
486  return (0);
487 }
488 
489 static int main_config_parser_cb(const char *path,
490  char *key,
491  char *value,
492  enum main_cp_cb_data_state *state,
493  enum parser_cb_type type,
494  const char **error_string,
495  icmap_map_t config_map,
496  void *user_data)
497 {
498  int ii;
499  long long int val;
500  long long int min_val, max_val;
502  unsigned long long int ull;
503  int add_as_string;
504  char key_name[ICMAP_KEYNAME_MAXLEN];
505  static char formated_err[256];
506  struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
507  struct key_value_list_item *kv_item;
508  struct list_head *iter, *iter_next;
509  int uid, gid;
510 
511  switch (type) {
512  case PARSER_CB_START:
513  memset(data, 0, sizeof(struct main_cp_cb_data));
515  break;
516  case PARSER_CB_END:
517  break;
518  case PARSER_CB_ITEM:
519  add_as_string = 1;
520 
521  switch (*state) {
523  break;
525  if ((strcmp(path, "pload.count") == 0) ||
526  (strcmp(path, "pload.size") == 0)) {
527  val_type = ICMAP_VALUETYPE_UINT32;
528  if (safe_atoq(value, &val, val_type) != 0) {
529  goto atoi_error;
530  }
531  icmap_set_uint32_r(config_map, path, val);
532  add_as_string = 0;
533  }
534  break;
536  if ((strcmp(path, "quorum.expected_votes") == 0) ||
537  (strcmp(path, "quorum.votes") == 0) ||
538  (strcmp(path, "quorum.last_man_standing_window") == 0) ||
539  (strcmp(path, "quorum.leaving_timeout") == 0)) {
540  val_type = ICMAP_VALUETYPE_UINT32;
541  if (safe_atoq(value, &val, val_type) != 0) {
542  goto atoi_error;
543  }
544  icmap_set_uint32_r(config_map, path, val);
545  add_as_string = 0;
546  }
547 
548  if ((strcmp(path, "quorum.two_node") == 0) ||
549  (strcmp(path, "quorum.expected_votes_tracking") == 0) ||
550  (strcmp(path, "quorum.allow_downscale") == 0) ||
551  (strcmp(path, "quorum.wait_for_all") == 0) ||
552  (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
553  (strcmp(path, "quorum.last_man_standing") == 0)) {
554  val_type = ICMAP_VALUETYPE_UINT8;
555  if (safe_atoq(value, &val, val_type) != 0) {
556  goto atoi_error;
557  }
558  icmap_set_uint8_r(config_map, path, val);
559  add_as_string = 0;
560  }
561  break;
563  if ((strcmp(path, "quorum.device.timeout") == 0) ||
564  (strcmp(path, "quorum.device.sync_timeout") == 0) ||
565  (strcmp(path, "quorum.device.votes") == 0)) {
566  val_type = ICMAP_VALUETYPE_UINT32;
567  if (safe_atoq(value, &val, val_type) != 0) {
568  goto atoi_error;
569  }
570  icmap_set_uint32_r(config_map, path, val);
571  add_as_string = 0;
572  }
573  if ((strcmp(path, "quorum.device.master_wins") == 0)) {
574  val_type = ICMAP_VALUETYPE_UINT8;
575  if (safe_atoq(value, &val, val_type) != 0) {
576  goto atoi_error;
577  }
578  icmap_set_uint8_r(config_map, path, val);
579  add_as_string = 0;
580  }
581  break;
583  if ((strcmp(path, "totem.version") == 0) ||
584  (strcmp(path, "totem.nodeid") == 0) ||
585  (strcmp(path, "totem.threads") == 0) ||
586  (strcmp(path, "totem.token") == 0) ||
587  (strcmp(path, "totem.token_coefficient") == 0) ||
588  (strcmp(path, "totem.token_retransmit") == 0) ||
589  (strcmp(path, "totem.hold") == 0) ||
590  (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
591  (strcmp(path, "totem.join") == 0) ||
592  (strcmp(path, "totem.send_join") == 0) ||
593  (strcmp(path, "totem.consensus") == 0) ||
594  (strcmp(path, "totem.merge") == 0) ||
595  (strcmp(path, "totem.downcheck") == 0) ||
596  (strcmp(path, "totem.fail_recv_const") == 0) ||
597  (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
598  (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
599  (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
600  (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
601  (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
602  (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
603  (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
604  (strcmp(path, "totem.max_network_delay") == 0) ||
605  (strcmp(path, "totem.window_size") == 0) ||
606  (strcmp(path, "totem.max_messages") == 0) ||
607  (strcmp(path, "totem.miss_count_const") == 0) ||
608  (strcmp(path, "totem.netmtu") == 0)) {
609  val_type = ICMAP_VALUETYPE_UINT32;
610  if (safe_atoq(value, &val, val_type) != 0) {
611  goto atoi_error;
612  }
613  icmap_set_uint32_r(config_map,path, val);
614  add_as_string = 0;
615  }
616  if (strcmp(path, "totem.config_version") == 0) {
617  if (str_to_ull(value, &ull) != 0) {
618  goto atoi_error;
619  }
620  icmap_set_uint64_r(config_map, path, ull);
621  add_as_string = 0;
622  }
623  if (strcmp(path, "totem.ip_version") == 0) {
624  if ((strcmp(value, "ipv4") != 0) &&
625  (strcmp(value, "ipv6") != 0)) {
626  *error_string = "Invalid ip_version type";
627 
628  return (0);
629  }
630  }
631  if (strcmp(path, "totem.crypto_type") == 0) {
632  if ((strcmp(value, "nss") != 0) &&
633  (strcmp(value, "aes256") != 0) &&
634  (strcmp(value, "aes192") != 0) &&
635  (strcmp(value, "aes128") != 0) &&
636  (strcmp(value, "3des") != 0)) {
637  *error_string = "Invalid crypto type";
638 
639  return (0);
640  }
641  }
642  if (strcmp(path, "totem.crypto_cipher") == 0) {
643  if ((strcmp(value, "none") != 0) &&
644  (strcmp(value, "aes256") != 0) &&
645  (strcmp(value, "aes192") != 0) &&
646  (strcmp(value, "aes128") != 0) &&
647  (strcmp(value, "3des") != 0)) {
648  *error_string = "Invalid cipher type";
649 
650  return (0);
651  }
652  }
653  if (strcmp(path, "totem.crypto_hash") == 0) {
654  if ((strcmp(value, "none") != 0) &&
655  (strcmp(value, "md5") != 0) &&
656  (strcmp(value, "sha1") != 0) &&
657  (strcmp(value, "sha256") != 0) &&
658  (strcmp(value, "sha384") != 0) &&
659  (strcmp(value, "sha512") != 0)) {
660  *error_string = "Invalid hash type";
661 
662  return (0);
663  }
664  }
665  break;
666 
668  if (strcmp(path, "qb.ipc_type") == 0) {
669  if ((strcmp(value, "native") != 0) &&
670  (strcmp(value, "shm") != 0) &&
671  (strcmp(value, "socket") != 0)) {
672  *error_string = "Invalid qb ipc_type";
673 
674  return (0);
675  }
676  }
677  break;
678 
680  if (strcmp(path, "totem.interface.ringnumber") == 0) {
681  val_type = ICMAP_VALUETYPE_UINT8;
682  if (safe_atoq(value, &val, val_type) != 0) {
683  goto atoi_error;
684  }
685 
686  data->ringnumber = val;
687  add_as_string = 0;
688  }
689  if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
690  data->bindnetaddr = strdup(value);
691  add_as_string = 0;
692  }
693  if (strcmp(path, "totem.interface.mcastaddr") == 0) {
694  data->mcastaddr = strdup(value);
695  add_as_string = 0;
696  }
697  if (strcmp(path, "totem.interface.broadcast") == 0) {
698  data->broadcast = strdup(value);
699  add_as_string = 0;
700  }
701  if (strcmp(path, "totem.interface.mcastport") == 0) {
702  val_type = ICMAP_VALUETYPE_UINT16;
703  if (safe_atoq(value, &val, val_type) != 0) {
704  goto atoi_error;
705  }
706  data->mcastport = val;
707  add_as_string = 0;
708  }
709  if (strcmp(path, "totem.interface.ttl") == 0) {
710  val_type = ICMAP_VALUETYPE_UINT8;
711  if (safe_atoq(value, &val, val_type) != 0) {
712  goto atoi_error;
713  }
714  data->ttl = val;
715  add_as_string = 0;
716  }
717  break;
719  if (strcmp(key, "subsys") == 0) {
720  data->subsys = strdup(value);
721  if (data->subsys == NULL) {
722  *error_string = "Can't alloc memory";
723 
724  return (0);
725  }
726  } else {
727  kv_item = malloc(sizeof(*kv_item));
728  if (kv_item == NULL) {
729  *error_string = "Can't alloc memory";
730 
731  return (0);
732  }
733  memset(kv_item, 0, sizeof(*kv_item));
734 
735  kv_item->key = strdup(key);
736  kv_item->value = strdup(value);
737  if (kv_item->key == NULL || kv_item->value == NULL) {
738  free(kv_item);
739  *error_string = "Can't alloc memory";
740 
741  return (0);
742  }
743  list_init(&kv_item->list);
744  list_add(&kv_item->list, &data->logger_subsys_items_head);
745  }
746  add_as_string = 0;
747  break;
749  if (strcmp(key, "subsys") == 0) {
750  data->subsys = strdup(value);
751  if (data->subsys == NULL) {
752  *error_string = "Can't alloc memory";
753 
754  return (0);
755  }
756  } else if (strcmp(key, "name") == 0) {
757  data->logging_daemon_name = strdup(value);
758  if (data->logging_daemon_name == NULL) {
759  *error_string = "Can't alloc memory";
760 
761  return (0);
762  }
763  } else {
764  kv_item = malloc(sizeof(*kv_item));
765  if (kv_item == NULL) {
766  *error_string = "Can't alloc memory";
767 
768  return (0);
769  }
770  memset(kv_item, 0, sizeof(*kv_item));
771 
772  kv_item->key = strdup(key);
773  kv_item->value = strdup(value);
774  if (kv_item->key == NULL || kv_item->value == NULL) {
775  free(kv_item);
776  *error_string = "Can't alloc memory";
777 
778  return (0);
779  }
780  list_init(&kv_item->list);
781  list_add(&kv_item->list, &data->logger_subsys_items_head);
782  }
783  add_as_string = 0;
784  break;
786  if (strcmp(key, "uid") == 0) {
787  uid = uid_determine(value);
788  if (uid == -1) {
789  *error_string = error_string_response;
790  return (0);
791  }
792  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
793  uid);
794  icmap_set_uint8_r(config_map, key_name, 1);
795  add_as_string = 0;
796  } else if (strcmp(key, "gid") == 0) {
797  gid = gid_determine(value);
798  if (gid == -1) {
799  *error_string = error_string_response;
800  return (0);
801  }
802  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
803  gid);
804  icmap_set_uint8_r(config_map, key_name, 1);
805  add_as_string = 0;
806  } else {
807  *error_string = "uidgid: Only uid and gid are allowed items";
808  return (0);
809  }
810  break;
812  if (strcmp(key, "memberaddr") != 0) {
813  *error_string = "Only memberaddr is allowed in member section";
814 
815  return (0);
816  }
817 
818  kv_item = malloc(sizeof(*kv_item));
819  if (kv_item == NULL) {
820  *error_string = "Can't alloc memory";
821 
822  return (0);
823  }
824  memset(kv_item, 0, sizeof(*kv_item));
825 
826  kv_item->key = strdup(key);
827  kv_item->value = strdup(value);
828  if (kv_item->key == NULL || kv_item->value == NULL) {
829  free(kv_item);
830  *error_string = "Can't alloc memory";
831 
832  return (0);
833  }
834  list_init(&kv_item->list);
835  list_add(&kv_item->list, &data->member_items_head);
836  add_as_string = 0;
837  break;
839  break;
841  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
842  if ((strcmp(key, "nodeid") == 0) ||
843  (strcmp(key, "quorum_votes") == 0)) {
844  val_type = ICMAP_VALUETYPE_UINT32;
845  if (safe_atoq(value, &val, val_type) != 0) {
846  goto atoi_error;
847  }
848 
849  icmap_set_uint32_r(config_map, key_name, val);
850  add_as_string = 0;
851  }
852 
853  if (strcmp(key, "ring0_addr") == 0) {
854  data->ring0_addr_added = 1;
855  }
856 
857  if (add_as_string) {
858  icmap_set_string_r(config_map, key_name, value);
859  add_as_string = 0;
860  }
861  break;
862  }
863 
864  if (add_as_string) {
865  icmap_set_string_r(config_map, path, value);
866  }
867  break;
869  if (strcmp(path, "totem.interface") == 0) {
871  data->ringnumber = 0;
872  data->mcastport = -1;
873  data->ttl = -1;
874  list_init(&data->member_items_head);
875  };
876  if (strcmp(path, "totem") == 0) {
878  };
879  if (strcmp(path, "qb") == 0) {
880  *state = MAIN_CP_CB_DATA_STATE_QB;
881  }
882  if (strcmp(path, "logging.logger_subsys") == 0) {
884  list_init(&data->logger_subsys_items_head);
885  data->subsys = NULL;
886  }
887  if (strcmp(path, "logging.logging_daemon") == 0) {
889  list_init(&data->logger_subsys_items_head);
890  data->subsys = NULL;
891  data->logging_daemon_name = NULL;
892  }
893  if (strcmp(path, "uidgid") == 0) {
895  }
896  if (strcmp(path, "totem.interface.member") == 0) {
898  }
899  if (strcmp(path, "quorum") == 0) {
901  }
902  if (strcmp(path, "quorum.device") == 0) {
904  }
905  if (strcmp(path, "nodelist") == 0) {
907  data->node_number = 0;
908  }
909  if (strcmp(path, "nodelist.node") == 0) {
911  data->ring0_addr_added = 0;
912  }
913  break;
915  switch (*state) {
917  /*
918  * Create new interface section
919  */
920  if (data->bindnetaddr != NULL) {
921  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
922  data->ringnumber);
923  icmap_set_string_r(config_map, key_name, data->bindnetaddr);
924 
925  free(data->bindnetaddr);
926  data->bindnetaddr = NULL;
927  }
928 
929  if (data->mcastaddr != NULL) {
930  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
931  data->ringnumber);
932  icmap_set_string_r(config_map, key_name, data->mcastaddr);
933 
934  free(data->mcastaddr);
935  data->mcastaddr = NULL;
936  }
937 
938  if (data->broadcast != NULL) {
939  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
940  data->ringnumber);
941  icmap_set_string_r(config_map, key_name, data->broadcast);
942 
943  free(data->broadcast);
944  data->broadcast = NULL;
945  }
946 
947  if (data->mcastport > -1) {
948  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
949  data->ringnumber);
950  icmap_set_uint16_r(config_map, key_name, data->mcastport);
951  }
952 
953  if (data->ttl > -1) {
954  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
955  data->ringnumber);
956  icmap_set_uint8_r(config_map, key_name, data->ttl);
957  }
958 
959  ii = 0;
960  for (iter = data->member_items_head.next;
961  iter != &data->member_items_head; iter = iter_next) {
962  kv_item = list_entry(iter, struct key_value_list_item, list);
963 
964  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
965  data->ringnumber, ii);
966  icmap_set_string_r(config_map, key_name, kv_item->value);
967 
968  iter_next = iter->next;
969 
970  free(kv_item->value);
971  free(kv_item->key);
972  free(kv_item);
973  ii++;
974  }
975 
976  break;
978  if (data->subsys == NULL) {
979  *error_string = "No subsys key in logger_subsys directive";
980 
981  return (0);
982  }
983 
984  for (iter = data->logger_subsys_items_head.next;
985  iter != &data->logger_subsys_items_head; iter = iter_next) {
986  kv_item = list_entry(iter, struct key_value_list_item, list);
987 
988  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
989  data->subsys, kv_item->key);
990  icmap_set_string_r(config_map, key_name, kv_item->value);
991 
992  iter_next = iter->next;
993 
994  free(kv_item->value);
995  free(kv_item->key);
996  free(kv_item);
997  }
998 
999  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1000  data->subsys);
1001  icmap_set_string_r(config_map, key_name, data->subsys);
1002 
1003  free(data->subsys);
1004 
1005  break;
1007  if (data->logging_daemon_name == NULL) {
1008  *error_string = "No name key in logging_daemon directive";
1009 
1010  return (0);
1011  }
1012 
1013  for (iter = data->logger_subsys_items_head.next;
1014  iter != &data->logger_subsys_items_head; iter = iter_next) {
1015  kv_item = list_entry(iter, struct key_value_list_item, list);
1016 
1017  if (data->subsys == NULL) {
1018  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1019  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1020  "logging.%s",
1021  kv_item->key);
1022  } else {
1023  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1024  "logging.logging_daemon.%s.%s",
1025  data->logging_daemon_name, kv_item->key);
1026  }
1027  } else {
1028  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1029  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1030  "logging.logger_subsys.%s.%s",
1031  data->subsys,
1032  kv_item->key);
1033  } else {
1034  snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
1035  "logging.logging_daemon.%s.%s.%s",
1036  data->logging_daemon_name, data->subsys,
1037  kv_item->key);
1038  }
1039  }
1040  icmap_set_string_r(config_map, key_name, kv_item->value);
1041 
1042  iter_next = iter->next;
1043 
1044  free(kv_item->value);
1045  free(kv_item->key);
1046  free(kv_item);
1047  }
1048 
1049  if (data->subsys == NULL) {
1050  if (strcmp(data->logging_daemon_name, "corosync") != 0) {
1051  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
1052  data->logging_daemon_name);
1053  icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1054  }
1055  } else {
1056  if (strcmp(data->logging_daemon_name, "corosync") == 0) {
1057  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
1058  data->subsys);
1059  icmap_set_string_r(config_map, key_name, data->subsys);
1060 
1061  } else {
1062  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
1063  data->logging_daemon_name, data->subsys);
1064  icmap_set_string_r(config_map, key_name, data->subsys);
1065  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
1066  data->logging_daemon_name, data->subsys);
1067  icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
1068  }
1069  }
1070 
1071  free(data->subsys);
1072  free(data->logging_daemon_name);
1073 
1074  break;
1076  if (!data->ring0_addr_added) {
1077  *error_string = "No ring0_addr specified for node";
1078 
1079  return (0);
1080  }
1081  data->node_number++;
1082  break;
1092  break;
1093  }
1094  break;
1095  }
1096 
1097  return (1);
1098 
1099 atoi_error:
1100  min_val = max_val = 0;
1101  /*
1102  * This is really assert, because developer ether doesn't set val_type correctly or
1103  * we've got here after some nasty memory overwrite
1104  */
1105  assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
1106 
1107  snprintf(formated_err, sizeof(formated_err),
1108  "Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
1109  key, min_val, max_val, value);
1110  *error_string = formated_err;
1111 
1112  return (0);
1113 }
1114 
1115 static int uidgid_config_parser_cb(const char *path,
1116  char *key,
1117  char *value,
1118  enum main_cp_cb_data_state *state,
1119  enum parser_cb_type type,
1120  const char **error_string,
1121  icmap_map_t config_map,
1122  void *user_data)
1123 {
1124  char key_name[ICMAP_KEYNAME_MAXLEN];
1125  int uid, gid;
1126 
1127  switch (type) {
1128  case PARSER_CB_START:
1129  break;
1130  case PARSER_CB_END:
1131  break;
1132  case PARSER_CB_ITEM:
1133  if (strcmp(path, "uidgid.uid") == 0) {
1134  uid = uid_determine(value);
1135  if (uid == -1) {
1136  *error_string = error_string_response;
1137  return (0);
1138  }
1139  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
1140  uid);
1141  icmap_set_uint8_r(config_map, key_name, 1);
1142  } else if (strcmp(path, "uidgid.gid") == 0) {
1143  gid = gid_determine(value);
1144  if (gid == -1) {
1145  *error_string = error_string_response;
1146  return (0);
1147  }
1148  snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
1149  gid);
1150  icmap_set_uint8_r(config_map, key_name, 1);
1151  } else {
1152  *error_string = "uidgid: Only uid and gid are allowed items";
1153  return (0);
1154  }
1155  break;
1157  if (strcmp(path, "uidgid") != 0) {
1158  *error_string = "uidgid: Can't add subsection different than uidgid";
1159  return (0);
1160  };
1161  break;
1162  case PARSER_CB_SECTION_END:
1163  break;
1164  }
1165 
1166  return (1);
1167 }
1168 
1169 static int read_uidgid_files_into_icmap(
1170  const char **error_string,
1171  icmap_map_t config_map)
1172 {
1173  FILE *fp;
1174  const char *dirname;
1175  DIR *dp;
1176  struct dirent *dirent;
1177  struct dirent *entry;
1178  char filename[PATH_MAX + FILENAME_MAX + 1];
1179  int res = 0;
1180  size_t len;
1181  int return_code;
1182  struct stat stat_buf;
1184  char key_name[ICMAP_KEYNAME_MAXLEN];
1185 
1186  dirname = COROSYSCONFDIR "/uidgid.d";
1187  dp = opendir (dirname);
1188 
1189  if (dp == NULL)
1190  return 0;
1191 
1192  len = offsetof(struct dirent, d_name) + FILENAME_MAX + 1;
1193 
1194  entry = malloc(len);
1195  if (entry == NULL) {
1196  res = 0;
1197  goto error_exit;
1198  }
1199 
1200  for (return_code = readdir_r(dp, entry, &dirent);
1201  dirent != NULL && return_code == 0;
1202  return_code = readdir_r(dp, entry, &dirent)) {
1203 
1204  snprintf(filename, sizeof (filename), "%s/%s", dirname, dirent->d_name);
1205  res = stat (filename, &stat_buf);
1206  if (res == 0 && S_ISREG(stat_buf.st_mode)) {
1207 
1208  fp = fopen (filename, "r");
1209  if (fp == NULL) continue;
1210 
1211  key_name[0] = 0;
1212 
1213  res = parse_section(fp, key_name, error_string, 0, state, uidgid_config_parser_cb, config_map, NULL);
1214 
1215  fclose (fp);
1216 
1217  if (res != 0) {
1218  goto error_exit;
1219  }
1220  }
1221  }
1222 
1223 error_exit:
1224  free (entry);
1225  closedir(dp);
1226 
1227  return res;
1228 }
1229 
1230 /* Read config file and load into icmap */
1231 static int read_config_file_into_icmap(
1232  const char **error_string,
1233  icmap_map_t config_map)
1234 {
1235  FILE *fp;
1236  const char *filename;
1237  char *error_reason = error_string_response;
1238  int res;
1239  char key_name[ICMAP_KEYNAME_MAXLEN];
1240  struct main_cp_cb_data data;
1242 
1243  filename = getenv ("COROSYNC_MAIN_CONFIG_FILE");
1244  if (!filename)
1245  filename = COROSYSCONFDIR "/corosync.conf";
1246 
1247  fp = fopen (filename, "r");
1248  if (fp == NULL) {
1249  char error_str[100];
1250  const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1251  snprintf (error_reason, sizeof(error_string_response),
1252  "Can't read file %s reason = (%s)",
1253  filename, error_ptr);
1254  *error_string = error_reason;
1255  return -1;
1256  }
1257 
1258  key_name[0] = 0;
1259 
1260  res = parse_section(fp, key_name, error_string, 0, state, main_config_parser_cb, config_map, &data);
1261 
1262  fclose(fp);
1263 
1264  if (res == 0) {
1265  res = read_uidgid_files_into_icmap(error_string, config_map);
1266  }
1267 
1268  if (res == 0) {
1269  snprintf (error_reason, sizeof(error_string_response),
1270  "Successfully read main configuration file '%s'.", filename);
1271  *error_string = error_reason;
1272  }
1273 
1274  return res;
1275 }
char * logging_daemon_name
Definition: coroparse.c:115
uint32_t value
struct list_head list
Definition: coroparse.c:102
struct list_head * next
Definition: list.h:47
struct list_head logger_subsys_items_head
Definition: coroparse.c:113
struct list_head member_items_head
Definition: coroparse.c:116
int coroparse_configparse(icmap_map_t config_map, const char **error_string)
Definition: coroparse.c:246
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
Definition: icmap.c:553
char * mcastaddr
Definition: coroparse.c:108
char * bindnetaddr
Definition: coroparse.c:107
#define COROSYSCONFDIR
Definition: config.h:11
Definition: list.h:46
parser_cb_type
Definition: coroparse.c:66
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
Definition: icmap.c:571
#define ICMAP_KEYNAME_MAXLEN
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:517
void * user_data
Definition: sam.c:126
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
Definition: icmap.c:541
char * broadcast
Definition: coroparse.c:109
Linked list API.
int ring0_addr_added
Definition: coroparse.c:119
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
Definition: icmap.c:529
main_cp_cb_data_state
Definition: coroparse.c:74
#define list_entry(ptr, type, member)
Definition: list.h:84
char type
Definition: totemrrp.c:518
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:90
icmap_value_types_t
Definition: icmap.h:58