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