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