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