]> git.proxmox.com Git - mirror_corosync.git/blame - exec/coroparse.c
votequorum: fix flag check for qdevice votes propagation
[mirror_corosync.git] / exec / coroparse.c
CommitLineData
2f552719 1/*
2ad0cdc8 2 * Copyright (c) 2006-2012 Red Hat, Inc.
2f552719
SD
3 *
4 * All rights reserved.
5 *
6 * Author: Patrick Caulfield (pcaulfie@redhat.com)
8a45e2b1 7 * Jan Friesse (jfriesse@redhat.com)
2f552719
SD
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 */
031c02f5
FDN
35
36#include <config.h>
37
2f552719
SD
38#include <sys/types.h>
39#include <sys/uio.h>
40#include <sys/socket.h>
1e0d40cd 41#include <sys/stat.h>
2f552719
SD
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>
2f552719 50#include <string.h>
ae229831 51#include <dirent.h>
6fd822c4 52#include <limits.h>
2290913d 53#include <stddef.h>
8a45e2b1
JF
54#include <grp.h>
55#include <pwd.h>
2f552719 56
8a45e2b1 57#include <corosync/list.h>
37e17e7a 58#include <qb/qbutil.h>
00434a4f 59#define LOGSYS_UTILS_ONLY 1
8ad583a5 60#include <corosync/logsys.h>
6f5e3293 61#include <corosync/icmap.h>
e1f53138 62
f763d3ba 63#include "main.h"
2f552719
SD
64#include "util.h"
65
8a45e2b1
JF
66enum parser_cb_type {
67 PARSER_CB_START,
68 PARSER_CB_END,
69 PARSER_CB_SECTION_START,
70 PARSER_CB_SECTION_END,
71 PARSER_CB_ITEM,
72};
73
74typedef int (*parser_cb_f)(const char *path,
75 char *key,
76 char *value,
77 enum parser_cb_type type,
78 const char **error_string,
79 void *user_data);
80
81enum main_cp_cb_data_state {
82 MAIN_CP_CB_DATA_STATE_NORMAL,
83 MAIN_CP_CB_DATA_STATE_TOTEM,
84 MAIN_CP_CB_DATA_STATE_INTERFACE,
85 MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS,
86 MAIN_CP_CB_DATA_STATE_UIDGID,
87 MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON,
88 MAIN_CP_CB_DATA_STATE_MEMBER,
89 MAIN_CP_CB_DATA_STATE_QUORUM,
cb5fd775 90 MAIN_CP_CB_DATA_STATE_QDEVICE,
6d0b0b14
JF
91 MAIN_CP_CB_DATA_STATE_NODELIST,
92 MAIN_CP_CB_DATA_STATE_NODELIST_NODE,
eb3d49ef 93 MAIN_CP_CB_DATA_STATE_PLOAD
8a45e2b1
JF
94};
95
96struct key_value_list_item {
97 char *key;
98 char *value;
99 struct list_head list;
100};
101
102struct main_cp_cb_data {
103 enum main_cp_cb_data_state state;
104
105 int ringnumber;
106 char *bindnetaddr;
107 char *mcastaddr;
108 char *broadcast;
109 int mcastport;
110 int ttl;
111
112 struct list_head logger_subsys_items_head;
113 char *subsys;
114 char *logging_daemon_name;
115 struct list_head member_items_head;
6d0b0b14
JF
116
117 int node_number;
118 int ring0_addr_added;
8a45e2b1
JF
119};
120
121static int read_config_file_into_icmap(
23c64c64 122 const char **error_string);
2f552719
SD
123static char error_string_response[512];
124
8a45e2b1
JF
125static int uid_determine (const char *req_user)
126{
127 int pw_uid = 0;
128 struct passwd passwd;
129 struct passwd* pwdptr = &passwd;
130 struct passwd* temp_pwd_pt;
131 char *pwdbuffer;
132 int pwdlinelen;
133
134 pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
135
136 if (pwdlinelen == -1) {
137 pwdlinelen = 256;
138 }
139
140 pwdbuffer = malloc (pwdlinelen);
141
142 if ((getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) != 0) {
143 sprintf (error_string_response,
144 "The '%s' user is not found in /etc/passwd, please read the documentation.",
145 req_user);
146 return (-1);
147 }
148 pw_uid = passwd.pw_uid;
149 free (pwdbuffer);
150
151 return pw_uid;
152}
153
154static int gid_determine (const char *req_group)
155{
7c8e83ac 156 int corosync_gid = 0;
8a45e2b1
JF
157 struct group group;
158 struct group * grpptr = &group;
159 struct group * temp_grp_pt;
160 char *grpbuffer;
161 int grplinelen;
162
163 grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
164
165 if (grplinelen == -1) {
166 grplinelen = 256;
167 }
168
169 grpbuffer = malloc (grplinelen);
170
171 if ((getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) != 0) {
172 sprintf (error_string_response,
173 "The '%s' group is not found in /etc/group, please read the documentation.",
174 req_group);
175 return (-1);
176 }
7c8e83ac 177 corosync_gid = group.gr_gid;
8a45e2b1 178 free (grpbuffer);
2f552719 179
7c8e83ac 180 return corosync_gid;
8a45e2b1 181}
3ffb151a
FDN
182static char *strchr_rs (const char *haystack, int byte)
183{
184 const char *end_address = strchr (haystack, byte);
185 if (end_address) {
186 end_address += 1; /* skip past { or = */
8a45e2b1
JF
187
188 while (*end_address == ' ' || *end_address == '\t')
189 end_address++;
3ffb151a
FDN
190 }
191
192 return ((char *) end_address);
193}
194
f763d3ba 195int coroparse_configparse (const char **error_string)
2f552719 196{
8a45e2b1 197 if (read_config_file_into_icmap(error_string)) {
2f552719
SD
198 return -1;
199 }
200
201 return 0;
202}
203
2f552719
SD
204static char *remove_whitespace(char *string)
205{
8a45e2b1
JF
206 char *start;
207 char *end;
2f552719 208
8a45e2b1
JF
209 start = string;
210 while (*start == ' ' || *start == '\t')
211 start++;
212
213 end = start+(strlen(start))-1;
2f552719
SD
214 while ((*end == ' ' || *end == '\t' || *end == ':' || *end == '{') && end > start)
215 end--;
216 if (end != start)
217 *(end+1) = '\0';
218
219 return start;
220}
221
ae229831 222
ae229831 223
2f552719 224static int parse_section(FILE *fp,
8a45e2b1 225 char *path,
ae229831 226 const char **error_string,
8a45e2b1
JF
227 parser_cb_f parser_cb,
228 void *user_data)
2f552719
SD
229{
230 char line[512];
231 int i;
232 char *loc;
99db3567 233 int ignore_line;
8a45e2b1
JF
234 char new_keyname[ICMAP_KEYNAME_MAXLEN];
235
236 if (strcmp(path, "") == 0) {
237 parser_cb("", NULL, NULL, PARSER_CB_START, error_string, user_data);
238 }
2f552719 239
94b64352
JF
240 while (fgets (line, sizeof (line), fp)) {
241 if (strlen(line) > 0) {
242 if (line[strlen(line) - 1] == '\n')
243 line[strlen(line) - 1] = '\0';
244 if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
245 line[strlen(line) - 1] = '\0';
246 }
2f552719
SD
247 /*
248 * Clear out white space and tabs
249 */
250 for (i = strlen (line) - 1; i > -1; i--) {
251 if (line[i] == '\t' || line[i] == ' ') {
252 line[i] = '\0';
253 } else {
254 break;
255 }
256 }
99db3567
JF
257
258 ignore_line = 1;
259 for (i = 0; i < strlen (line); i++) {
260 if (line[i] != '\t' && line[i] != ' ') {
261 if (line[i] != '#')
262 ignore_line = 0;
263
264 break;
265 }
266 }
2f552719
SD
267 /*
268 * Clear out comments and empty lines
269 */
99db3567 270 if (ignore_line) {
2f552719
SD
271 continue;
272 }
273
274 /* New section ? */
283011c6 275 if ((loc = strchr_rs (line, '{'))) {
2f552719
SD
276 char *section = remove_whitespace(line);
277
278 loc--;
279 *loc = '\0';
8a45e2b1
JF
280
281 strcpy(new_keyname, path);
282 if (strcmp(path, "") != 0) {
283 strcat(new_keyname, ".");
ae229831 284 }
8a45e2b1 285 strcat(new_keyname, section);
ae229831 286
8a45e2b1
JF
287 if (!parser_cb(new_keyname, NULL, NULL, PARSER_CB_SECTION_START, error_string, user_data)) {
288 return -1;
289 }
290
291 if (parse_section(fp, new_keyname, error_string, parser_cb, user_data))
2f552719
SD
292 return -1;
293 }
294
295 /* New key/value */
283011c6 296 if ((loc = strchr_rs (line, ':'))) {
2f552719
SD
297 char *key;
298 char *value;
299
300 *(loc-1) = '\0';
301 key = remove_whitespace(line);
302 value = remove_whitespace(loc);
8a45e2b1
JF
303
304 strcpy(new_keyname, path);
305 if (strcmp(path, "") != 0) {
306 strcat(new_keyname, ".");
307 }
308 strcat(new_keyname, key);
309
310 if (!parser_cb(new_keyname, key, value, PARSER_CB_ITEM, error_string, user_data)) {
311 return -1;
ae229831 312 }
2f552719
SD
313 }
314
8236a087 315 if (strchr_rs (line, '}')) {
8a45e2b1
JF
316 if (!parser_cb(path, NULL, NULL, PARSER_CB_SECTION_END, error_string, user_data)) {
317 return -1;
318 }
319
2f552719
SD
320 return 0;
321 }
322 }
323
8a45e2b1 324 if (strcmp(path, "") != 0) {
2f552719
SD
325 *error_string = "Missing closing brace";
326 return -1;
327 }
328
8a45e2b1
JF
329 if (strcmp(path, "") == 0) {
330 parser_cb("", NULL, NULL, PARSER_CB_END, error_string, user_data);
331 }
332
2f552719
SD
333 return 0;
334}
335
0929dcb6
JF
336static int safe_atoi(const char *str, int *res)
337{
338 int val;
339 char *endptr;
340
341 errno = 0;
342
343 val = strtol(str, &endptr, 10);
344 if (errno == ERANGE) {
345 return (-1);
346 }
347
348 if (endptr == str) {
349 return (-1);
350 }
351
352 if (*endptr != '\0') {
353 return (-1);
354 }
355
356 *res = val;
357 return (0);
358}
359
360
8a45e2b1
JF
361static int main_config_parser_cb(const char *path,
362 char *key,
363 char *value,
364 enum parser_cb_type type,
365 const char **error_string,
366 void *user_data)
ae229831 367{
8a45e2b1
JF
368 int i;
369 int add_as_string;
370 char key_name[ICMAP_KEYNAME_MAXLEN];
0929dcb6 371 static char formated_err[256];
8a45e2b1
JF
372 struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
373 struct key_value_list_item *kv_item;
374 struct list_head *iter, *iter_next;
375 int uid, gid;
376
377 switch (type) {
378 case PARSER_CB_START:
379 memset(data, 0, sizeof(struct main_cp_cb_data));
380 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
381 break;
382 case PARSER_CB_END:
383 break;
384 case PARSER_CB_ITEM:
385 add_as_string = 1;
386
387 switch (data->state) {
388 case MAIN_CP_CB_DATA_STATE_NORMAL:
389 break;
eb3d49ef
FDN
390 case MAIN_CP_CB_DATA_STATE_PLOAD:
391 if ((strcmp(path, "pload.count") == 0) ||
392 (strcmp(path, "pload.size") == 0)) {
393 if (safe_atoi(value, &i) != 0) {
394 goto atoi_error;
395 }
396 icmap_set_uint32(path, i);
397 add_as_string = 0;
398 }
399 break;
8a45e2b1
JF
400 case MAIN_CP_CB_DATA_STATE_QUORUM:
401 if ((strcmp(path, "quorum.expected_votes") == 0) ||
402 (strcmp(path, "quorum.votes") == 0) ||
10098dba 403 (strcmp(path, "quorum.last_man_standing_window") == 0) ||
8a45e2b1 404 (strcmp(path, "quorum.leaving_timeout") == 0)) {
0929dcb6
JF
405 if (safe_atoi(value, &i) != 0) {
406 goto atoi_error;
407 }
8a45e2b1
JF
408 icmap_set_uint32(path, i);
409 add_as_string = 0;
410 }
411
9589611d 412 if ((strcmp(path, "quorum.two_node") == 0) ||
2d7a8ab2 413 (strcmp(path, "quorum.allow_downscale") == 0) ||
e8d0af0b 414 (strcmp(path, "quorum.wait_for_all") == 0) ||
b41372c6 415 (strcmp(path, "quorum.auto_tie_breaker") == 0) ||
769fc913 416 (strcmp(path, "quorum.last_man_standing") == 0)) {
0929dcb6
JF
417 if (safe_atoi(value, &i) != 0) {
418 goto atoi_error;
419 }
8a45e2b1
JF
420 icmap_set_uint8(path, i);
421 add_as_string = 0;
422 }
423 break;
cb5fd775
FDN
424 case MAIN_CP_CB_DATA_STATE_QDEVICE:
425 if ((strcmp(path, "quorum.device.timeout") == 0) ||
426 (strcmp(path, "quorum.device.votes") == 0)) {
427 if (safe_atoi(value, &i) != 0) {
428 goto atoi_error;
429 }
430 icmap_set_uint32(path, i);
431 add_as_string = 0;
432 }
8a45e2b1
JF
433 case MAIN_CP_CB_DATA_STATE_TOTEM:
434 if ((strcmp(path, "totem.version") == 0) ||
435 (strcmp(path, "totem.nodeid") == 0) ||
436 (strcmp(path, "totem.threads") == 0) ||
437 (strcmp(path, "totem.token") == 0) ||
438 (strcmp(path, "totem.token_retransmit") == 0) ||
439 (strcmp(path, "totem.hold") == 0) ||
440 (strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
441 (strcmp(path, "totem.join") == 0) ||
442 (strcmp(path, "totem.send_join") == 0) ||
443 (strcmp(path, "totem.consensus") == 0) ||
444 (strcmp(path, "totem.merge") == 0) ||
445 (strcmp(path, "totem.downcheck") == 0) ||
446 (strcmp(path, "totem.fail_recv_const") == 0) ||
447 (strcmp(path, "totem.seqno_unchanged_const") == 0) ||
448 (strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
449 (strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
450 (strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
451 (strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
452 (strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
453 (strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
454 (strcmp(path, "totem.max_network_delay") == 0) ||
455 (strcmp(path, "totem.window_size") == 0) ||
456 (strcmp(path, "totem.max_messages") == 0) ||
457 (strcmp(path, "totem.miss_count_const") == 0) ||
458 (strcmp(path, "totem.netmtu") == 0)) {
0929dcb6
JF
459 if (safe_atoi(value, &i) != 0) {
460 goto atoi_error;
461 }
8a45e2b1
JF
462 icmap_set_uint32(path, i);
463 add_as_string = 0;
464 }
8cdd2fc4
JF
465 if (strcmp(path, "totem.crypto_type") == 0) {
466 if ((strcmp(value, "nss") != 0) &&
467 (strcmp(value, "aes256") != 0)) {
468 *error_string = "Invalid crypto type";
469
470 return (0);
471 }
472 }
ab1675f0
JF
473 if (strcmp(path, "totem.crypto_cipher") == 0) {
474 if ((strcmp(value, "none") != 0) &&
475 (strcmp(value, "aes256") != 0)) {
476 *error_string = "Invalid cipher type";
477
478 return (0);
479 }
480 }
481 if (strcmp(path, "totem.crypto_hash") == 0) {
482 if ((strcmp(value, "none") != 0) &&
e57b5b9e 483 (strcmp(value, "md5") != 0) &&
4a2d5036 484 (strcmp(value, "sha1") != 0) &&
4a2d5036
FDN
485 (strcmp(value, "sha256") != 0) &&
486 (strcmp(value, "sha384") != 0) &&
487 (strcmp(value, "sha512") != 0)) {
ab1675f0
JF
488 *error_string = "Invalid hash type";
489
490 return (0);
491 }
492 }
a919908e
SD
493 break;
494
8a45e2b1
JF
495 case MAIN_CP_CB_DATA_STATE_INTERFACE:
496 if (strcmp(path, "totem.interface.ringnumber") == 0) {
0929dcb6
JF
497 if (safe_atoi(value, &i) != 0) {
498 goto atoi_error;
499 }
500
501 data->ringnumber = i;
8a45e2b1
JF
502 add_as_string = 0;
503 }
504 if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
505 data->bindnetaddr = strdup(value);
506 add_as_string = 0;
507 }
508 if (strcmp(path, "totem.interface.mcastaddr") == 0) {
509 data->mcastaddr = strdup(value);
510 add_as_string = 0;
511 }
512 if (strcmp(path, "totem.interface.broadcast") == 0) {
513 data->broadcast = strdup(value);
514 add_as_string = 0;
515 }
516 if (strcmp(path, "totem.interface.mcastport") == 0) {
0929dcb6
JF
517 if (safe_atoi(value, &i) != 0) {
518 goto atoi_error;
519 }
520 data->mcastport = i;
8a45e2b1
JF
521 if (data->mcastport < 0 || data->mcastport > 65535) {
522 *error_string = "Invalid multicast port (should be 0..65535)";
523
524 return (0);
525 };
526 add_as_string = 0;
527 }
528 if (strcmp(path, "totem.interface.ttl") == 0) {
0929dcb6
JF
529 if (safe_atoi(value, &i) != 0) {
530 goto atoi_error;
531 }
532 data->ttl = i;
8a45e2b1
JF
533 if (data->ttl < 0 || data->ttl > 255) {
534 *error_string = "Invalid TTL (should be 0..255)";
535
536 return (0);
537 };
538 add_as_string = 0;
539 }
540 break;
541 case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
542 if (strcmp(key, "subsys") == 0) {
543 data->subsys = strdup(value);
544 if (data->subsys == NULL) {
545 *error_string = "Can't alloc memory";
546
547 return (0);
548 }
549 } else {
550 kv_item = malloc(sizeof(*kv_item));
551 if (kv_item == NULL) {
552 *error_string = "Can't alloc memory";
553
554 return (0);
555 }
556 memset(kv_item, 0, sizeof(*kv_item));
557
558 kv_item->key = strdup(key);
559 kv_item->value = strdup(value);
560 if (kv_item->key == NULL || kv_item->value == NULL) {
561 free(kv_item);
562 *error_string = "Can't alloc memory";
563
564 return (0);
565 }
566 list_init(&kv_item->list);
567 list_add(&kv_item->list, &data->logger_subsys_items_head);
568 }
569 add_as_string = 0;
570 break;
571 case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
572 if (strcmp(key, "subsys") == 0) {
573 data->subsys = strdup(value);
574 if (data->subsys == NULL) {
575 *error_string = "Can't alloc memory";
576
577 return (0);
578 }
579 } else if (strcmp(key, "name") == 0) {
580 data->logging_daemon_name = strdup(value);
581 if (data->logging_daemon_name == NULL) {
582 *error_string = "Can't alloc memory";
583
584 return (0);
585 }
586 } else {
587 kv_item = malloc(sizeof(*kv_item));
588 if (kv_item == NULL) {
589 *error_string = "Can't alloc memory";
590
591 return (0);
592 }
593 memset(kv_item, 0, sizeof(*kv_item));
594
595 kv_item->key = strdup(key);
596 kv_item->value = strdup(value);
597 if (kv_item->key == NULL || kv_item->value == NULL) {
598 free(kv_item);
599 *error_string = "Can't alloc memory";
600
601 return (0);
602 }
603 list_init(&kv_item->list);
604 list_add(&kv_item->list, &data->logger_subsys_items_head);
605 }
606 add_as_string = 0;
607 break;
608 case MAIN_CP_CB_DATA_STATE_UIDGID:
609 if (strcmp(key, "uid") == 0) {
610 uid = uid_determine(value);
611 if (uid == -1) {
612 *error_string = error_string_response;
613 return (0);
614 }
615 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
616 uid);
617 icmap_set_uint8(key_name, 1);
618 add_as_string = 0;
619 } else if (strcmp(key, "gid") == 0) {
620 gid = gid_determine(value);
621 if (gid == -1) {
622 *error_string = error_string_response;
623 return (0);
624 }
625 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
626 gid);
627 icmap_set_uint8(key_name, 1);
628 add_as_string = 0;
629 } else {
630 *error_string = "uidgid: Only uid and gid are allowed items";
631 return (0);
632 }
633 break;
634 case MAIN_CP_CB_DATA_STATE_MEMBER:
635 if (strcmp(key, "memberaddr") != 0) {
636 *error_string = "Only memberaddr is allowed in member section";
637
638 return (0);
639 }
640
641 kv_item = malloc(sizeof(*kv_item));
642 if (kv_item == NULL) {
643 *error_string = "Can't alloc memory";
644
645 return (0);
646 }
647 memset(kv_item, 0, sizeof(*kv_item));
648
649 kv_item->key = strdup(key);
650 kv_item->value = strdup(value);
651 if (kv_item->key == NULL || kv_item->value == NULL) {
652 free(kv_item);
653 *error_string = "Can't alloc memory";
654
655 return (0);
656 }
657 list_init(&kv_item->list);
658 list_add(&kv_item->list, &data->member_items_head);
659 add_as_string = 0;
660 break;
6d0b0b14
JF
661 case MAIN_CP_CB_DATA_STATE_NODELIST:
662 break;
663 case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
664 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
665 if ((strcmp(key, "nodeid") == 0) ||
666 (strcmp(key, "quorum_votes") == 0)) {
0929dcb6
JF
667 if (safe_atoi(value, &i) != 0) {
668 goto atoi_error;
669 }
670
6d0b0b14
JF
671 icmap_set_uint32(key_name, i);
672 add_as_string = 0;
673 }
674
675 if (strcmp(key, "ring0_addr") == 0) {
676 data->ring0_addr_added = 1;
677 }
678
679 if (add_as_string) {
680 icmap_set_string(key_name, value);
681 add_as_string = 0;
682 }
683 break;
ae229831
JF
684 }
685
8a45e2b1
JF
686 if (add_as_string) {
687 icmap_set_string(path, value);
688 }
689 break;
690 case PARSER_CB_SECTION_START:
691 if (strcmp(path, "totem.interface") == 0) {
692 data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
693 data->ringnumber = 0;
694 data->mcastport = -1;
695 data->ttl = -1;
696 list_init(&data->member_items_head);
697 };
698 if (strcmp(path, "totem") == 0) {
699 data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
700 };
701
702 if (strcmp(path, "logging.logger_subsys") == 0) {
703 data->state = MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS;
704 list_init(&data->logger_subsys_items_head);
705 data->subsys = NULL;
706 }
707 if (strcmp(path, "logging.logging_daemon") == 0) {
708 data->state = MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON;
709 list_init(&data->logger_subsys_items_head);
710 data->subsys = NULL;
711 data->logging_daemon_name = NULL;
712 }
713 if (strcmp(path, "uidgid") == 0) {
714 data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
ae229831 715 }
8a45e2b1
JF
716 if (strcmp(path, "totem.interface.member") == 0) {
717 data->state = MAIN_CP_CB_DATA_STATE_MEMBER;
718 }
719 if (strcmp(path, "quorum") == 0) {
720 data->state = MAIN_CP_CB_DATA_STATE_QUORUM;
721 }
cb5fd775
FDN
722 if (strcmp(path, "quorum.device") == 0) {
723 data->state = MAIN_CP_CB_DATA_STATE_QDEVICE;
724 }
6d0b0b14
JF
725 if (strcmp(path, "nodelist") == 0) {
726 data->state = MAIN_CP_CB_DATA_STATE_NODELIST;
727 data->node_number = 0;
728 }
729 if (strcmp(path, "nodelist.node") == 0) {
730 data->state = MAIN_CP_CB_DATA_STATE_NODELIST_NODE;
731 data->ring0_addr_added = 0;
732 }
8a45e2b1
JF
733 break;
734 case PARSER_CB_SECTION_END:
735 switch (data->state) {
736 case MAIN_CP_CB_DATA_STATE_NORMAL:
737 break;
eb3d49ef
FDN
738 case MAIN_CP_CB_DATA_STATE_PLOAD:
739 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
740 break;
8a45e2b1
JF
741 case MAIN_CP_CB_DATA_STATE_INTERFACE:
742 /*
743 * Create new interface section
744 */
745 if (data->bindnetaddr != NULL) {
746 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
747 data->ringnumber);
748 icmap_set_string(key_name, data->bindnetaddr);
749
750 free(data->bindnetaddr);
751 data->bindnetaddr = NULL;
8a45e2b1
JF
752 }
753
754 if (data->mcastaddr != NULL) {
755 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
756 data->ringnumber);
757 icmap_set_string(key_name, data->mcastaddr);
758
759 free(data->mcastaddr);
760 data->mcastaddr = NULL;
761 }
762
763 if (data->broadcast != NULL) {
764 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
765 data->ringnumber);
766 icmap_set_string(key_name, data->broadcast);
767
768 free(data->broadcast);
769 data->broadcast = NULL;
770 }
771
772 if (data->mcastport > -1) {
773 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
774 data->ringnumber);
775 icmap_set_uint16(key_name, data->mcastport);
776 }
777
778 if (data->ttl > -1) {
779 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
780 data->ringnumber);
781 icmap_set_uint8(key_name, data->ttl);
782 }
783
784 i = 0;
785 for (iter = data->member_items_head.next;
786 iter != &data->member_items_head; iter = iter_next) {
787 kv_item = list_entry(iter, struct key_value_list_item, list);
788
789 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
790 data->ringnumber, i);
791 icmap_set_string(key_name, kv_item->value);
792
793 iter_next = iter->next;
794
795 free(kv_item->value);
796 free(kv_item->key);
797 free(kv_item);
798 i++;
799 }
800
801 data->state = MAIN_CP_CB_DATA_STATE_TOTEM;
802 break;
803 case MAIN_CP_CB_DATA_STATE_TOTEM:
804 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
805 break;
806 case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
807 if (data->subsys == NULL) {
808 *error_string = "No subsys key in logger_subsys directive";
809
810 return (0);
811 }
812
813 for (iter = data->logger_subsys_items_head.next;
814 iter != &data->logger_subsys_items_head; iter = iter_next) {
815 kv_item = list_entry(iter, struct key_value_list_item, list);
816
817 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
818 data->subsys, kv_item->key);
819 icmap_set_string(key_name, kv_item->value);
820
821 iter_next = iter->next;
822
823 free(kv_item->value);
824 free(kv_item->key);
825 free(kv_item);
826 }
827
828 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
829 data->subsys);
830 icmap_set_string(key_name, data->subsys);
831
832 free(data->subsys);
833
834 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
835 break;
836 case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
837 if (data->logging_daemon_name == NULL) {
838 *error_string = "No name key in logging_daemon directive";
839
840 return (0);
841 }
842
843 for (iter = data->logger_subsys_items_head.next;
844 iter != &data->logger_subsys_items_head; iter = iter_next) {
845 kv_item = list_entry(iter, struct key_value_list_item, list);
846
847 if (data->subsys == NULL) {
848 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
849 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
850 "logging.%s",
851 kv_item->key);
852 } else {
853 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
854 "logging.logging_daemon.%s.%s",
855 data->logging_daemon_name, kv_item->key);
856 }
857 } else {
858 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
859 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
860 "logging.logger_subsys.%s.%s",
861 data->subsys,
862 kv_item->key);
863 } else {
864 snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
865 "logging.logging_daemon.%s.%s.%s",
866 data->logging_daemon_name, data->subsys,
867 kv_item->key);
868 }
869 }
870 icmap_set_string(key_name, kv_item->value);
871
872 iter_next = iter->next;
873
874 free(kv_item->value);
875 free(kv_item->key);
876 free(kv_item);
877 }
878
879 if (data->subsys == NULL) {
880 if (strcmp(data->logging_daemon_name, "corosync") != 0) {
881 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
882 data->logging_daemon_name);
883 icmap_set_string(key_name, data->logging_daemon_name);
884 }
885 } else {
886 if (strcmp(data->logging_daemon_name, "corosync") == 0) {
887 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
888 data->subsys);
889 icmap_set_string(key_name, data->subsys);
890
891 } else {
892 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
893 data->logging_daemon_name, data->subsys);
894 icmap_set_string(key_name, data->subsys);
895 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
896 data->logging_daemon_name, data->subsys);
897 icmap_set_string(key_name, data->logging_daemon_name);
898 }
899 }
900
901 free(data->subsys);
902 free(data->logging_daemon_name);
903
904 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
905 break;
906 case MAIN_CP_CB_DATA_STATE_UIDGID:
907 data->state = MAIN_CP_CB_DATA_STATE_UIDGID;
908 break;
909 case MAIN_CP_CB_DATA_STATE_MEMBER:
910 data->state = MAIN_CP_CB_DATA_STATE_INTERFACE;
911 break;
912 case MAIN_CP_CB_DATA_STATE_QUORUM:
913 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
914 break;
cb5fd775
FDN
915 case MAIN_CP_CB_DATA_STATE_QDEVICE:
916 data->state = MAIN_CP_CB_DATA_STATE_QUORUM;
917 break;
6d0b0b14
JF
918 case MAIN_CP_CB_DATA_STATE_NODELIST:
919 data->state = MAIN_CP_CB_DATA_STATE_NORMAL;
920 break;
921 case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
922 if (!data->ring0_addr_added) {
923 *error_string = "No ring0_addr specified for node";
924
925 return (0);
926 }
927 data->node_number++;
928 data->state = MAIN_CP_CB_DATA_STATE_NODELIST;
929 break;
8a45e2b1
JF
930 }
931 break;
ae229831
JF
932 }
933
8a45e2b1 934 return (1);
0929dcb6
JF
935
936atoi_error:
937 snprintf(formated_err, sizeof(formated_err),
938 "Value of key \"%s\" must be integer, but \"%s\" was given", key, value);
939 *error_string = formated_err;
940
941 return (0);
8a45e2b1
JF
942}
943
944static int uidgid_config_parser_cb(const char *path,
945 char *key,
946 char *value,
947 enum parser_cb_type type,
948 const char **error_string,
949 void *user_data)
950{
951 char key_name[ICMAP_KEYNAME_MAXLEN];
952 int uid, gid;
953
954 switch (type) {
955 case PARSER_CB_START:
956 break;
957 case PARSER_CB_END:
958 break;
959 case PARSER_CB_ITEM:
960 if (strcmp(path, "uidgid.uid") == 0) {
961 uid = uid_determine(value);
962 if (uid == -1) {
963 *error_string = error_string_response;
964 return (0);
965 }
966 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.uid.%u",
967 uid);
968 icmap_set_uint8(key_name, 1);
92ead610 969 } else if (strcmp(path, "uidgid.gid") == 0) {
8a45e2b1
JF
970 gid = gid_determine(value);
971 if (gid == -1) {
972 *error_string = error_string_response;
973 return (0);
974 }
975 snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.gid.%u",
976 gid);
977 icmap_set_uint8(key_name, 1);
978 } else {
ae229831 979 *error_string = "uidgid: Only uid and gid are allowed items";
8a45e2b1 980 return (0);
ae229831 981 }
8a45e2b1
JF
982 break;
983 case PARSER_CB_SECTION_START:
984 if (strcmp(path, "uidgid") != 0) {
985 *error_string = "uidgid: Can't add subsection different then uidgid";
986 return (0);
987 };
988 break;
989 case PARSER_CB_SECTION_END:
990 break;
ae229831 991 }
2f552719 992
8a45e2b1 993 return (1);
ae229831
JF
994}
995
8a45e2b1 996static int read_uidgid_files_into_icmap(
ae229831
JF
997 const char **error_string)
998{
999 FILE *fp;
1000 const char *dirname;
1001 DIR *dp;
1002 struct dirent *dirent;
2290913d 1003 struct dirent *entry;
1bd8aba6 1004 char filename[PATH_MAX + FILENAME_MAX + 1];
ae229831 1005 int res = 0;
2290913d
AS
1006 size_t len;
1007 int return_code;
1e0d40cd 1008 struct stat stat_buf;
8a45e2b1 1009 char key_name[ICMAP_KEYNAME_MAXLEN];
ae229831 1010
2135d91c 1011 dirname = COROSYSCONFDIR "/uidgid.d";
ae229831
JF
1012 dp = opendir (dirname);
1013
1014 if (dp == NULL)
1015 return 0;
1016
eda1e364
JF
1017 len = offsetof(struct dirent, d_name) + NAME_MAX + 1;
1018
2290913d 1019 entry = malloc(len);
eda1e364 1020 if (entry == NULL) {
c2a39cb8
JF
1021 res = 0;
1022 goto error_exit;
eda1e364 1023 }
2290913d
AS
1024
1025 for (return_code = readdir_r(dp, entry, &dirent);
1026 dirent != NULL && return_code == 0;
1027 return_code = readdir_r(dp, entry, &dirent)) {
1028
1e0d40cd
SD
1029 snprintf(filename, sizeof (filename), "%s/%s", dirname, dirent->d_name);
1030 stat (filename, &stat_buf);
1031 if (S_ISREG(stat_buf.st_mode)) {
ae229831
JF
1032
1033 fp = fopen (filename, "r");
1034 if (fp == NULL) continue;
1035
8a45e2b1
JF
1036 key_name[0] = 0;
1037
1038 res = parse_section(fp, key_name, error_string, uidgid_config_parser_cb, NULL);
ae229831
JF
1039
1040 fclose (fp);
1041
1042 if (res != 0) {
1043 goto error_exit;
1044 }
1045 }
1046 }
1047
1048error_exit:
2290913d 1049 free (entry);
ae229831
JF
1050 closedir(dp);
1051
1052 return res;
1053}
2f552719 1054
8a45e2b1
JF
1055/* Read config file and load into icmap */
1056static int read_config_file_into_icmap(
23c64c64 1057 const char **error_string)
2f552719
SD
1058{
1059 FILE *fp;
23c64c64 1060 const char *filename;
2f552719
SD
1061 char *error_reason = error_string_response;
1062 int res;
8a45e2b1
JF
1063 char key_name[ICMAP_KEYNAME_MAXLEN];
1064 struct main_cp_cb_data data;
2f552719
SD
1065
1066 filename = getenv ("COROSYNC_MAIN_CONFIG_FILE");
1067 if (!filename)
2135d91c 1068 filename = COROSYSCONFDIR "/corosync.conf";
2f552719
SD
1069
1070 fp = fopen (filename, "r");
23c64c64 1071 if (fp == NULL) {
20f3331d 1072 char error_str[100];
37e17e7a 1073 const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
870046d0 1074 snprintf (error_reason, sizeof(error_string_response),
3131601c 1075 "Can't read file %s reason = (%s)",
00434a4f 1076 filename, error_ptr);
2f552719
SD
1077 *error_string = error_reason;
1078 return -1;
1079 }
1080
8a45e2b1
JF
1081 key_name[0] = 0;
1082
1083 res = parse_section(fp, key_name, error_string, main_config_parser_cb, &data);
2f552719
SD
1084
1085 fclose(fp);
1086
ae229831 1087 if (res == 0) {
8a45e2b1 1088 res = read_uidgid_files_into_icmap(error_string);
ae229831
JF
1089 }
1090
94b64352
JF
1091 if (res == 0) {
1092 snprintf (error_reason, sizeof(error_string_response),
3131601c 1093 "Successfully read main configuration file '%s'.", filename);
94b64352
JF
1094 *error_string = error_reason;
1095 }
2f552719
SD
1096
1097 return res;
1098}