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