]> git.proxmox.com Git - mirror_corosync.git/blob - exec/totemconfig.c
totemconfig: Remove support for 3des
[mirror_corosync.git] / exec / totemconfig.c
1 /*
2 * Copyright (c) 2002-2005 MontaVista Software, Inc.
3 * Copyright (c) 2006-2018 Red Hat, Inc.
4 *
5 * All rights reserved.
6 *
7 * Author: Steven Dake (sdake@redhat.com)
8 * Jan Friesse (jfriesse@redhat.com)
9 *
10 * This software licensed under BSD license, the text of which follows:
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * - Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * - Neither the name of the MontaVista Software, Inc. nor the names of its
21 * contributors may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #include <config.h>
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <sys/socket.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <ifaddrs.h>
49 #include <netdb.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <sys/param.h>
53 #include <sys/utsname.h>
54
55 #include <corosync/swab.h>
56 #include <qb/qblist.h>
57 #include <qb/qbdefs.h>
58 #include <libknet.h>
59 #include <corosync/totem/totem.h>
60 #include <corosync/config.h>
61 #include <corosync/logsys.h>
62 #include <corosync/icmap.h>
63
64 #include "util.h"
65 #include "totemconfig.h"
66
67 #define TOKEN_RETRANSMITS_BEFORE_LOSS_CONST 4
68 #define TOKEN_TIMEOUT 1000
69 #define TOKEN_WARNING 75
70 #define TOKEN_COEFFICIENT 650
71 #define JOIN_TIMEOUT 50
72 #define MERGE_TIMEOUT 200
73 #define DOWNCHECK_TIMEOUT 1000
74 #define FAIL_TO_RECV_CONST 2500
75 #define SEQNO_UNCHANGED_CONST 30
76 #define MINIMUM_TIMEOUT (int)(1000/HZ)*3
77 #define MAX_NETWORK_DELAY 50
78 #define WINDOW_SIZE 50
79 #define MAX_MESSAGES 17
80 #define MISS_COUNT_CONST 5
81
82 /* These currently match the defaults in libknet.h */
83 #define KNET_PING_INTERVAL 1000
84 #define KNET_PING_TIMEOUT 2000
85 #define KNET_PING_PRECISION 2048
86 #define KNET_PONG_COUNT 2
87 #define KNET_PMTUD_INTERVAL 30
88 #define KNET_DEFAULT_TRANSPORT KNET_TRANSPORT_UDP
89
90 #define DEFAULT_PORT 5405
91
92 static char error_string_response[768];
93
94 static void add_totem_config_notification(struct totem_config *totem_config);
95
96 static void *totem_get_param_by_name(struct totem_config *totem_config, const char *param_name)
97 {
98 if (strcmp(param_name, "totem.token") == 0)
99 return &totem_config->token_timeout;
100 if (strcmp(param_name, "totem.token_warning") == 0)
101 return &totem_config->token_warning;
102 if (strcmp(param_name, "totem.token_retransmit") == 0)
103 return &totem_config->token_retransmit_timeout;
104 if (strcmp(param_name, "totem.hold") == 0)
105 return &totem_config->token_hold_timeout;
106 if (strcmp(param_name, "totem.token_retransmits_before_loss_const") == 0)
107 return &totem_config->token_retransmits_before_loss_const;
108 if (strcmp(param_name, "totem.join") == 0)
109 return &totem_config->join_timeout;
110 if (strcmp(param_name, "totem.send_join") == 0)
111 return &totem_config->send_join_timeout;
112 if (strcmp(param_name, "totem.consensus") == 0)
113 return &totem_config->consensus_timeout;
114 if (strcmp(param_name, "totem.merge") == 0)
115 return &totem_config->merge_timeout;
116 if (strcmp(param_name, "totem.downcheck") == 0)
117 return &totem_config->downcheck_timeout;
118 if (strcmp(param_name, "totem.fail_recv_const") == 0)
119 return &totem_config->fail_to_recv_const;
120 if (strcmp(param_name, "totem.seqno_unchanged_const") == 0)
121 return &totem_config->seqno_unchanged_const;
122 if (strcmp(param_name, "totem.heartbeat_failures_allowed") == 0)
123 return &totem_config->heartbeat_failures_allowed;
124 if (strcmp(param_name, "totem.max_network_delay") == 0)
125 return &totem_config->max_network_delay;
126 if (strcmp(param_name, "totem.window_size") == 0)
127 return &totem_config->window_size;
128 if (strcmp(param_name, "totem.max_messages") == 0)
129 return &totem_config->max_messages;
130 if (strcmp(param_name, "totem.miss_count_const") == 0)
131 return &totem_config->miss_count_const;
132 if (strcmp(param_name, "totem.knet_pmtud_interval") == 0)
133 return &totem_config->knet_pmtud_interval;
134 if (strcmp(param_name, "totem.knet_compression_threshold") == 0)
135 return &totem_config->knet_compression_threshold;
136 if (strcmp(param_name, "totem.knet_compression_level") == 0)
137 return &totem_config->knet_compression_level;
138 if (strcmp(param_name, "totem.knet_compression_model") == 0)
139 return &totem_config->knet_compression_model;
140
141 return NULL;
142 }
143
144 /*
145 * Read key_name from icmap. If key is not found or key_name == delete_key or if allow_zero is false
146 * and readed value is zero, default value is used and stored into totem_config.
147 */
148 static void totem_volatile_config_set_uint32_value (struct totem_config *totem_config,
149 const char *key_name, const char *deleted_key, unsigned int default_value,
150 int allow_zero_value)
151 {
152 char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
153
154 if (icmap_get_uint32(key_name, totem_get_param_by_name(totem_config, key_name)) != CS_OK ||
155 (deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
156 (!allow_zero_value && *(uint32_t *)totem_get_param_by_name(totem_config, key_name) == 0)) {
157 *(uint32_t *)totem_get_param_by_name(totem_config, key_name) = default_value;
158 }
159
160 /*
161 * Store totem_config value to cmap runtime section
162 */
163 if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
164 /*
165 * This shouldn't happen
166 */
167 return ;
168 }
169
170 strcpy(runtime_key_name, "runtime.config.");
171 strcat(runtime_key_name, key_name);
172
173 icmap_set_uint32(runtime_key_name, *(uint32_t *)totem_get_param_by_name(totem_config, key_name));
174 }
175
176 static void totem_volatile_config_set_int32_value (struct totem_config *totem_config,
177 const char *key_name, const char *deleted_key, int default_value,
178 int allow_zero_value)
179 {
180 char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
181
182 if (icmap_get_int32(key_name, totem_get_param_by_name(totem_config, key_name)) != CS_OK ||
183 (deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
184 (!allow_zero_value && *(int32_t *)totem_get_param_by_name(totem_config, key_name) == 0)) {
185 *(int32_t *)totem_get_param_by_name(totem_config, key_name) = default_value;
186 }
187
188 /*
189 * Store totem_config value to cmap runtime section
190 */
191 if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
192 /*
193 * This shouldn't happen
194 */
195 return ;
196 }
197
198 strcpy(runtime_key_name, "runtime.config.");
199 strcat(runtime_key_name, key_name);
200
201 icmap_set_int32(runtime_key_name, *(int32_t *)totem_get_param_by_name(totem_config, key_name));
202 }
203
204 static void totem_volatile_config_set_string_value (struct totem_config *totem_config,
205 const char *key_name, const char *deleted_key, const char *default_value)
206 {
207 char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
208 void **config_value;
209 void *old_config_ptr;
210
211 config_value = totem_get_param_by_name(totem_config, key_name);
212 old_config_ptr = *config_value;
213 if (icmap_get_string(key_name, totem_get_param_by_name(totem_config, key_name)) != CS_OK ||
214 (deleted_key != NULL && strcmp(deleted_key, key_name) == 0)) {
215
216 /* Need to strdup() here so that the free() below works for a default and a configured value */
217 *config_value = strdup(default_value);
218 }
219 free(old_config_ptr);
220
221 /*
222 * Store totem_config value to cmap runtime section
223 */
224 if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
225 /*
226 * This shouldn't happen
227 */
228 return ;
229 }
230
231 strcpy(runtime_key_name, "runtime.config.");
232 strcat(runtime_key_name, key_name);
233
234 icmap_set_string(runtime_key_name, (char *)*config_value);
235 }
236
237
238 /*
239 * Read and validate config values from cmap and store them into totem_config. If key doesn't exists,
240 * default value is stored. deleted_key is name of key beeing processed by delete operation
241 * from cmap. It is considered as non existing even if it can be read. Can be NULL.
242 */
243 static void totem_volatile_config_read (struct totem_config *totem_config, const char *deleted_key)
244 {
245 uint32_t u32;
246
247 totem_volatile_config_set_uint32_value(totem_config, "totem.token_retransmits_before_loss_const", deleted_key,
248 TOKEN_RETRANSMITS_BEFORE_LOSS_CONST, 0);
249
250 totem_volatile_config_set_uint32_value(totem_config, "totem.token", deleted_key, TOKEN_TIMEOUT, 0);
251
252 totem_volatile_config_set_uint32_value(totem_config, "totem.token_warning", deleted_key, TOKEN_WARNING, 1);
253
254 if (totem_config->interfaces[0].member_count > 2) {
255 u32 = TOKEN_COEFFICIENT;
256 icmap_get_uint32("totem.token_coefficient", &u32);
257 totem_config->token_timeout += (totem_config->interfaces[0].member_count - 2) * u32;
258
259 /*
260 * Store totem_config value to cmap runtime section
261 */
262 icmap_set_uint32("runtime.config.totem.token", totem_config->token_timeout);
263 }
264
265 totem_volatile_config_set_uint32_value(totem_config, "totem.max_network_delay", deleted_key, MAX_NETWORK_DELAY, 0);
266
267 totem_volatile_config_set_uint32_value(totem_config, "totem.window_size", deleted_key, WINDOW_SIZE, 0);
268
269 totem_volatile_config_set_uint32_value(totem_config, "totem.max_messages", deleted_key, MAX_MESSAGES, 0);
270
271 totem_volatile_config_set_uint32_value(totem_config, "totem.miss_count_const", deleted_key, MISS_COUNT_CONST, 0);
272 totem_volatile_config_set_uint32_value(totem_config, "totem.knet_pmtud_interval", deleted_key, KNET_PMTUD_INTERVAL, 0);
273
274 totem_volatile_config_set_uint32_value(totem_config, "totem.token_retransmit", deleted_key,
275 (int)(totem_config->token_timeout / (totem_config->token_retransmits_before_loss_const + 0.2)), 0);
276
277 totem_volatile_config_set_uint32_value(totem_config, "totem.hold", deleted_key,
278 (int)(totem_config->token_retransmit_timeout * 0.8 - (1000/HZ)), 0);
279
280 totem_volatile_config_set_uint32_value(totem_config, "totem.join", deleted_key, JOIN_TIMEOUT, 0);
281
282 totem_volatile_config_set_uint32_value(totem_config, "totem.consensus", deleted_key,
283 (int)(float)(1.2 * totem_config->token_timeout), 0);
284
285 totem_volatile_config_set_uint32_value(totem_config, "totem.merge", deleted_key, MERGE_TIMEOUT, 0);
286
287 totem_volatile_config_set_uint32_value(totem_config, "totem.downcheck", deleted_key, DOWNCHECK_TIMEOUT, 0);
288
289 totem_volatile_config_set_uint32_value(totem_config, "totem.fail_recv_const", deleted_key, FAIL_TO_RECV_CONST, 0);
290
291 totem_volatile_config_set_uint32_value(totem_config, "totem.seqno_unchanged_const", deleted_key,
292 SEQNO_UNCHANGED_CONST, 0);
293
294 totem_volatile_config_set_uint32_value(totem_config, "totem.send_join", deleted_key, 0, 1);
295
296 totem_volatile_config_set_uint32_value(totem_config, "totem.heartbeat_failures_allowed", deleted_key, 0, 1);
297
298 totem_volatile_config_set_uint32_value(totem_config, "totem.knet_compression_threshold", deleted_key, 0, 1);
299
300 totem_volatile_config_set_int32_value(totem_config, "totem.knet_compression_level", deleted_key, 0, 1);
301
302 totem_volatile_config_set_string_value(totem_config, "totem.knet_compression_model", deleted_key, "none");
303
304
305 }
306
307 static int totem_volatile_config_validate (
308 struct totem_config *totem_config,
309 const char **error_string)
310 {
311 static char local_error_reason[512];
312 const char *error_reason = local_error_reason;
313 char name_key[ICMAP_KEYNAME_MAXLEN];
314 char *name_str;
315 int i, num_configured, members;
316
317 if (totem_config->max_network_delay < MINIMUM_TIMEOUT) {
318 snprintf (local_error_reason, sizeof(local_error_reason),
319 "The max_network_delay parameter (%d ms) may not be less than (%d ms).",
320 totem_config->max_network_delay, MINIMUM_TIMEOUT);
321 goto parse_error;
322 }
323
324 if (totem_config->token_timeout < MINIMUM_TIMEOUT) {
325 snprintf (local_error_reason, sizeof(local_error_reason),
326 "The token timeout parameter (%d ms) may not be less than (%d ms).",
327 totem_config->token_timeout, MINIMUM_TIMEOUT);
328 goto parse_error;
329 }
330
331 if (totem_config->token_warning > 100 || totem_config->token_warning < 0) {
332 snprintf (local_error_reason, sizeof(local_error_reason),
333 "The token warning parameter (%d%%) must be between 0 (disabled) and 100.",
334 totem_config->token_warning);
335 goto parse_error;
336 }
337
338 if (totem_config->token_retransmit_timeout < MINIMUM_TIMEOUT) {
339 snprintf (local_error_reason, sizeof(local_error_reason),
340 "The token retransmit timeout parameter (%d ms) may not be less than (%d ms).",
341 totem_config->token_retransmit_timeout, MINIMUM_TIMEOUT);
342 goto parse_error;
343 }
344
345 if (totem_config->token_hold_timeout < MINIMUM_TIMEOUT) {
346 snprintf (local_error_reason, sizeof(local_error_reason),
347 "The token hold timeout parameter (%d ms) may not be less than (%d ms).",
348 totem_config->token_hold_timeout, MINIMUM_TIMEOUT);
349 goto parse_error;
350 }
351
352 if (totem_config->join_timeout < MINIMUM_TIMEOUT) {
353 snprintf (local_error_reason, sizeof(local_error_reason),
354 "The join timeout parameter (%d ms) may not be less than (%d ms).",
355 totem_config->join_timeout, MINIMUM_TIMEOUT);
356 goto parse_error;
357 }
358
359 if (totem_config->consensus_timeout < MINIMUM_TIMEOUT) {
360 snprintf (local_error_reason, sizeof(local_error_reason),
361 "The consensus timeout parameter (%d ms) may not be less than (%d ms).",
362 totem_config->consensus_timeout, MINIMUM_TIMEOUT);
363 goto parse_error;
364 }
365
366 if (totem_config->consensus_timeout < totem_config->join_timeout) {
367 snprintf (local_error_reason, sizeof(local_error_reason),
368 "The consensus timeout parameter (%d ms) may not be less than join timeout (%d ms).",
369 totem_config->consensus_timeout, totem_config->join_timeout);
370 goto parse_error;
371 }
372
373 if (totem_config->merge_timeout < MINIMUM_TIMEOUT) {
374 snprintf (local_error_reason, sizeof(local_error_reason),
375 "The merge timeout parameter (%d ms) may not be less than (%d ms).",
376 totem_config->merge_timeout, MINIMUM_TIMEOUT);
377 goto parse_error;
378 }
379
380 if (totem_config->downcheck_timeout < MINIMUM_TIMEOUT) {
381 snprintf (local_error_reason, sizeof(local_error_reason),
382 "The downcheck timeout parameter (%d ms) may not be less than (%d ms).",
383 totem_config->downcheck_timeout, MINIMUM_TIMEOUT);
384 goto parse_error;
385 }
386
387 /* Check that we have nodelist 'name' if there is more than one link */
388 num_configured = 0;
389 for (i = 0; i < INTERFACE_MAX; i++) {
390 if (totem_config->interfaces[i].configured) {
391 num_configured++;
392 }
393 }
394
395 if (num_configured > 1) {
396 members = totem_config->interfaces[0].member_count;
397
398 for (i=0; i<totem_config->interfaces[0].member_count; i++) {
399 snprintf(name_key, sizeof(name_key), "nodelist.node.%d.name", i);
400
401 if (icmap_get_string(name_key, &name_str) != CS_OK) {
402 snprintf (local_error_reason, sizeof(local_error_reason),
403 "for a multi-link configuration, all nodes must have a 'name' attribute");
404 goto parse_error;
405 }
406 }
407
408 for (i=0; i<num_configured; i++) {
409 if (totem_config->interfaces[i].member_count != members) {
410 snprintf (local_error_reason, sizeof(local_error_reason),
411 "Not all nodes have the same number of links");
412 goto parse_error;
413 }
414 }
415
416
417
418 }
419
420 return 0;
421
422 parse_error:
423 snprintf (error_string_response, sizeof(error_string_response),
424 "parse error in config: %s\n", error_reason);
425 *error_string = error_string_response;
426 return (-1);
427
428 }
429
430 static int totem_get_crypto(struct totem_config *totem_config, const char **error_string)
431 {
432 char *str;
433 const char *tmp_cipher;
434 const char *tmp_hash;
435 const char *tmp_model;
436
437 tmp_hash = "none";
438 tmp_cipher = "none";
439 tmp_model = "none";
440
441 if (icmap_get_string("totem.crypto_model", &str) == CS_OK) {
442 if (strcmp(str, "nss") == 0) {
443 tmp_model = "nss";
444 }
445 if (strcmp(str, "openssl") == 0) {
446 tmp_model = "openssl";
447 }
448 free(str);
449 } else {
450 tmp_model = "nss";
451 }
452
453 if (icmap_get_string("totem.crypto_cipher", &str) == CS_OK) {
454 if (strcmp(str, "none") == 0) {
455 tmp_cipher = "none";
456 }
457 if (strcmp(str, "aes256") == 0) {
458 tmp_cipher = "aes256";
459 }
460 if (strcmp(str, "aes192") == 0) {
461 tmp_cipher = "aes192";
462 }
463 if (strcmp(str, "aes128") == 0) {
464 tmp_cipher = "aes128";
465 }
466 free(str);
467 }
468
469 if (icmap_get_string("totem.crypto_hash", &str) == CS_OK) {
470 if (strcmp(str, "none") == 0) {
471 tmp_hash = "none";
472 }
473 if (strcmp(str, "md5") == 0) {
474 tmp_hash = "md5";
475 }
476 if (strcmp(str, "sha1") == 0) {
477 tmp_hash = "sha1";
478 }
479 if (strcmp(str, "sha256") == 0) {
480 tmp_hash = "sha256";
481 }
482 if (strcmp(str, "sha384") == 0) {
483 tmp_hash = "sha384";
484 }
485 if (strcmp(str, "sha512") == 0) {
486 tmp_hash = "sha512";
487 }
488 free(str);
489 }
490
491 if ((strcmp(tmp_cipher, "none") != 0) &&
492 (strcmp(tmp_hash, "none") == 0)) {
493 *error_string = "crypto_cipher requires crypto_hash with value other than none";
494 return -1;
495 }
496
497 if (strcmp(tmp_model, "none") == 0) {
498 *error_string = "crypto_model should be 'nss' or 'openssl'";
499 return -1;
500 }
501
502 free(totem_config->crypto_cipher_type);
503 free(totem_config->crypto_hash_type);
504 free(totem_config->crypto_model);
505
506 totem_config->crypto_cipher_type = strdup(tmp_cipher);
507 totem_config->crypto_hash_type = strdup(tmp_hash);
508 totem_config->crypto_model = strdup(tmp_model);
509
510 return 0;
511 }
512
513 static int nodelist_byname(const char *find_name, int strip_domain)
514 {
515 icmap_iter_t iter;
516 const char *iter_key;
517 char name_str[ICMAP_KEYNAME_MAXLEN];
518 int res = 0;
519 unsigned int node_pos;
520 char *name;
521 unsigned int namelen;
522
523 iter = icmap_iter_init("nodelist.node.");
524 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
525 res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, name_str);
526 if (res != 2) {
527 continue;
528 }
529 /* ring0_addr is allowed as a fallback */
530 if (strcmp(name_str, "name") && strcmp(name_str, "ring0_addr")) {
531 continue;
532 }
533 if (icmap_get_string(iter_key, &name) != CS_OK) {
534 continue;
535 }
536 namelen = strlen(name);
537
538 if (strip_domain) {
539 char *dot;
540 dot = strchr(name, '.');
541 if (dot) {
542 namelen = name - dot - 1;
543 }
544 }
545 if (strncmp(find_name, name, namelen) == 0 &&
546 strlen(find_name) == strlen(name)) {
547 icmap_iter_finalize(iter);
548 return node_pos;
549 }
550 }
551 icmap_iter_finalize(iter);
552 return -1;
553 }
554
555 /* Compare two addresses */
556 static int ipaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
557 {
558 int addrlen = 0;
559
560 if (addr1->ss_family != addr2->ss_family)
561 return 0;
562
563 if (addr1->ss_family == AF_INET) {
564 addrlen = sizeof(struct sockaddr_in);
565 }
566 if (addr1->ss_family == AF_INET6) {
567 addrlen = sizeof(struct sockaddr_in6);
568 }
569 assert(addrlen);
570
571 if (memcmp(addr1, addr2, addrlen) == 0)
572 return 1;
573 else
574 return 0;
575
576 }
577
578
579 /* Finds the local node and returns its position in the nodelist.
580 * Uses nodelist.local_node_pos as a cache to save effort
581 */
582 static int find_local_node(int use_cache)
583 {
584 char nodename2[PATH_MAX];
585 char name_str[ICMAP_KEYNAME_MAXLEN];
586 icmap_iter_t iter;
587 const char *iter_key;
588 unsigned int cached_pos;
589 char *dot = NULL;
590 const char *node;
591 struct ifaddrs *ifa, *ifa_list;
592 struct sockaddr *sa;
593 int found = 0;
594 int node_pos = -1;
595 int res;
596 struct utsname utsname;
597
598 /* Check for cached value first */
599 if (use_cache) {
600 if (icmap_get_uint32("nodelist.local_node_pos", &cached_pos) == CS_OK) {
601 return cached_pos;
602 }
603 }
604
605 res = uname(&utsname);
606 if (res) {
607 return -1;
608 }
609 node = utsname.nodename;
610
611 /* 1. Exact match */
612 node_pos = nodelist_byname(node, 0);
613 if (node_pos > -1) {
614 found = 1;
615 goto ret_found;
616 }
617
618 /* 2. Try to match with increasingly more
619 * specific versions of it
620 */
621 strcpy(nodename2, node);
622 dot = strrchr(nodename2, '.');
623 while (dot) {
624 *dot = '\0';
625
626 node_pos = nodelist_byname(nodename2, 0);
627 if (node_pos > -1) {
628 found = 1;
629 goto ret_found;
630 }
631 dot = strrchr(nodename2, '.');
632 }
633
634 node_pos = nodelist_byname(nodename2, 1);
635 if (node_pos > -1) {
636 found = 1;
637 goto ret_found;
638 }
639
640 /*
641 * The corosync.conf name may not be related to uname at all,
642 * they may match a hostname on some network interface.
643 */
644 if (getifaddrs(&ifa_list))
645 return -1;
646
647 for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
648 socklen_t salen = 0;
649
650 /* Restore this */
651 strcpy(nodename2, node);
652 sa = ifa->ifa_addr;
653 if (!sa) {
654 continue;
655 }
656 if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6) {
657 continue;
658 }
659
660 if (sa->sa_family == AF_INET) {
661 salen = sizeof(struct sockaddr_in);
662 }
663 if (sa->sa_family == AF_INET6) {
664 salen = sizeof(struct sockaddr_in6);
665 }
666
667 if (getnameinfo(sa, salen,
668 nodename2, sizeof(nodename2),
669 NULL, 0, 0) == 0) {
670
671 node_pos = nodelist_byname(nodename2, 0);
672 if (node_pos > -1) {
673 found = 1;
674 goto out;
675 }
676
677 /* Truncate this name and try again */
678 dot = strchr(nodename2, '.');
679 if (dot) {
680 *dot = '\0';
681
682 node_pos = nodelist_byname(nodename2, 0);
683 if (node_pos > -1) {
684 found = 1;
685 goto out;
686 }
687 }
688 }
689
690 /* See if it's the IP address that's in corosync.conf */
691 if (getnameinfo(sa, sizeof(*sa),
692 nodename2, sizeof(nodename2),
693 NULL, 0, NI_NUMERICHOST))
694 continue;
695
696 node_pos = nodelist_byname(nodename2, 0);
697 if (node_pos > -1) {
698 found = 1;
699 goto out;
700 }
701 }
702
703 out:
704 if (found) {
705 freeifaddrs(ifa_list);
706 goto ret_found;
707 }
708
709 /*
710 * This section covers the usecase where the nodename specified in cluster.conf
711 * is an alias specified in /etc/hosts. For example:
712 * <ipaddr> hostname alias1 alias2
713 * and <clusternode name="alias2">
714 * the above calls use uname and getnameinfo does not return aliases.
715 * here we take the name specified in cluster.conf, resolve it to an address
716 * and then compare against all known local ip addresses.
717 * if we have a match, we found our nodename. In theory this chunk of code
718 * could replace all the checks above, but let's avoid any possible regressions
719 * and use it as last.
720 */
721
722 iter = icmap_iter_init("nodelist.node.");
723 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
724 char *dbnodename = NULL;
725 struct addrinfo hints;
726 struct addrinfo *result = NULL, *rp = NULL;
727
728 res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, name_str);
729 if (res != 2) {
730 continue;
731 }
732 /* 'ring0_addr' is allowed as a fallback, but 'name' will be found first
733 * because the names are in alpha order.
734 */
735 if (strcmp(name_str, "name") && strcmp(name_str, "ring0_addr")) {
736 continue;
737 }
738 if (icmap_get_string(iter_key, &dbnodename) != CS_OK) {
739 continue;
740 }
741
742 memset(&hints, 0, sizeof(struct addrinfo));
743 hints.ai_family = AF_UNSPEC;
744 hints.ai_socktype = SOCK_DGRAM;
745 hints.ai_flags = 0;
746 hints.ai_protocol = IPPROTO_UDP;
747
748 if (getaddrinfo(dbnodename, NULL, &hints, &result)) {
749 continue;
750 }
751
752 for (rp = result; rp != NULL; rp = rp->ai_next) {
753 for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
754 if (ifa->ifa_addr &&
755 ipaddr_equal((struct sockaddr_storage *)rp->ai_addr,
756 (struct sockaddr_storage *)ifa->ifa_addr)) {
757 freeaddrinfo(result);
758 found = 1;
759 goto out2;
760 }
761 }
762 }
763
764 freeaddrinfo(result);
765 }
766 out2:
767 icmap_iter_finalize(iter);
768 freeifaddrs(ifa_list);
769
770 ret_found:
771 if (found) {
772 res = icmap_set_uint32("nodelist.local_node_pos", node_pos);
773 }
774
775 return node_pos;
776 }
777
778 static enum totem_ip_version_enum totem_config_get_ip_version(struct totem_config *totem_config)
779 {
780 enum totem_ip_version_enum res;
781 char *str;
782
783 res = TOTEM_IP_VERSION_6_4;
784
785 if (totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
786 res = TOTEM_IP_VERSION_4;
787 }
788
789 if (icmap_get_string("totem.ip_version", &str) == CS_OK) {
790 if (strcmp(str, "ipv4") == 0) {
791 res = TOTEM_IP_VERSION_4;
792 }
793 if (strcmp(str, "ipv6") == 0) {
794 res = TOTEM_IP_VERSION_6;
795 }
796 if (strcmp(str, "ipv6-4") == 0) {
797 res = TOTEM_IP_VERSION_6_4;
798 }
799 if (strcmp(str, "ipv4-6") == 0) {
800 res = TOTEM_IP_VERSION_4_6;
801 }
802 free(str);
803 }
804
805 return (res);
806 }
807
808 static uint16_t generate_cluster_id (const char *cluster_name)
809 {
810 int i;
811 int value = 0;
812
813 for (i = 0; i < strlen(cluster_name); i++) {
814 value <<= 1;
815 value += cluster_name[i];
816 }
817
818 return (value & 0xFFFF);
819 }
820
821 static int get_cluster_mcast_addr (
822 const char *cluster_name,
823 unsigned int linknumber,
824 enum totem_ip_version_enum ip_version,
825 struct totem_ip_address *res)
826 {
827 uint16_t clusterid;
828 char addr[INET6_ADDRSTRLEN + 1];
829 int err;
830
831 if (cluster_name == NULL) {
832 return (-1);
833 }
834
835 clusterid = generate_cluster_id(cluster_name) + linknumber;
836 memset (res, 0, sizeof(*res));
837
838 switch (ip_version) {
839 case TOTEM_IP_VERSION_4:
840 case TOTEM_IP_VERSION_4_6:
841 snprintf(addr, sizeof(addr), "239.192.%d.%d", clusterid >> 8, clusterid % 0xFF);
842 break;
843 case TOTEM_IP_VERSION_6:
844 case TOTEM_IP_VERSION_6_4:
845 snprintf(addr, sizeof(addr), "ff15::%x", clusterid);
846 break;
847 default:
848 /*
849 * Unknown family
850 */
851 return (-1);
852 }
853
854 err = totemip_parse (res, addr, ip_version);
855
856 return (err);
857 }
858
859 static unsigned int generate_nodeid(
860 struct totem_config *totem_config,
861 char *addr)
862 {
863 unsigned int nodeid;
864 struct totem_ip_address totemip;
865
866 /* AF_INET hard-coded here because auto-generated nodeids
867 are only for IPv4 */
868 if (totemip_parse(&totemip, addr, TOTEM_IP_VERSION_4) != 0)
869 return -1;
870
871 memcpy (&nodeid, &totemip.addr, sizeof (unsigned int));
872
873 #if __BYTE_ORDER == __LITTLE_ENDIAN
874 nodeid = swab32 (nodeid);
875 #endif
876
877 if (totem_config->clear_node_high_bit) {
878 nodeid &= 0x7FFFFFFF;
879 }
880 return nodeid;
881 }
882
883 static int check_for_duplicate_nodeids(
884 struct totem_config *totem_config,
885 const char **error_string)
886 {
887 icmap_iter_t iter;
888 icmap_iter_t subiter;
889 const char *iter_key;
890 int res = 0;
891 int retval = 0;
892 char tmp_key[ICMAP_KEYNAME_MAXLEN];
893 char *ring0_addr=NULL;
894 char *ring0_addr1=NULL;
895 unsigned int node_pos;
896 unsigned int node_pos1;
897 unsigned int last_node_pos = -1;
898 unsigned int nodeid;
899 unsigned int nodeid1;
900 int autogenerated;
901
902 iter = icmap_iter_init("nodelist.node.");
903 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
904 res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
905 if (res != 2) {
906 continue;
907 }
908
909 /*
910 * This relies on the fact the icmap keys are always returned in order
911 * so all of the keys for a node will be grouped together. We're basically
912 * just running the code below once for each node.
913 */
914 if (last_node_pos == node_pos) {
915 continue;
916 }
917 last_node_pos = node_pos;
918
919 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos);
920 autogenerated = 0;
921
922 /* Generated nodeids are only allowed for UDP/UDPU so ring0_addr is valid here */
923 if (icmap_get_uint32(tmp_key, &nodeid) != CS_OK) {
924
925 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos);
926 if (icmap_get_string(tmp_key, &ring0_addr) != CS_OK) {
927 continue;
928 }
929
930 /* Generate nodeid so we can check that auto-generated nodeids don't clash either */
931 nodeid = generate_nodeid(totem_config, ring0_addr);
932 if (nodeid == -1) {
933 continue;
934 }
935 autogenerated = 1;
936 }
937
938 node_pos1 = 0;
939 subiter = icmap_iter_init("nodelist.node.");
940 while (((iter_key = icmap_iter_next(subiter, NULL, NULL)) != NULL) && (node_pos1 < node_pos)) {
941 res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos1, tmp_key);
942 if ((res != 2) || (node_pos1 >= node_pos)) {
943 continue;
944 }
945
946 if (strcmp(tmp_key, "nodeid") != 0) {
947 continue;
948 }
949
950 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos1);
951 if (icmap_get_uint32(tmp_key, &nodeid1) != CS_OK) {
952
953 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos1);
954 if (icmap_get_string(tmp_key, &ring0_addr1) != CS_OK) {
955 continue;
956 }
957 nodeid1 = generate_nodeid(totem_config, ring0_addr1);
958 if (nodeid1 == -1) {
959 continue;
960 }
961 }
962
963 if (nodeid == nodeid1) {
964 retval = -1;
965 snprintf (error_string_response, sizeof(error_string_response),
966 "Nodeid %u%s%s%s appears twice in corosync.conf", nodeid,
967 autogenerated?"(autogenerated from ":"",
968 autogenerated?ring0_addr:"",
969 autogenerated?")":"");
970 log_printf (LOGSYS_LEVEL_ERROR, error_string_response);
971 *error_string = error_string_response;
972 break;
973 }
974 }
975 icmap_iter_finalize(subiter);
976 }
977 icmap_iter_finalize(iter);
978 return retval;
979 }
980
981
982 /*
983 * This needs to be done last of all. It would be nice to do it when reading the
984 * interface params, but the totem params need to have them to be read first. We
985 * need both, so this is a way round that circular dependancy.
986 */
987 static void calc_knet_ping_timers(struct totem_config *totem_config)
988 {
989 char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
990 int interface;
991
992 for (interface = 0; interface < INTERFACE_MAX; interface++) {
993
994 if (totem_config->interfaces[interface].configured) {
995 if (!totem_config->interfaces[interface].knet_pong_count) {
996 totem_config->interfaces[interface].knet_pong_count = KNET_PONG_COUNT;
997 }
998 if (!totem_config->interfaces[interface].knet_ping_timeout) {
999 totem_config->interfaces[interface].knet_ping_timeout =
1000 totem_config->token_timeout / totem_config->interfaces[interface].knet_pong_count;
1001 }
1002 snprintf(runtime_key_name, sizeof(runtime_key_name),
1003 "runtime.config.totem.interface.%d.knet_ping_timeout", interface);
1004 icmap_set_uint32(runtime_key_name, totem_config->interfaces[interface].knet_ping_timeout);
1005
1006 if (!totem_config->interfaces[interface].knet_ping_interval) {
1007 totem_config->interfaces[interface].knet_ping_interval =
1008 totem_config->token_timeout / (totem_config->interfaces[interface].knet_pong_count * 2);
1009 }
1010 snprintf(runtime_key_name, sizeof(runtime_key_name),
1011 "runtime.config.totem.interface.%d.knet_ping_interval", interface);
1012 icmap_set_uint32(runtime_key_name, totem_config->interfaces[interface].knet_ping_interval);
1013 }
1014 }
1015 }
1016
1017 /*
1018 * Compute difference between two set of totem interface arrays. set1 and set2
1019 * are changed so for same ring, ip existing in both set1 and set2 are cleared
1020 * (set to 0), and ips which are only in set1 or set2 remains untouched.
1021 * totempg_node_add/remove is called.
1022 */
1023 static void compute_interfaces_diff(struct totem_interface *set1,
1024 struct totem_interface *set2)
1025 {
1026 int ring_no, set1_pos, set2_pos;
1027 struct totem_ip_address empty_ip_address;
1028
1029 memset(&empty_ip_address, 0, sizeof(empty_ip_address));
1030
1031 for (ring_no = 0; ring_no < INTERFACE_MAX; ring_no++) {
1032 if (!set1[ring_no].configured && !set2[ring_no].configured) {
1033 continue;
1034 }
1035
1036 for (set1_pos = 0; set1_pos < set1[ring_no].member_count; set1_pos++) {
1037 for (set2_pos = 0; set2_pos < set2[ring_no].member_count; set2_pos++) {
1038 /*
1039 * For current ring_no remove all set1 items existing
1040 * in set2
1041 */
1042 if (memcmp(&set1[ring_no].member_list[set1_pos],
1043 &set2[ring_no].member_list[set2_pos],
1044 sizeof(struct totem_ip_address)) == 0) {
1045 memset(&set1[ring_no].member_list[set1_pos], 0,
1046 sizeof(struct totem_ip_address));
1047 memset(&set2[ring_no].member_list[set2_pos], 0,
1048 sizeof(struct totem_ip_address));
1049 }
1050 }
1051 }
1052 }
1053
1054 for (ring_no = 0; ring_no < INTERFACE_MAX; ring_no++) {
1055 for (set1_pos = 0; set1_pos < set1[ring_no].member_count; set1_pos++) {
1056 /*
1057 * All items which remained in set1 doesn't exists in set2 any longer so
1058 * node has to be removed.
1059 */
1060 if (memcmp(&set1[ring_no].member_list[set1_pos], &empty_ip_address, sizeof(empty_ip_address)) != 0) {
1061 log_printf(LOGSYS_LEVEL_DEBUG,
1062 "removing dynamic member %s for ring %u",
1063 totemip_print(&set1[ring_no].member_list[set1_pos]),
1064 ring_no);
1065
1066 totempg_member_remove(&set1[ring_no].member_list[set1_pos], ring_no);
1067 }
1068 }
1069 if (!set2[ring_no].configured) {
1070 continue;
1071 }
1072 for (set2_pos = 0; set2_pos < set2[ring_no].member_count; set2_pos++) {
1073 /*
1074 * All items which remained in set2 doesn't existed in set1 so this is no node
1075 * and has to be added.
1076 */
1077 if (memcmp(&set2[ring_no].member_list[set2_pos], &empty_ip_address, sizeof(empty_ip_address)) != 0) {
1078 log_printf(LOGSYS_LEVEL_DEBUG,
1079 "adding dynamic member %s for ring %u",
1080 totemip_print(&set2[ring_no].member_list[set2_pos]),
1081 ring_no);
1082
1083 totempg_member_add(&set2[ring_no].member_list[set2_pos], ring_no);
1084 }
1085 }
1086 }
1087 }
1088
1089 /*
1090 * Reconfigure links in totempg. Sets new local IP address and adds params for new links.
1091 */
1092 static void reconfigure_links(struct totem_config *totem_config)
1093 {
1094 int i;
1095 char tmp_key[ICMAP_KEYNAME_MAXLEN];
1096 char *addr_string;
1097 struct totem_ip_address local_ip;
1098 int err;
1099 int local_node_pos = find_local_node(0);
1100
1101 for (i = 0; i<INTERFACE_MAX; i++) {
1102 if (!totem_config->interfaces[i].configured) {
1103 continue;
1104 }
1105
1106 log_printf(LOGSYS_LEVEL_INFO, "Configuring link %d\n", i);
1107
1108 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring%u_addr", local_node_pos, i);
1109 if (icmap_get_string(tmp_key, &addr_string) != CS_OK) {
1110 continue;
1111 }
1112
1113 err = totemip_parse(&local_ip, addr_string, totem_config->ip_version);
1114 if (err != 0) {
1115 continue;
1116 }
1117 local_ip.nodeid = totem_config->node_id;
1118
1119 /* In case this is a new link, fill in the defaults if there was no interface{} section for it */
1120 if (!totem_config->interfaces[i].knet_link_priority)
1121 totem_config->interfaces[i].knet_link_priority = 1;
1122
1123 /* knet_ping_interval & knet_ping_timeout are set later once we know all the other params */
1124
1125 if (!totem_config->interfaces[i].knet_ping_precision)
1126 totem_config->interfaces[i].knet_ping_precision = KNET_PING_PRECISION;
1127 if (!totem_config->interfaces[i].knet_pong_count)
1128 totem_config->interfaces[i].knet_pong_count = KNET_PONG_COUNT;
1129 if (!totem_config->interfaces[i].knet_transport)
1130 totem_config->interfaces[i].knet_transport = KNET_TRANSPORT_UDP;
1131 if (!totem_config->interfaces[i].ip_port)
1132 totem_config->interfaces[i].ip_port = DEFAULT_PORT + i;
1133
1134 totempg_iface_set(&local_ip, totem_config->interfaces[i].ip_port, i);
1135 }
1136 }
1137
1138 /* Check for differences in config that can't be done on-the-fly and print an error */
1139 static void check_things_have_not_changed(struct totem_config *totem_config)
1140 {
1141 int i,j;
1142 const char *ip_str;
1143 char addr_buf[INET6_ADDRSTRLEN];
1144 int changed = 0;
1145
1146 for (i = 0; i<INTERFACE_MAX; i++) {
1147 if (totem_config->interfaces[i].configured) {
1148 if (totem_config->interfaces[i].knet_transport !=
1149 totem_config->orig_interfaces[i].knet_transport) {
1150 log_printf(LOGSYS_LEVEL_ERROR,
1151 "New config has different knet transport for link %d. Internal value was NOT changed.\n", i);
1152 changed = 1;
1153 }
1154 for (j=0; j < min(totem_config->interfaces[i].member_count, totem_config->orig_interfaces[i].member_count); j++) {
1155 if (memcmp(&totem_config->interfaces[i].member_list[j],
1156 &totem_config->orig_interfaces[i].member_list[j],
1157 sizeof(struct totem_ip_address))) {
1158
1159 ip_str = totemip_print(&totem_config->orig_interfaces[i].member_list[j]);
1160
1161 /* if ip_str is NULL then the old address was invalid and is allowed to change */
1162 if (ip_str) {
1163 strncpy(addr_buf, ip_str, sizeof(addr_buf));
1164 addr_buf[sizeof(addr_buf) - 1] = '\0';
1165 log_printf(LOGSYS_LEVEL_ERROR,
1166 "new config has different address for link %d (addr changed from %s to %s). Internal value was NOT changed.\n",
1167 i, addr_buf, totemip_print(&totem_config->interfaces[i].member_list[j]));
1168 changed = 1;
1169 }
1170 }
1171 }
1172 }
1173 }
1174
1175 if (changed) {
1176 log_printf(LOGSYS_LEVEL_ERROR, "To reconfigure an interface it must be deleted and recreated. A working interface needs to be available to corosync at all times");
1177 }
1178 }
1179
1180
1181 static int put_nodelist_members_to_config(struct totem_config *totem_config, int reload, const char **error_string)
1182 {
1183 icmap_iter_t iter, iter2;
1184 const char *iter_key, *iter_key2;
1185 int res = 0;
1186 unsigned int node_pos;
1187 char tmp_key[ICMAP_KEYNAME_MAXLEN];
1188 char tmp_key2[ICMAP_KEYNAME_MAXLEN];
1189 char *node_addr_str;
1190 int member_count;
1191 unsigned int linknumber = 0;
1192 int i, j;
1193 int last_node_pos = -1;
1194 struct totem_interface *new_interfaces = NULL;
1195
1196 if (reload) {
1197 /*
1198 * We need to compute diff only for reload. Also for initial configuration
1199 * not all totem structures are initialized so corosync will crash during
1200 * member_add/remove
1201 */
1202 new_interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
1203 assert(new_interfaces != NULL);
1204 }
1205
1206 /* Clear out nodelist so we can put the new one in if needed */
1207 for (i = 0; i < INTERFACE_MAX; i++) {
1208 for (j = 0; j < PROCESSOR_COUNT_MAX; j++) {
1209 memset(&totem_config->interfaces[i].member_list[j], 0, sizeof(struct totem_ip_address));
1210 }
1211 totem_config->interfaces[i].member_count = 0;
1212 }
1213
1214 iter = icmap_iter_init("nodelist.node.");
1215 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
1216 res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, tmp_key);
1217 if (res != 2) {
1218 continue;
1219 }
1220 /* If it's the same as the last node_pos then skip it */
1221 if (node_pos == last_node_pos) {
1222 continue;
1223 }
1224 last_node_pos = node_pos;
1225
1226 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.", node_pos);
1227 iter2 = icmap_iter_init(tmp_key);
1228 while ((iter_key2 = icmap_iter_next(iter2, NULL, NULL)) != NULL) {
1229 unsigned int nodeid;
1230 char *str;
1231
1232 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", node_pos);
1233 if (icmap_get_uint32(tmp_key, &nodeid) != CS_OK) {
1234 nodeid = 0;
1235 }
1236
1237 res = sscanf(iter_key2, "nodelist.node.%u.ring%u%s", &node_pos, &linknumber, tmp_key2);
1238 if (res != 3 || strcmp(tmp_key2, "_addr") != 0) {
1239 continue;
1240 }
1241
1242 if (icmap_get_string(iter_key2, &node_addr_str) != CS_OK) {
1243 continue;
1244 }
1245
1246 /* Generate nodeids if they are not provided and transport is UDP/U */
1247 if (!nodeid &&
1248 (totem_config->transport_number == TOTEM_TRANSPORT_UDP ||
1249 totem_config->transport_number == TOTEM_TRANSPORT_UDPU)) {
1250 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos);
1251 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1252 nodeid = generate_nodeid(totem_config, str);
1253 log_printf(LOGSYS_LEVEL_DEBUG,
1254 "Generated nodeid = 0x%x for %s", nodeid, str);
1255 free(str);
1256 }
1257 }
1258
1259 member_count = totem_config->interfaces[linknumber].member_count;
1260 res = totemip_parse(&totem_config->interfaces[linknumber].member_list[member_count],
1261 node_addr_str, totem_config->ip_version);
1262 if (res == 0) {
1263 totem_config->interfaces[linknumber].member_list[member_count].nodeid = nodeid;
1264 totem_config->interfaces[linknumber].member_count++;
1265 totem_config->interfaces[linknumber].configured = 1;
1266 } else {
1267 sprintf(error_string_response, "failed to parse node address '%s'\n", node_addr_str);
1268 *error_string = error_string_response;
1269
1270 memset(&totem_config->interfaces[linknumber].member_list[member_count], 0,
1271 sizeof(struct totem_ip_address));
1272
1273 free(node_addr_str);
1274 icmap_iter_finalize(iter2);
1275 icmap_iter_finalize(iter);
1276 return -1;
1277 }
1278
1279 free(node_addr_str);
1280 }
1281
1282 icmap_iter_finalize(iter2);
1283 }
1284
1285 icmap_iter_finalize(iter);
1286
1287 if (reload) {
1288 log_printf(LOGSYS_LEVEL_DEBUG, "About to reconfigure links from nodelist.\n");
1289 reconfigure_links(totem_config);
1290
1291 memcpy(new_interfaces, totem_config->interfaces, sizeof (struct totem_interface) * INTERFACE_MAX);
1292
1293 check_things_have_not_changed(totem_config);
1294
1295 compute_interfaces_diff(totem_config->orig_interfaces, new_interfaces);
1296
1297 free(new_interfaces);
1298 }
1299 return 0;
1300 }
1301
1302 static void config_convert_nodelist_to_interface(struct totem_config *totem_config)
1303 {
1304 int res = 0;
1305 int node_pos;
1306 char tmp_key[ICMAP_KEYNAME_MAXLEN];
1307 char tmp_key2[ICMAP_KEYNAME_MAXLEN];
1308 char *node_addr_str;
1309 unsigned int linknumber = 0;
1310 icmap_iter_t iter;
1311 const char *iter_key;
1312
1313 node_pos = find_local_node(1);
1314 if (node_pos > -1) {
1315 /*
1316 * We found node, so create interface section
1317 */
1318 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.", node_pos);
1319 iter = icmap_iter_init(tmp_key);
1320 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
1321 res = sscanf(iter_key, "nodelist.node.%u.ring%u%s", &node_pos, &linknumber, tmp_key2);
1322 if (res != 3 || strcmp(tmp_key2, "_addr") != 0) {
1323 continue ;
1324 }
1325
1326 if (icmap_get_string(iter_key, &node_addr_str) != CS_OK) {
1327 continue;
1328 }
1329
1330 snprintf(tmp_key2, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr", linknumber);
1331 icmap_set_string(tmp_key2, node_addr_str);
1332 free(node_addr_str);
1333 }
1334 icmap_iter_finalize(iter);
1335 }
1336 }
1337
1338 static int get_interface_params(struct totem_config *totem_config,
1339 const char **error_string, uint64_t *warnings,
1340 int reload)
1341 {
1342 int res = 0;
1343 unsigned int linknumber = 0;
1344 int member_count = 0;
1345 int i;
1346 icmap_iter_t iter, member_iter;
1347 const char *iter_key;
1348 const char *member_iter_key;
1349 char linknumber_key[ICMAP_KEYNAME_MAXLEN];
1350 char tmp_key[ICMAP_KEYNAME_MAXLEN];
1351 uint8_t u8;
1352 uint32_t u32;
1353 char *str;
1354 char *cluster_name = NULL;
1355
1356 if (reload) {
1357 for (i=0; i<INTERFACE_MAX; i++) {
1358 /*
1359 * Set back to defaults things that might have been configured and
1360 * now have been taken out of corosync.conf. These won't be caught by the
1361 * code below which only looks at interface{} sections that actually exist.
1362 */
1363 totem_config->interfaces[i].configured = 0;
1364 totem_config->interfaces[i].knet_ping_timeout = 0;
1365 totem_config->interfaces[i].knet_ping_interval = 0;
1366 totem_config->interfaces[i].knet_ping_precision = KNET_PING_PRECISION;
1367 totem_config->interfaces[i].knet_pong_count = KNET_PONG_COUNT;
1368 }
1369 }
1370 if (icmap_get_string("totem.cluster_name", &cluster_name) != CS_OK) {
1371 cluster_name = NULL;
1372 }
1373
1374 iter = icmap_iter_init("totem.interface.");
1375 while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
1376 res = sscanf(iter_key, "totem.interface.%[^.].%s", linknumber_key, tmp_key);
1377 if (res != 2) {
1378 continue;
1379 }
1380
1381 if (strcmp(tmp_key, "bindnetaddr") != 0 && totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1382 continue;
1383 }
1384
1385 member_count = 0;
1386 linknumber = atoi(linknumber_key);
1387
1388 if (linknumber >= INTERFACE_MAX) {
1389 free(cluster_name);
1390
1391 snprintf (error_string_response, sizeof(error_string_response),
1392 "parse error in config: interface ring number %u is bigger than allowed maximum %u\n",
1393 linknumber, INTERFACE_MAX - 1);
1394
1395 *error_string = error_string_response;
1396 return -1;
1397 }
1398
1399 /* These things are only valid for the initial read */
1400 if (!reload) {
1401 /*
1402 * Get the bind net address
1403 */
1404 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr", linknumber);
1405
1406 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1407 res = totemip_parse (&totem_config->interfaces[linknumber].bindnet, str,
1408 totem_config->ip_version);
1409
1410 if (res) {
1411 sprintf(error_string_response, "failed to parse bindnet address '%s'\n", str);
1412 *error_string = error_string_response;
1413 free(str);
1414
1415 return -1;
1416 }
1417
1418 free(str);
1419 }
1420
1421 /*
1422 * Get interface multicast address
1423 */
1424 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr", linknumber);
1425 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1426 res = totemip_parse (&totem_config->interfaces[linknumber].mcast_addr, str,
1427 totem_config->ip_version);
1428
1429 if (res) {
1430 sprintf(error_string_response, "failed to parse mcast address '%s'\n", str);
1431 *error_string = error_string_response;
1432 free(str);
1433
1434 return -1;
1435 }
1436
1437 free(str);
1438 } else if (totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1439 /*
1440 * User not specified address -> autogenerate one from cluster_name key
1441 * (if available). Return code is intentionally ignored, because
1442 * udpu doesn't need mcastaddr and validity of mcastaddr for udp is
1443 * checked later anyway.
1444 */
1445 (void)get_cluster_mcast_addr (cluster_name,
1446 linknumber,
1447 totem_config->ip_version,
1448 &totem_config->interfaces[linknumber].mcast_addr);
1449 }
1450
1451 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast", linknumber);
1452 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1453 if (strcmp (str, "yes") == 0) {
1454 totem_config->broadcast_use = 1;
1455 }
1456 free(str);
1457 }
1458 }
1459
1460 /* These things are only valid for the initial read OR a newly-defined link */
1461 if (!reload || (totem_config->interfaces[linknumber].configured == 0)) {
1462
1463 /*
1464 * Get mcast port
1465 */
1466 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport", linknumber);
1467 if (icmap_get_uint16(tmp_key, &totem_config->interfaces[linknumber].ip_port) != CS_OK) {
1468 if (totem_config->broadcast_use) {
1469 totem_config->interfaces[linknumber].ip_port = DEFAULT_PORT + (2 * linknumber);
1470 } else {
1471 totem_config->interfaces[linknumber].ip_port = DEFAULT_PORT + linknumber;
1472 }
1473 }
1474
1475 /*
1476 * Get the TTL
1477 */
1478 totem_config->interfaces[linknumber].ttl = 1;
1479
1480 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl", linknumber);
1481
1482 if (icmap_get_uint8(tmp_key, &u8) == CS_OK) {
1483 totem_config->interfaces[linknumber].ttl = u8;
1484 }
1485
1486 totem_config->interfaces[linknumber].knet_transport = KNET_DEFAULT_TRANSPORT;
1487 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport", linknumber);
1488 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1489 if (strcmp(str, "sctp") == 0) {
1490 totem_config->interfaces[linknumber].knet_transport = KNET_TRANSPORT_SCTP;
1491 }
1492 else if (strcmp(str, "udp") == 0) {
1493 totem_config->interfaces[linknumber].knet_transport = KNET_TRANSPORT_UDP;
1494 }
1495 else {
1496 *error_string = "Unrecognised knet_transport. expected 'udp' or 'sctp'";
1497 return -1;
1498 }
1499 }
1500 }
1501 totem_config->interfaces[linknumber].configured = 1;
1502
1503 /*
1504 * Get the knet link params
1505 */
1506 totem_config->interfaces[linknumber].knet_link_priority = 1;
1507 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority", linknumber);
1508
1509 if (icmap_get_uint8(tmp_key, &u8) == CS_OK) {
1510 totem_config->interfaces[linknumber].knet_link_priority = u8;
1511 }
1512
1513 totem_config->interfaces[linknumber].knet_ping_interval = 0; /* real default applied later */
1514 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval", linknumber);
1515 if (icmap_get_uint32(tmp_key, &u32) == CS_OK) {
1516 totem_config->interfaces[linknumber].knet_ping_interval = u32;
1517 }
1518 totem_config->interfaces[linknumber].knet_ping_timeout = 0; /* real default applied later */
1519 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout", linknumber);
1520 if (icmap_get_uint32(tmp_key, &u32) == CS_OK) {
1521 totem_config->interfaces[linknumber].knet_ping_timeout = u32;
1522 }
1523 totem_config->interfaces[linknumber].knet_ping_precision = KNET_PING_PRECISION;
1524 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision", linknumber);
1525 if (icmap_get_uint32(tmp_key, &u32) == CS_OK) {
1526 totem_config->interfaces[linknumber].knet_ping_precision = u32;
1527 }
1528 totem_config->interfaces[linknumber].knet_pong_count = KNET_PONG_COUNT;
1529 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count", linknumber);
1530 if (icmap_get_uint32(tmp_key, &u32) == CS_OK) {
1531 totem_config->interfaces[linknumber].knet_pong_count = u32;
1532 }
1533
1534 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.", linknumber);
1535 member_iter = icmap_iter_init(tmp_key);
1536 while ((member_iter_key = icmap_iter_next(member_iter, NULL, NULL)) != NULL) {
1537 if (member_count == 0) {
1538 if (icmap_get_string("nodelist.node.0.ring0_addr", &str) == CS_OK) {
1539 free(str);
1540 *warnings |= TOTEM_CONFIG_WARNING_MEMBERS_IGNORED;
1541 break;
1542 } else {
1543 *warnings |= TOTEM_CONFIG_WARNING_MEMBERS_DEPRECATED;
1544 }
1545 }
1546
1547 if (icmap_get_string(member_iter_key, &str) == CS_OK) {
1548 res = totemip_parse (&totem_config->interfaces[linknumber].member_list[member_count++],
1549 str, totem_config->ip_version);
1550 if (res) {
1551 sprintf(error_string_response, "failed to parse node address '%s'\n", str);
1552 *error_string = error_string_response;
1553
1554 icmap_iter_finalize(member_iter);
1555 icmap_iter_finalize(iter);
1556 free(str);
1557 return -1;
1558 }
1559
1560 free(str);
1561 }
1562 }
1563 icmap_iter_finalize(member_iter);
1564
1565 totem_config->interfaces[linknumber].member_count = member_count;
1566
1567 }
1568 icmap_iter_finalize(iter);
1569
1570 return 0;
1571 }
1572
1573 extern int totem_config_read (
1574 struct totem_config *totem_config,
1575 const char **error_string,
1576 uint64_t *warnings)
1577 {
1578 int res = 0;
1579 char *str, *ring0_addr_str;
1580 char tmp_key[ICMAP_KEYNAME_MAXLEN];
1581 uint16_t u16;
1582 int i;
1583 int local_node_pos;
1584 int nodeid_set;
1585
1586 *warnings = 0;
1587
1588 memset (totem_config, 0, sizeof (struct totem_config));
1589 totem_config->interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
1590 if (totem_config->interfaces == 0) {
1591 *error_string = "Out of memory trying to allocate ethernet interface storage area";
1592 return -1;
1593 }
1594
1595 totem_config->transport_number = TOTEM_TRANSPORT_KNET;
1596 if (icmap_get_string("totem.transport", &str) == CS_OK) {
1597 if (strcmp (str, "udpu") == 0) {
1598 totem_config->transport_number = TOTEM_TRANSPORT_UDPU;
1599 }
1600
1601 if (strcmp (str, "udp") == 0) {
1602 totem_config->transport_number = TOTEM_TRANSPORT_UDP;
1603 }
1604
1605 if (strcmp (str, "knet") == 0) {
1606 totem_config->transport_number = TOTEM_TRANSPORT_KNET;
1607 }
1608
1609 free(str);
1610 }
1611
1612 memset (totem_config->interfaces, 0,
1613 sizeof (struct totem_interface) * INTERFACE_MAX);
1614
1615 strcpy (totem_config->link_mode, "passive");
1616
1617 icmap_get_uint32("totem.version", (uint32_t *)&totem_config->version);
1618
1619 if (totem_get_crypto(totem_config, error_string) != 0) {
1620 return -1;
1621 }
1622
1623 if (icmap_get_string("totem.link_mode", &str) == CS_OK) {
1624 if (strlen(str) >= TOTEM_LINK_MODE_BYTES) {
1625 *error_string = "totem.link_mode is too long";
1626 free(str);
1627
1628 return -1;
1629 }
1630 strcpy (totem_config->link_mode, str);
1631 free(str);
1632 }
1633
1634 icmap_get_uint32("totem.nodeid", &totem_config->node_id);
1635
1636 totem_config->clear_node_high_bit = 0;
1637 if (icmap_get_string("totem.clear_node_high_bit", &str) == CS_OK) {
1638 if (strcmp (str, "yes") == 0) {
1639 totem_config->clear_node_high_bit = 1;
1640 }
1641 free(str);
1642 }
1643
1644 icmap_get_uint32("totem.threads", &totem_config->threads);
1645
1646 icmap_get_uint32("totem.netmtu", &totem_config->net_mtu);
1647
1648 totem_config->ip_version = totem_config_get_ip_version(totem_config);
1649
1650 if (icmap_get_string("totem.interface.0.bindnetaddr", &str) != CS_OK) {
1651 /*
1652 * We were not able to find ring 0 bindnet addr. Try to use nodelist informations
1653 */
1654 config_convert_nodelist_to_interface(totem_config);
1655 } else {
1656 if (icmap_get_string("nodelist.node.0.ring0_addr", &ring0_addr_str) == CS_OK) {
1657 /*
1658 * Both bindnetaddr and ring0_addr are set.
1659 * Log warning information, and use nodelist instead
1660 */
1661 *warnings |= TOTEM_CONFIG_BINDNETADDR_NODELIST_SET;
1662
1663 config_convert_nodelist_to_interface(totem_config);
1664
1665 free(ring0_addr_str);
1666 }
1667
1668 free(str);
1669 }
1670
1671 /*
1672 * Broadcast option is global but set in interface section,
1673 * so reset before processing interfaces.
1674 */
1675 totem_config->broadcast_use = 0;
1676
1677 res = get_interface_params(totem_config, error_string, warnings, 0);
1678 if (res < 0) {
1679 return res;
1680 }
1681
1682 /*
1683 * Use broadcast is global, so if set, make sure to fill mcast addr correctly
1684 * broadcast is only supported for UDP so just do interface 0;
1685 */
1686 if (totem_config->broadcast_use) {
1687 totemip_parse (&totem_config->interfaces[0].mcast_addr,
1688 "255.255.255.255", TOTEM_IP_VERSION_4);
1689 }
1690
1691
1692 /*
1693 * Store automatically generated items back to icmap only for UDP
1694 */
1695 if (totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1696 for (i = 0; i < INTERFACE_MAX; i++) {
1697 if (!totem_config->interfaces[i].configured) {
1698 continue;
1699 }
1700 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr", i);
1701 if (icmap_get_string(tmp_key, &str) == CS_OK) {
1702 free(str);
1703 } else {
1704 str = (char *)totemip_print(&totem_config->interfaces[i].mcast_addr);
1705 icmap_set_string(tmp_key, str);
1706 }
1707
1708 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport", i);
1709 if (icmap_get_uint16(tmp_key, &u16) != CS_OK) {
1710 icmap_set_uint16(tmp_key, totem_config->interfaces[i].ip_port);
1711 }
1712 }
1713 }
1714
1715 /*
1716 * Check existence of nodelist
1717 */
1718 if ((icmap_get_string("nodelist.node.0.name", &str) == CS_OK) ||
1719 (icmap_get_string("nodelist.node.0.ring0_addr", &str) == CS_OK)) {
1720 free(str);
1721 /*
1722 * find local node
1723 */
1724 local_node_pos = find_local_node(1);
1725 if (local_node_pos != -1) {
1726
1727 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.nodeid", local_node_pos);
1728
1729 nodeid_set = (totem_config->node_id != 0);
1730 if (icmap_get_uint32(tmp_key, &totem_config->node_id) == CS_OK && nodeid_set) {
1731 *warnings |= TOTEM_CONFIG_WARNING_TOTEM_NODEID_IGNORED;
1732 }
1733 if ((totem_config->transport_number == TOTEM_TRANSPORT_KNET) && (!totem_config->node_id)) {
1734 *error_string = "Knet requires an explicit nodeid for the local node";
1735 return -1;
1736 }
1737
1738 if ((totem_config->transport_number == TOTEM_TRANSPORT_UDP ||
1739 totem_config->transport_number == TOTEM_TRANSPORT_UDPU) && (!totem_config->node_id)) {
1740
1741 snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", local_node_pos);
1742 icmap_get_string(tmp_key, &str);
1743
1744 totem_config->node_id = generate_nodeid(totem_config, str);
1745 totem_config->interfaces[0].member_list[local_node_pos].nodeid = totem_config->node_id;
1746
1747 free(str);
1748 }
1749
1750 /* Users must not change this */
1751 icmap_set_ro_access("nodelist.local_node_pos", 0, 1);
1752 }
1753
1754 if (put_nodelist_members_to_config(totem_config, 0, error_string)) {
1755 return -1;
1756 }
1757 }
1758
1759 /*
1760 * Get things that might change in the future (and can depend on totem_config->interfaces);
1761 */
1762 totem_volatile_config_read(totem_config, NULL);
1763
1764 calc_knet_ping_timers(totem_config);
1765
1766 icmap_set_uint8("config.totemconfig_reload_in_progress", 0);
1767
1768 add_totem_config_notification(totem_config);
1769
1770 return 0;
1771 }
1772
1773
1774 int totem_config_validate (
1775 struct totem_config *totem_config,
1776 const char **error_string)
1777 {
1778 static char local_error_reason[512];
1779 char parse_error[512];
1780 static char addr_str_buf[INET6_ADDRSTRLEN];
1781 const char *error_reason = local_error_reason;
1782 int i,j;
1783 uint32_t u32;
1784 int num_configured = 0;
1785 unsigned int interface_max = INTERFACE_MAX;
1786
1787 for (i = 0; i < INTERFACE_MAX; i++) {
1788 if (totem_config->interfaces[i].configured) {
1789 num_configured++;
1790 }
1791 }
1792 if (num_configured == 0) {
1793 error_reason = "No interfaces defined";
1794 goto parse_error;
1795 }
1796
1797 /* Check we found a local node name */
1798 if (icmap_get_uint32("nodelist.local_node_pos", &u32) != CS_OK) {
1799 error_reason = "No valid name found for local host";
1800 goto parse_error;
1801 }
1802
1803 for (i = 0; i < INTERFACE_MAX; i++) {
1804 /*
1805 * Some error checking of parsed data to make sure its valid
1806 */
1807
1808 struct totem_ip_address null_addr;
1809
1810 if (!totem_config->interfaces[i].configured) {
1811 continue;
1812 }
1813
1814 memset (&null_addr, 0, sizeof (struct totem_ip_address));
1815
1816 if ((totem_config->transport_number == TOTEM_TRANSPORT_UDP) &&
1817 memcmp (&totem_config->interfaces[i].mcast_addr, &null_addr,
1818 sizeof (struct totem_ip_address)) == 0) {
1819 error_reason = "No multicast address specified";
1820 goto parse_error;
1821 }
1822
1823 if (totem_config->interfaces[i].ip_port == 0) {
1824 error_reason = "No multicast port specified";
1825 goto parse_error;
1826 }
1827
1828 if (totem_config->interfaces[i].ttl > 255) {
1829 error_reason = "Invalid TTL (should be 0..255)";
1830 goto parse_error;
1831 }
1832 if (totem_config->transport_number != TOTEM_TRANSPORT_UDP &&
1833 totem_config->interfaces[i].ttl != 1) {
1834 error_reason = "Can only set ttl on multicast transport types";
1835 goto parse_error;
1836 }
1837 if (totem_config->interfaces[i].knet_link_priority > 255) {
1838 error_reason = "Invalid link priority (should be 0..255)";
1839 goto parse_error;
1840 }
1841 if (totem_config->transport_number != TOTEM_TRANSPORT_KNET &&
1842 totem_config->interfaces[i].knet_link_priority != 1) {
1843 error_reason = "Can only set link priority on knet transport type";
1844 goto parse_error;
1845 }
1846
1847 if (totem_config->interfaces[i].mcast_addr.family == AF_INET6 &&
1848 totem_config->node_id == 0) {
1849
1850 error_reason = "An IPV6 network requires that a node ID be specified.";
1851 goto parse_error;
1852 }
1853
1854 if (totem_config->broadcast_use == 0 && totem_config->transport_number == TOTEM_TRANSPORT_UDP) {
1855 if (totem_config->interfaces[i].mcast_addr.family != totem_config->interfaces[i].bindnet.family) {
1856 error_reason = "Multicast address family does not match bind address family";
1857 goto parse_error;
1858 }
1859
1860 if (totemip_is_mcast (&totem_config->interfaces[i].mcast_addr) != 0) {
1861 error_reason = "mcastaddr is not a correct multicast address.";
1862 goto parse_error;
1863 }
1864 }
1865 /* Verify that all nodes on the same knet link have the same IP family */
1866 for (j=1; j<totem_config->interfaces[i].member_count; j++) {
1867 if (totem_config->interfaces[i].configured) {
1868 if (totem_config->interfaces[i].member_list[j].family !=
1869 totem_config->interfaces[i].member_list[0].family) {
1870 memcpy(addr_str_buf,
1871 totemip_print(&(totem_config->interfaces[i].member_list[j])),
1872 sizeof(addr_str_buf));
1873
1874 snprintf (local_error_reason, sizeof(local_error_reason),
1875 "Nodes for link %d have different IP families "
1876 "(compared %s with %s)", i,
1877 addr_str_buf,
1878 totemip_print(&(totem_config->interfaces[i].member_list[0])));
1879 goto parse_error;
1880 }
1881 }
1882 }
1883 }
1884
1885 if (totem_config->version != 2) {
1886 error_reason = "This totem parser can only parse version 2 configurations.";
1887 goto parse_error;
1888 }
1889
1890 if (totem_volatile_config_validate(totem_config, error_string) == -1) {
1891 return (-1);
1892 }
1893
1894 if (check_for_duplicate_nodeids(totem_config, error_string) == -1) {
1895 return (-1);
1896 }
1897
1898 /*
1899 * KNET Link values validation
1900 */
1901 if (strcmp (totem_config->link_mode, "active") &&
1902 strcmp (totem_config->link_mode, "rr") &&
1903 strcmp (totem_config->link_mode, "passive")) {
1904 snprintf (local_error_reason, sizeof(local_error_reason),
1905 "The Knet link mode \"%s\" specified is invalid. It must be active, passive or rr.\n", totem_config->link_mode);
1906 goto parse_error;
1907 }
1908
1909 /* Only Knet does multiple interfaces */
1910 if (totem_config->transport_number != TOTEM_TRANSPORT_KNET) {
1911 interface_max = 1;
1912 }
1913
1914 if (interface_max < num_configured) {
1915 snprintf (parse_error, sizeof(parse_error),
1916 "%d is too many configured interfaces for non-Knet transport.",
1917 num_configured);
1918 error_reason = parse_error;
1919 goto parse_error;
1920 }
1921
1922 /* Only knet allows crypto */
1923 if (totem_config->transport_number != TOTEM_TRANSPORT_KNET) {
1924 if ((strcmp(totem_config->crypto_cipher_type, "none") != 0) ||
1925 (strcmp(totem_config->crypto_hash_type, "none") != 0)) {
1926
1927 snprintf (parse_error, sizeof(parse_error),
1928 "crypto_cipher & crypto_hash are only valid for the Knet transport.");
1929 error_reason = parse_error;
1930 goto parse_error;
1931 }
1932 }
1933
1934 if (totem_config->net_mtu == 0) {
1935 if (totem_config->transport_number == TOTEM_TRANSPORT_KNET) {
1936 totem_config->net_mtu = KNET_MAX_PACKET_SIZE;
1937 }
1938 else {
1939 totem_config->net_mtu = 1500;
1940 }
1941 }
1942
1943 return 0;
1944
1945 parse_error:
1946 snprintf (error_string_response, sizeof(error_string_response),
1947 "parse error in config: %s\n", error_reason);
1948 *error_string = error_string_response;
1949 return (-1);
1950
1951 }
1952
1953 static int read_keyfile (
1954 const char *key_location,
1955 struct totem_config *totem_config,
1956 const char **error_string)
1957 {
1958 int fd;
1959 int res;
1960 int saved_errno;
1961 char error_str[100];
1962 const char *error_ptr;
1963
1964 fd = open (key_location, O_RDONLY);
1965 if (fd == -1) {
1966 error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
1967 snprintf (error_string_response, sizeof(error_string_response),
1968 "Could not open %s: %s\n",
1969 key_location, error_ptr);
1970 goto parse_error;
1971 }
1972
1973 res = read (fd, totem_config->private_key, TOTEM_PRIVATE_KEY_LEN_MAX);
1974 saved_errno = errno;
1975 close (fd);
1976
1977 if (res == -1) {
1978 error_ptr = qb_strerror_r (saved_errno, error_str, sizeof(error_str));
1979 snprintf (error_string_response, sizeof(error_string_response),
1980 "Could not read %s: %s\n",
1981 key_location, error_ptr);
1982 goto parse_error;
1983 }
1984
1985 if (res < TOTEM_PRIVATE_KEY_LEN_MIN) {
1986 snprintf (error_string_response, sizeof(error_string_response),
1987 "Could only read %d bits of minimum %u bits from %s.\n",
1988 res * 8, TOTEM_PRIVATE_KEY_LEN_MIN * 8, key_location);
1989 goto parse_error;
1990 }
1991
1992 totem_config->private_key_len = res;
1993
1994 return 0;
1995
1996 parse_error:
1997 *error_string = error_string_response;
1998 return (-1);
1999 }
2000
2001 int totem_config_keyread (
2002 struct totem_config *totem_config,
2003 const char **error_string)
2004 {
2005 int got_key = 0;
2006 char *key_location = NULL;
2007 int res;
2008 size_t key_len;
2009
2010 memset (totem_config->private_key, 0, sizeof(totem_config->private_key));
2011 totem_config->private_key_len = 0;
2012
2013 if (strcmp(totem_config->crypto_cipher_type, "none") == 0 &&
2014 strcmp(totem_config->crypto_hash_type, "none") == 0) {
2015 return (0);
2016 }
2017
2018 /* cmap may store the location of the key file */
2019 if (icmap_get_string("totem.keyfile", &key_location) == CS_OK) {
2020 res = read_keyfile(key_location, totem_config, error_string);
2021 free(key_location);
2022 if (res) {
2023 goto key_error;
2024 }
2025 got_key = 1;
2026 } else { /* Or the key itself may be in the cmap */
2027 if (icmap_get("totem.key", NULL, &key_len, NULL) == CS_OK) {
2028 if (key_len > sizeof(totem_config->private_key)) {
2029 sprintf(error_string_response, "key is too long");
2030 goto key_error;
2031 }
2032 if (key_len < TOTEM_PRIVATE_KEY_LEN_MIN) {
2033 sprintf(error_string_response, "key is too short");
2034 goto key_error;
2035 }
2036 if (icmap_get("totem.key", totem_config->private_key, &key_len, NULL) == CS_OK) {
2037 totem_config->private_key_len = key_len;
2038 got_key = 1;
2039 } else {
2040 sprintf(error_string_response, "can't load private key");
2041 goto key_error;
2042 }
2043 }
2044 }
2045
2046 /* In desperation we read the default filename */
2047 if (!got_key) {
2048 res = read_keyfile(COROSYSCONFDIR "/authkey", totem_config, error_string);
2049 if (res)
2050 goto key_error;
2051 }
2052
2053 return (0);
2054
2055 key_error:
2056 *error_string = error_string_response;
2057 return (-1);
2058
2059 }
2060
2061 static void debug_dump_totem_config(const struct totem_config *totem_config)
2062 {
2063
2064 log_printf(LOGSYS_LEVEL_DEBUG, "Token Timeout (%d ms) retransmit timeout (%d ms)",
2065 totem_config->token_timeout, totem_config->token_retransmit_timeout);
2066 if (totem_config->token_warning) {
2067 uint32_t token_warning_ms = totem_config->token_warning * totem_config->token_timeout / 100;
2068 log_printf(LOGSYS_LEVEL_DEBUG, "Token warning every %d ms (%d%% of Token Timeout)",
2069 token_warning_ms, totem_config->token_warning);
2070 if (token_warning_ms < totem_config->token_retransmit_timeout)
2071 log_printf (LOGSYS_LEVEL_DEBUG,
2072 "The token warning interval (%d ms) is less than the token retransmit timeout (%d ms) "
2073 "which can lead to spurious token warnings. Consider increasing the token_warning parameter.",
2074 token_warning_ms, totem_config->token_retransmit_timeout);
2075
2076 } else
2077 log_printf(LOGSYS_LEVEL_DEBUG, "Token warnings disabled");
2078 log_printf(LOGSYS_LEVEL_DEBUG, "token hold (%d ms) retransmits before loss (%d retrans)",
2079 totem_config->token_hold_timeout, totem_config->token_retransmits_before_loss_const);
2080 log_printf(LOGSYS_LEVEL_DEBUG, "join (%d ms) send_join (%d ms) consensus (%d ms) merge (%d ms)",
2081 totem_config->join_timeout, totem_config->send_join_timeout, totem_config->consensus_timeout,
2082 totem_config->merge_timeout);
2083 log_printf(LOGSYS_LEVEL_DEBUG, "downcheck (%d ms) fail to recv const (%d msgs)",
2084 totem_config->downcheck_timeout, totem_config->fail_to_recv_const);
2085 log_printf(LOGSYS_LEVEL_DEBUG,
2086 "seqno unchanged const (%d rotations) Maximum network MTU %d",
2087 totem_config->seqno_unchanged_const, totem_config->net_mtu);
2088 log_printf(LOGSYS_LEVEL_DEBUG,
2089 "window size per rotation (%d messages) maximum messages per rotation (%d messages)",
2090 totem_config->window_size, totem_config->max_messages);
2091 log_printf(LOGSYS_LEVEL_DEBUG, "missed count const (%d messages)", totem_config->miss_count_const);
2092 log_printf(LOGSYS_LEVEL_DEBUG, "heartbeat_failures_allowed (%d)",
2093 totem_config->heartbeat_failures_allowed);
2094 log_printf(LOGSYS_LEVEL_DEBUG, "max_network_delay (%d ms)", totem_config->max_network_delay);
2095 }
2096
2097 static void totem_change_notify(
2098 int32_t event,
2099 const char *key_name,
2100 struct icmap_notify_value new_val,
2101 struct icmap_notify_value old_val,
2102 void *user_data)
2103 {
2104 struct totem_config *totem_config = (struct totem_config *)user_data;
2105 uint32_t *param;
2106 uint8_t reloading;
2107 const char *deleted_key = NULL;
2108 const char *error_string;
2109
2110 /*
2111 * If a full reload is in progress then don't do anything until it's done and
2112 * can reconfigure it all atomically
2113 */
2114 if (icmap_get_uint8("config.reload_in_progress", &reloading) == CS_OK && reloading)
2115 return;
2116
2117 param = totem_get_param_by_name((struct totem_config *)user_data, key_name);
2118 /*
2119 * Process change only if changed key is found in totem_config (-> param is not NULL)
2120 * or for special key token_coefficient. token_coefficient key is not stored in
2121 * totem_config, but it is used for computation of token timeout.
2122 */
2123 if (!param && strcmp(key_name, "totem.token_coefficient") != 0)
2124 return;
2125
2126 /*
2127 * Values other than UINT32 are not supported, or needed (yet)
2128 */
2129 switch (event) {
2130 case ICMAP_TRACK_DELETE:
2131 deleted_key = key_name;
2132 break;
2133 case ICMAP_TRACK_ADD:
2134 case ICMAP_TRACK_MODIFY:
2135 deleted_key = NULL;
2136 break;
2137 default:
2138 break;
2139 }
2140
2141 totem_volatile_config_read (totem_config, deleted_key);
2142 log_printf(LOGSYS_LEVEL_DEBUG, "Totem related config key changed. Dumping actual totem config.");
2143 debug_dump_totem_config(totem_config);
2144 if (totem_volatile_config_validate(totem_config, &error_string) == -1) {
2145 log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
2146 /*
2147 * TODO: Consider corosync exit and/or load defaults for volatile
2148 * values. For now, log error seems to be enough
2149 */
2150 }
2151 }
2152
2153 static void totem_reload_notify(
2154 int32_t event,
2155 const char *key_name,
2156 struct icmap_notify_value new_val,
2157 struct icmap_notify_value old_val,
2158 void *user_data)
2159 {
2160 struct totem_config *totem_config = (struct totem_config *)user_data;
2161 const char *error_string;
2162 uint64_t warnings;
2163
2164 /* Reload has completed */
2165 if (*(uint8_t *)new_val.data == 0) {
2166
2167 totem_config->orig_interfaces = malloc (sizeof (struct totem_interface) * INTERFACE_MAX);
2168 assert(totem_config->orig_interfaces != NULL);
2169 memcpy(totem_config->orig_interfaces, totem_config->interfaces, sizeof (struct totem_interface) * INTERFACE_MAX);
2170
2171 get_interface_params(totem_config, &error_string, &warnings, 1);
2172 if (put_nodelist_members_to_config (totem_config, 1, &error_string)) {
2173 log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
2174 }
2175 totem_volatile_config_read (totem_config, NULL);
2176
2177 calc_knet_ping_timers(totem_config);
2178
2179 log_printf(LOGSYS_LEVEL_DEBUG, "Configuration reloaded. Dumping actual totem config.");
2180 debug_dump_totem_config(totem_config);
2181 if (totem_volatile_config_validate(totem_config, &error_string) == -1) {
2182 log_printf (LOGSYS_LEVEL_ERROR, "%s", error_string);
2183 /*
2184 * TODO: Consider corosync exit and/or load defaults for volatile
2185 * values. For now, log error seems to be enough
2186 */
2187 }
2188
2189 /* Reinstate the local_node_pos */
2190 (void)find_local_node(0);
2191
2192 /* Reconfigure network params as appropriate */
2193 totempg_reconfigure();
2194
2195 free(totem_config->orig_interfaces);
2196
2197 icmap_set_uint8("config.totemconfig_reload_in_progress", 0);
2198 } else {
2199 icmap_set_uint8("config.totemconfig_reload_in_progress", 1);
2200 }
2201 }
2202
2203 static void add_totem_config_notification(struct totem_config *totem_config)
2204 {
2205 icmap_track_t icmap_track;
2206
2207 icmap_track_add("totem.",
2208 ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX,
2209 totem_change_notify,
2210 totem_config,
2211 &icmap_track);
2212
2213 icmap_track_add("config.reload_in_progress",
2214 ICMAP_TRACK_ADD | ICMAP_TRACK_MODIFY,
2215 totem_reload_notify,
2216 totem_config,
2217 &icmap_track);
2218 }