]> git.proxmox.com Git - corosync-pve.git/blob - patches/0001-cherry-pick-3.0.2-as-patches.patch
buildsys: fix source tarball generation directory level one-off
[corosync-pve.git] / patches / 0001-cherry-pick-3.0.2-as-patches.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
3 Date: Wed, 22 May 2019 12:26:43 +0200
4 Subject: [PATCH] cherry-pick 3.0.2 as patches
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
10 ---
11 ...vateTmp-in-the-systemd-service-files.patch | 4 +-
12 .../Revert-init-Enable-StopWhenUnneeded.patch | 31 +
13 ...-AWK-variable-provided-by-configure.patch} | 8 +-
14 ...-SED-variable-provided-by-configure.patch} | 10 +-
15 .../cfgtool-Fix-link-status-display.patch | 65 +
16 .../cfgtool-Improve-link-status-display.patch | 134 ++
17 .../configure-Do-not-autodetect-nozzle.patch | 114 ++
18 .../configure-Fix-GDB_CFLAGS-typo.patch | 27 +
19 ...e.ac-AC_PROG_SED-is-already-present.patch} | 8 +-
20 .../coroparse-Fix-compiler-warning.patch | 24 +
21 .../corosync-cfgtool-Fix-i-matching.patch | 115 ++
22 .../patches/corosync.conf.5-fix-grammar.patch | 8 +-
23 .../corosync.conf.5-typography-fixes.patch | 8 +-
24 .../cpg-Add-CPG_REASON_UNDEFINED.patch | 152 +++
25 ...rypto-re-introduce-secauth-parameter.patch | 62 +
26 debian/patches/doc-Update-INSTALL-file.patch | 124 ++
27 .../keygen-Reflect-change-in-knet.patch | 100 ++
28 ...ple-of-errors-when-adding-a-new-link.patch | 82 ++
29 ...ix-initialising-of-knet-access-lists.patch | 70 +
30 .../patches/knet-Use-block_unlisted_ips.patch | 67 +
31 ...ow-corosync-to-use-knet-access-lists.patch | 93 ++
32 ...im-man-page-into-distributed-tarball.patch | 40 +
33 ...ahnce-block_unlisted_ips-description.patch | 33 +
34 .../man-Enhance-corosync.conf-mp-a-bit.patch | 37 +
35 ...Enhance-token_retransmit-description.patch | 28 +
36 ...le-Add-support-for-libnozzle-devices.patch | 707 ++++++++++
37 .../quorumtool-Fix-exit-status-codes.patch | 237 ++++
38 ...et-totem.keyfile-and-totem.key-to-RO.patch | 44 +
39 ...port-for-user-flags-configure-option.patch | 43 +
40 ...-Ensure-nodeid-is-specified-for-IPv6.patch | 48 +
41 ...g-Fix-minimum-limit-for-hold-timeout.patch | 67 +
42 .../totemconfig-Remove-support-for-3des.patch | 138 ++
43 ...fig-fix-autogen-mcastaddr-for-ipv6-4.patch | 51 +
44 ...ig-ipaddr_equal-check-just-addr-part.patch | 86 ++
45 .../totemconfig-ipaddr_equal-use-switch.patch | 44 +
46 .../totemip-Use-res-in-totemip_sa_equal.patch | 32 +
47 ...mknet-Ignore-icmap_get_string-result.patch | 32 +
48 ...tialize-return-value-in-setup_nozzle.patch | 39 +
49 ...-create_nozzle_device-simplify-check.patch | 34 +
50 .../totemknet-macaddr_str-is-always-set.patch | 27 +
51 .../totemsrp-Word-spelling-mistake.patch | 24 +
52 .../udpu-Drop-packets-from-unlisted-IPs.patch | 254 ++++
53 .../vqsim-Check-length-of-copied-optarg.patch | 37 +
54 ...sim-Check-length-of-received-message.patch | 42 +
55 ...sim-Check-result-of-icmap_set_uint32.patch | 31 +
56 debian/patches/vqsim-Check-write-result.patch | 33 +
57 ...sim-Do-not-access-unitialized-argv-0.patch | 24 +
58 debian/patches/vqsim-Enhance-vqsim.patch | 1155 +++++++++++++++++
59 .../vqsim-Fix-vqsim-for-corosync-3.0.patch | 102 ++
60 .../vqsim-Free-allocated-newvq-on-error.patch | 23 +
61 debian/patches/vqsim-Make-vqsim-compile.patch | 131 ++
62 .../vqsim-Remove-unused-total_nodes.patch | 62 +
63 debian/patches/series | 57 +-
64 53 files changed, 5034 insertions(+), 14 deletions(-)
65 create mode 100644 debian/patches/Revert-init-Enable-StopWhenUnneeded.patch
66 rename debian/patches/{Use-the-AWK-variable-provided-by-configure.patch => build-Use-the-AWK-variable-provided-by-configure.patch} (78%)
67 rename debian/patches/{Use-the-SED-variable-provided-by-configure.patch => build-Use-the-SED-variable-provided-by-configure.patch} (94%)
68 create mode 100644 debian/patches/cfgtool-Fix-link-status-display.patch
69 create mode 100644 debian/patches/cfgtool-Improve-link-status-display.patch
70 create mode 100644 debian/patches/configure-Do-not-autodetect-nozzle.patch
71 create mode 100644 debian/patches/configure-Fix-GDB_CFLAGS-typo.patch
72 rename debian/patches/{AC_PROG_SED-is-already-present.patch => configure.ac-AC_PROG_SED-is-already-present.patch} (62%)
73 create mode 100644 debian/patches/coroparse-Fix-compiler-warning.patch
74 create mode 100644 debian/patches/corosync-cfgtool-Fix-i-matching.patch
75 create mode 100644 debian/patches/cpg-Add-CPG_REASON_UNDEFINED.patch
76 create mode 100644 debian/patches/crypto-re-introduce-secauth-parameter.patch
77 create mode 100644 debian/patches/doc-Update-INSTALL-file.patch
78 create mode 100644 debian/patches/keygen-Reflect-change-in-knet.patch
79 create mode 100644 debian/patches/knet-Fix-a-couple-of-errors-when-adding-a-new-link.patch
80 create mode 100644 debian/patches/knet-Fix-initialising-of-knet-access-lists.patch
81 create mode 100644 debian/patches/knet-Use-block_unlisted_ips.patch
82 create mode 100644 debian/patches/knet-allow-corosync-to-use-knet-access-lists.patch
83 create mode 100644 debian/patches/man-Add-vqsim-man-page-into-distributed-tarball.patch
84 create mode 100644 debian/patches/man-Enahnce-block_unlisted_ips-description.patch
85 create mode 100644 debian/patches/man-Enhance-corosync.conf-mp-a-bit.patch
86 create mode 100644 debian/patches/man-Enhance-token_retransmit-description.patch
87 create mode 100644 debian/patches/nozzle-Add-support-for-libnozzle-devices.patch
88 create mode 100644 debian/patches/quorumtool-Fix-exit-status-codes.patch
89 create mode 100644 debian/patches/set-totem.keyfile-and-totem.key-to-RO.patch
90 create mode 100644 debian/patches/spec-Add-support-for-user-flags-configure-option.patch
91 create mode 100644 debian/patches/totemconfig-Ensure-nodeid-is-specified-for-IPv6.patch
92 create mode 100644 debian/patches/totemconfig-Fix-minimum-limit-for-hold-timeout.patch
93 create mode 100644 debian/patches/totemconfig-Remove-support-for-3des.patch
94 create mode 100644 debian/patches/totemconfig-fix-autogen-mcastaddr-for-ipv6-4.patch
95 create mode 100644 debian/patches/totemconfig-ipaddr_equal-check-just-addr-part.patch
96 create mode 100644 debian/patches/totemconfig-ipaddr_equal-use-switch.patch
97 create mode 100644 debian/patches/totemip-Use-res-in-totemip_sa_equal.patch
98 create mode 100644 debian/patches/totemknet-Ignore-icmap_get_string-result.patch
99 create mode 100644 debian/patches/totemknet-Initialize-return-value-in-setup_nozzle.patch
100 create mode 100644 debian/patches/totemknet-create_nozzle_device-simplify-check.patch
101 create mode 100644 debian/patches/totemknet-macaddr_str-is-always-set.patch
102 create mode 100644 debian/patches/totemsrp-Word-spelling-mistake.patch
103 create mode 100644 debian/patches/udpu-Drop-packets-from-unlisted-IPs.patch
104 create mode 100644 debian/patches/vqsim-Check-length-of-copied-optarg.patch
105 create mode 100644 debian/patches/vqsim-Check-length-of-received-message.patch
106 create mode 100644 debian/patches/vqsim-Check-result-of-icmap_set_uint32.patch
107 create mode 100644 debian/patches/vqsim-Check-write-result.patch
108 create mode 100644 debian/patches/vqsim-Do-not-access-unitialized-argv-0.patch
109 create mode 100644 debian/patches/vqsim-Enhance-vqsim.patch
110 create mode 100644 debian/patches/vqsim-Fix-vqsim-for-corosync-3.0.patch
111 create mode 100644 debian/patches/vqsim-Free-allocated-newvq-on-error.patch
112 create mode 100644 debian/patches/vqsim-Make-vqsim-compile.patch
113 create mode 100644 debian/patches/vqsim-Remove-unused-total_nodes.patch
114
115 diff --git a/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch b/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch
116 index 45d24d3d..b4644516 100644
117 --- a/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch
118 +++ b/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch
119 @@ -20,10 +20,10 @@ index 410a683..9247cbc 100644
120 [Install]
121 WantedBy=multi-user.target
122 diff --git a/init/corosync.service.in b/init/corosync.service.in
123 -index bf757d8..dc99a4a 100644
124 +index 654e41f..0c74306 100644
125 --- a/init/corosync.service.in
126 +++ b/init/corosync.service.in
127 -@@ -29,6 +29,7 @@ StandardError=null
128 +@@ -28,6 +28,7 @@ StandardError=null
129 #RestartSec=70
130 # rewrite according to environment.
131 #ExecStartPre=/sbin/modprobe softdog
132 diff --git a/debian/patches/Revert-init-Enable-StopWhenUnneeded.patch b/debian/patches/Revert-init-Enable-StopWhenUnneeded.patch
133 new file mode 100644
134 index 00000000..29fb842d
135 --- /dev/null
136 +++ b/debian/patches/Revert-init-Enable-StopWhenUnneeded.patch
137 @@ -0,0 +1,31 @@
138 +From: Jan Friesse <jfriesse@redhat.com>
139 +Date: Thu, 4 Apr 2019 11:40:19 +0200
140 +Subject: Revert "init: Enable StopWhenUnneeded"
141 +
142 +This reverts commit 03d9321bc80887d4578744c26c05d61e2d9d4278.
143 +
144 +Reverted because when corosync service is not enabled and corosync
145 +is executed by "systemctl start corosync" it is then immediately
146 +shutdown because of "Unit not needed anymore. Stopping.".
147 +
148 +This is really not expected behavior.
149 +
150 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
151 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
152 +(cherry picked from commit 527e30a8d050c077d8adff2a5aa77d9b683a8f28)
153 +---
154 + init/corosync.service.in | 1 -
155 + 1 file changed, 1 deletion(-)
156 +
157 +diff --git a/init/corosync.service.in b/init/corosync.service.in
158 +index bf757d8..654e41f 100644
159 +--- a/init/corosync.service.in
160 ++++ b/init/corosync.service.in
161 +@@ -4,7 +4,6 @@ Documentation=man:corosync man:corosync.conf man:corosync_overview
162 + ConditionKernelCommandLine=!nocluster
163 + Requires=network-online.target
164 + After=network-online.target
165 +-StopWhenUnneeded=yes
166 +
167 + [Service]
168 + EnvironmentFile=-@INITCONFIGDIR@/corosync
169 diff --git a/debian/patches/Use-the-AWK-variable-provided-by-configure.patch b/debian/patches/build-Use-the-AWK-variable-provided-by-configure.patch
170 similarity index 78%
171 rename from debian/patches/Use-the-AWK-variable-provided-by-configure.patch
172 rename to debian/patches/build-Use-the-AWK-variable-provided-by-configure.patch
173 index 85511c66..61407483 100644
174 --- a/debian/patches/Use-the-AWK-variable-provided-by-configure.patch
175 +++ b/debian/patches/build-Use-the-AWK-variable-provided-by-configure.patch
176 @@ -1,7 +1,13 @@
177 From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
178 Date: Tue, 29 Jan 2019 15:25:18 +0100
179 -Subject: Use the AWK variable provided by configure
180 +Subject: build: Use the AWK variable provided by configure
181 +MIME-Version: 1.0
182 +Content-Type: text/plain; charset="utf-8"
183 +Content-Transfer-Encoding: 8bit
184
185 +Signed-off-by: Ferenc Wágner <wferi@debian.org>
186 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
187 +(cherry picked from commit b09b96fe6ff5a77e637efb692ed37b6c80f40ba3)
188 ---
189 man/Makefile.am | 4 ++--
190 1 file changed, 2 insertions(+), 2 deletions(-)
191 diff --git a/debian/patches/Use-the-SED-variable-provided-by-configure.patch b/debian/patches/build-Use-the-SED-variable-provided-by-configure.patch
192 similarity index 94%
193 rename from debian/patches/Use-the-SED-variable-provided-by-configure.patch
194 rename to debian/patches/build-Use-the-SED-variable-provided-by-configure.patch
195 index 672d4817..1c2941c5 100644
196 --- a/debian/patches/Use-the-SED-variable-provided-by-configure.patch
197 +++ b/debian/patches/build-Use-the-SED-variable-provided-by-configure.patch
198 @@ -1,7 +1,13 @@
199 From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
200 Date: Tue, 29 Jan 2019 15:24:19 +0100
201 -Subject: Use the SED variable provided by configure
202 +Subject: build: Use the SED variable provided by configure
203 +MIME-Version: 1.0
204 +Content-Type: text/plain; charset="utf-8"
205 +Content-Transfer-Encoding: 8bit
206
207 +Signed-off-by: Ferenc Wágner <wferi@debian.org>
208 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
209 +(cherry picked from commit 6a476017b998e02bc4c1b88e78f86bc11f16ae7f)
210 ---
211 Makefile.am | 8 ++++----
212 conf/logrotate/Makefile.am | 10 +++++-----
213 @@ -141,7 +147,7 @@ index 131d675..1994a3c 100644
214
215 LINT_FILES1:=$(filter-out sa_error.c, $(wildcard *.c))
216 diff --git a/tools/Makefile.am b/tools/Makefile.am
217 -index 14520c2..7a9ab04 100644
218 +index 8825498..0793884 100644
219 --- a/tools/Makefile.am
220 +++ b/tools/Makefile.am
221 @@ -49,12 +49,12 @@ EXTRA_DIST = corosync-xmlproc.sh \
222 diff --git a/debian/patches/cfgtool-Fix-link-status-display.patch b/debian/patches/cfgtool-Fix-link-status-display.patch
223 new file mode 100644
224 index 00000000..b441458b
225 --- /dev/null
226 +++ b/debian/patches/cfgtool-Fix-link-status-display.patch
227 @@ -0,0 +1,65 @@
228 +From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
229 +Date: Wed, 29 May 2019 14:57:09 +0200
230 +Subject: cfgtool: Fix link status display
231 +MIME-Version: 1.0
232 +Content-Type: text/plain; charset="utf-8"
233 +Content-Transfer-Encoding: 8bit
234 +
235 +instead of the nodeid, this displayed arbitrary values (usually '1')
236 +from other cmap keys under nodelist.node.XX.
237 +
238 +sscanf returns the number of conversions even on mismatch, e.g. it also
239 +returns 1 for
240 +
241 +nodelist.node.2.quorum_votes
242 +nodelist.node.2.ring0_addr
243 +nodelist.node.2.name
244 +...
245 +
246 +instead of just
247 +
248 +nodelist.node.2.nodeid
249 +
250 +which leads to the value of (at least) quorum_votes being stored in
251 +nodeid_list in addition to the actual nodeid.
252 +
253 +storing the returned int in a cs_error_t enum also potentially masks
254 +errors, so just compare the result with the expectation directly.
255 +
256 +Fixes: c0d14485c3ebdeb2332f7c48acd155163e5b7fc1
257 +
258 +Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
259 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
260 +(cherry picked from commit ef2569d323c68633a63dc15e59805ec491b69348)
261 +---
262 + tools/corosync-cfgtool.c | 10 +++++++---
263 + 1 file changed, 7 insertions(+), 3 deletions(-)
264 +
265 +diff --git a/tools/corosync-cfgtool.c b/tools/corosync-cfgtool.c
266 +index a43ee1e..f51b9d4 100644
267 +--- a/tools/corosync-cfgtool.c
268 ++++ b/tools/corosync-cfgtool.c
269 +@@ -100,7 +100,7 @@ linkstatusget_do (char *interface_name, int brief)
270 + unsigned int i;
271 + cmap_iter_handle_t iter;
272 + unsigned int nodeid;
273 +- unsigned int node_pos;
274 ++ int nodeid_match_guard;
275 + cmap_value_types_t type;
276 + size_t value_len;
277 + int rc = 0;
278 +@@ -128,8 +128,12 @@ linkstatusget_do (char *interface_name, int brief)
279 + }
280 +
281 + while ((cmap_iter_next(cmap_handle, iter, iter_key, &value_len, &type)) == CS_OK) {
282 +- result = sscanf(iter_key, "nodelist.node.%u.nodeid", &node_pos);
283 +- if (result != 1) {
284 ++ nodeid_match_guard = 0;
285 ++ if (sscanf(iter_key, "nodelist.node.%*u.nodeid%n", &nodeid_match_guard) != 0) {
286 ++ continue;
287 ++ }
288 ++ /* check for exact match */
289 ++ if (nodeid_match_guard != strlen(iter_key)) {
290 + continue;
291 + }
292 + if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
293 diff --git a/debian/patches/cfgtool-Improve-link-status-display.patch b/debian/patches/cfgtool-Improve-link-status-display.patch
294 new file mode 100644
295 index 00000000..e05732bf
296 --- /dev/null
297 +++ b/debian/patches/cfgtool-Improve-link-status-display.patch
298 @@ -0,0 +1,134 @@
299 +From: Christine Caulfield <ccaulfie@redhat.com>
300 +Date: Tue, 22 Jan 2019 10:06:29 +0000
301 +Subject: cfgtool: Improve link status display
302 +
303 +Now show the nodeids properly, rather than node indexes which were
304 +annoying and unhelpful.
305 +
306 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
307 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
308 +(cherry picked from commit c0d14485c3ebdeb2332f7c48acd155163e5b7fc1)
309 +---
310 + tools/Makefile.am | 2 +-
311 + tools/corosync-cfgtool.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++--
312 + 2 files changed, 55 insertions(+), 3 deletions(-)
313 +
314 +diff --git a/tools/Makefile.am b/tools/Makefile.am
315 +index 14520c2..8825498 100644
316 +--- a/tools/Makefile.am
317 ++++ b/tools/Makefile.am
318 +@@ -58,7 +58,7 @@ corosync-blackbox: corosync-blackbox.sh
319 +
320 + corosync_cmapctl_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcmap.la
321 +
322 +-corosync_cfgtool_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la
323 ++corosync_cfgtool_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la $(top_builddir)/lib/libcmap.la
324 +
325 + corosync_cpgtool_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la \
326 + $(top_builddir)/lib/libcpg.la
327 +diff --git a/tools/corosync-cfgtool.c b/tools/corosync-cfgtool.c
328 +index c138085..ed29694 100644
329 +--- a/tools/corosync-cfgtool.c
330 ++++ b/tools/corosync-cfgtool.c
331 +@@ -50,6 +50,7 @@
332 + #include <corosync/corotypes.h>
333 + #include <corosync/totem/totem.h>
334 + #include <corosync/cfg.h>
335 ++#include <corosync/cmap.h>
336 +
337 + #define cs_repeat(result, max, code) \
338 + do { \
339 +@@ -75,16 +76,33 @@ enum user_action {
340 + ACTION_KILL_NODE,
341 + };
342 +
343 ++static int node_compare(const void *aptr, const void *bptr)
344 ++{
345 ++ uint32_t a,b;
346 ++
347 ++ a = *(uint32_t *)aptr;
348 ++ b = *(uint32_t *)bptr;
349 ++
350 ++ return a > b;
351 ++}
352 ++
353 + static int
354 + linkstatusget_do (char *interface_name, int brief)
355 + {
356 + cs_error_t result;
357 + corosync_cfg_handle_t handle;
358 ++ cmap_handle_t cmap_handle;
359 + unsigned int interface_count;
360 + char **interface_names;
361 + char **interface_status;
362 ++ uint32_t nodeid_list[KNET_MAX_HOST];
363 ++ char iter_key[CMAP_KEYNAME_MAXLEN];
364 + unsigned int i;
365 ++ cmap_iter_handle_t iter;
366 + unsigned int nodeid;
367 ++ unsigned int node_pos;
368 ++ cmap_value_types_t type;
369 ++ size_t value_len;
370 + int rc = 0;
371 + int len, s = 0, t;
372 +
373 +@@ -95,6 +113,37 @@ linkstatusget_do (char *interface_name, int brief)
374 + exit (1);
375 + }
376 +
377 ++ result = cmap_initialize (&cmap_handle);
378 ++ if (result != CS_OK) {
379 ++ printf ("Could not initialize corosync cmap API error %d\n", result);
380 ++ exit (1);
381 ++ }
382 ++ /* Get a list of nodes. We do it this way rather than using votequorum as cfgtool
383 ++ * needs to be independent of quorum type
384 ++ */
385 ++ result = cmap_iter_init(cmap_handle, "nodelist.node.", &iter);
386 ++ if (result != CS_OK) {
387 ++ printf ("Could not get nodelist from cmap. error %d\n", result);
388 ++ exit (1);
389 ++ }
390 ++
391 ++ while ((cmap_iter_next(cmap_handle, iter, iter_key, &value_len, &type)) == CS_OK) {
392 ++ result = sscanf(iter_key, "nodelist.node.%u.nodeid", &node_pos);
393 ++ if (result != 1) {
394 ++ continue;
395 ++ }
396 ++ if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
397 ++ nodeid_list[s++] = nodeid;
398 ++ }
399 ++ }
400 ++
401 ++ /* totemknet returns nodes in nodeid order - even though it doesn't tell us
402 ++ what the nodeid is. So sort our node list and we can then look up
403 ++ knet node pos to get an actual nodeid.
404 ++ Yep, I really should have totally rewritten the cfg interface for this.
405 ++ */
406 ++ qsort(nodeid_list, s, sizeof(uint32_t), node_compare);
407 ++
408 + result = corosync_cfg_local_get(handle, &nodeid);
409 + if (result != CS_OK) {
410 + printf ("Could not get the local node id, the error is: %d\n", result);
411 +@@ -134,9 +183,11 @@ linkstatusget_do (char *interface_name, int brief)
412 + (!strstr(interface_status[i], "FAULTY"))) {
413 + len = strlen(interface_status[i]);
414 + printf ("\tstatus:\n");
415 +- while(s < len) {
416 ++ while (s < len) {
417 ++ nodeid = nodeid_list[s];
418 + t = interface_status[i][s] - '0';
419 +- printf("\t\tnode %d:\t", s++);
420 ++ s++;
421 ++ printf("\t\tnodeid %2d:\t", nodeid);
422 + printf("link enabled:%d\t", t&1? 1 : 0);
423 + printf("link connected:%d\n", t&2? 1: 0);
424 + }
425 +@@ -157,6 +208,7 @@ linkstatusget_do (char *interface_name, int brief)
426 + free(interface_names);
427 + }
428 +
429 ++ (void)cmap_finalize (cmap_handle);
430 + (void)corosync_cfg_finalize (handle);
431 + return rc;
432 + }
433 diff --git a/debian/patches/configure-Do-not-autodetect-nozzle.patch b/debian/patches/configure-Do-not-autodetect-nozzle.patch
434 new file mode 100644
435 index 00000000..6d66e433
436 --- /dev/null
437 +++ b/debian/patches/configure-Do-not-autodetect-nozzle.patch
438 @@ -0,0 +1,114 @@
439 +From: Jan Friesse <jfriesse@redhat.com>
440 +Date: Tue, 26 Feb 2019 11:04:16 +0100
441 +Subject: configure: Do not autodetect nozzle
442 +
443 +Nozzle is part of kronosnet but it is independent library. Enabling it
444 +when detected without ability to turn it off is not in line with
445 +other libraries.
446 +
447 +Solution is to use same method as for other libraries - add
448 +--enable-nozzle to configure script and add support for this option into
449 +spec file.
450 +
451 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
452 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
453 +(cherry picked from commit 83dc407f550a5b67f134dc41da6282f7b80d0ba2)
454 +---
455 + configure.ac | 21 ++++++++++++++-------
456 + corosync.spec.in | 7 +++++++
457 + 2 files changed, 21 insertions(+), 7 deletions(-)
458 +
459 +diff --git a/configure.ac b/configure.ac
460 +index 95cdb35..14c0e17 100644
461 +--- a/configure.ac
462 ++++ b/configure.ac
463 +@@ -174,7 +174,6 @@ LIBS="$SAVE_LIBS"
464 + AC_CHECK_LIB([pthread], [pthread_create])
465 + AC_CHECK_LIB([socket], [socket])
466 + PKG_CHECK_MODULES([knet],[libknet])
467 +-PKG_CHECK_MODULES([nozzle],[libnozzle], [AC_DEFINE_UNQUOTED([HAVE_LIBNOZZLE], 1, [Have libnozzle])], [have_nozzle="no"])
468 + AC_CHECK_LIB([nsl], [t_open])
469 + AC_CHECK_LIB([rt], [sched_getscheduler])
470 + AC_CHECK_LIB([z], [crc32],
471 +@@ -395,21 +394,20 @@ AC_ARG_ENABLE([xmlconf],
472 + AM_CONDITIONAL(INSTALL_XMLCONF, test x$enable_xmlconf = xyes)
473 +
474 + AC_ARG_ENABLE([vqsim],
475 +- [ --enable-vqsim : Quorum simulator support ],,
476 ++ [ --enable-vqsim : Quorum simulator support ],,
477 + [ enable_vqsim="no" ])
478 + AM_CONDITIONAL(BUILD_VQSIM, test x$enable_vqsim = xyes)
479 +
480 ++AC_ARG_ENABLE([nozzle],
481 ++ [ --enable-nozzle : Support for nozzle ],,
482 ++ [ enable_nozzle="no" ])
483 ++
484 + # *FLAGS handling goes here
485 +
486 + ENV_CFLAGS="$CFLAGS"
487 + ENV_CPPFLAGS="$CPPFLAGS"
488 + ENV_LDFLAGS="$LDFLAGS"
489 +
490 +-# Add nozzle to Package features if enabled
491 +-if test "x$have_nozzle" != xno; then
492 +- PACKAGE_FEATURES="$PACKAGE_FEATURES nozzle"
493 +-fi
494 +-
495 + # debug build stuff
496 + if test "x${enable_debug}" = xyes; then
497 + AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code])
498 +@@ -426,6 +424,7 @@ else
499 + GDB_FLAGS="-g"
500 + fi
501 +
502 ++
503 + # Look for dbus-1
504 + if test "x${enable_dbus}" = xyes; then
505 + PKG_CHECK_MODULES([DBUS],[dbus-1])
506 +@@ -474,6 +473,14 @@ if test "x${enable_vqsim}" = xyes; then
507 + fi
508 + AM_CONDITIONAL(VQSIM_READLINE, [test "x${ac_cv_header_readline_readline_h}" = xyes])
509 +
510 ++# Look for nozzle
511 ++if test "x${enable_nozzle}" = xyes; then
512 ++ PKG_CHECK_MODULES([nozzle],[libnozzle])
513 ++ AC_DEFINE_UNQUOTED([HAVE_LIBNOZZLE], 1, [have nozzle])
514 ++ PACKAGE_FEATURES="$PACKAGE_FEATURES nozzle"
515 ++ WITH_LIST="$WITH_LIST --with nozzle"
516 ++fi
517 ++
518 + do_snmp=0
519 + if test "x${enable_snmp}" = xyes; then
520 + AC_PATH_PROGS([SNMPCONFIG], [net-snmp-config])
521 +diff --git a/corosync.spec.in b/corosync.spec.in
522 +index bf5bfc2..07c004c 100644
523 +--- a/corosync.spec.in
524 ++++ b/corosync.spec.in
525 +@@ -11,6 +11,7 @@
526 + %bcond_with dbus
527 + %bcond_with systemd
528 + %bcond_with xmlconf
529 ++%bcond_with nozzle
530 + %bcond_with runautogen
531 +
532 + %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}
533 +@@ -55,6 +56,9 @@ BuildRequires: dbus-1-devel
534 + BuildRequires: dbus-devel
535 + %endif
536 + %endif
537 ++%if %{with nozzle}
538 ++BuildRequires: libnozzle1-devel
539 ++%endif
540 + %if %{with systemd}
541 + %{?systemd_requires}
542 + BuildRequires: systemd
543 +@@ -93,6 +97,9 @@ Requires: libxslt
544 + %endif
545 + %if %{with xmlconf}
546 + --enable-xmlconf \
547 ++%endif
548 ++%if %{with nozzle}
549 ++ --enable-nozzle \
550 + %endif
551 + --with-initddir=%{_initrddir} \
552 + --with-systemddir=%{_unitdir} \
553 diff --git a/debian/patches/configure-Fix-GDB_CFLAGS-typo.patch b/debian/patches/configure-Fix-GDB_CFLAGS-typo.patch
554 new file mode 100644
555 index 00000000..8c1340d6
556 --- /dev/null
557 +++ b/debian/patches/configure-Fix-GDB_CFLAGS-typo.patch
558 @@ -0,0 +1,27 @@
559 +From: Jan Friesse <jfriesse@redhat.com>
560 +Date: Mon, 10 Jun 2019 10:56:10 +0200
561 +Subject: configure: Fix GDB_CFLAGS typo
562 +
563 +GDB_FLAGS (without C) is the correct name of variable
564 +to print in the summary.
565 +
566 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
567 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
568 +(cherry picked from commit 45d19a2d90bc2e926974e5668f85c17b37688637)
569 +---
570 + configure.ac | 2 +-
571 + 1 file changed, 1 insertion(+), 1 deletion(-)
572 +
573 +diff --git a/configure.ac b/configure.ac
574 +index 82479f9..22b7898 100644
575 +--- a/configure.ac
576 ++++ b/configure.ac
577 +@@ -746,7 +746,7 @@ AC_MSG_RESULT([$PACKAGE build info:])
578 + AC_MSG_RESULT([ Library SONAME = ${SONAME}])
579 + LIB_MSG_RESULT(m4_shift(local_soname_list))dnl
580 + AC_MSG_RESULT([ Default optimization = ${OPT_CFLAGS}])
581 +-AC_MSG_RESULT([ Default debug options = ${GDB_CFLAGS}])
582 ++AC_MSG_RESULT([ Default debug options = ${GDB_FLAGS}])
583 + AC_MSG_RESULT([ Extra compiler warnings = ${EXTRA_WARNING}])
584 + AC_MSG_RESULT([ Env. defined CFLAG = ${ENV_CFLAGS}])
585 + AC_MSG_RESULT([ Env. defined CPPFLAGS = ${ENV_CPPFLAGS}])
586 diff --git a/debian/patches/AC_PROG_SED-is-already-present.patch b/debian/patches/configure.ac-AC_PROG_SED-is-already-present.patch
587 similarity index 62%
588 rename from debian/patches/AC_PROG_SED-is-already-present.patch
589 rename to debian/patches/configure.ac-AC_PROG_SED-is-already-present.patch
590 index 7547a7e7..fa970bcf 100644
591 --- a/debian/patches/AC_PROG_SED-is-already-present.patch
592 +++ b/debian/patches/configure.ac-AC_PROG_SED-is-already-present.patch
593 @@ -1,7 +1,13 @@
594 From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
595 Date: Tue, 29 Jan 2019 15:15:27 +0100
596 -Subject: AC_PROG_SED is already present
597 +Subject: configure.ac: AC_PROG_SED is already present
598 +MIME-Version: 1.0
599 +Content-Type: text/plain; charset="utf-8"
600 +Content-Transfer-Encoding: 8bit
601
602 +Signed-off-by: Ferenc Wágner <wferi@debian.org>
603 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
604 +(cherry picked from commit b9cc5be3a2ee7acd45486c821785cddffba3a48e)
605 ---
606 configure.ac | 1 -
607 1 file changed, 1 deletion(-)
608 diff --git a/debian/patches/coroparse-Fix-compiler-warning.patch b/debian/patches/coroparse-Fix-compiler-warning.patch
609 new file mode 100644
610 index 00000000..418a4625
611 --- /dev/null
612 +++ b/debian/patches/coroparse-Fix-compiler-warning.patch
613 @@ -0,0 +1,24 @@
614 +From: Jan Friesse <jfriesse@redhat.com>
615 +Date: Tue, 26 Feb 2019 13:28:08 +0100
616 +Subject: coroparse: Fix compiler warning
617 +
618 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
619 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
620 +(cherry picked from commit 7c825173deae33645d4c24d091a86162ac5ba28e)
621 +---
622 + exec/coroparse.c | 2 +-
623 + 1 file changed, 1 insertion(+), 1 deletion(-)
624 +
625 +diff --git a/exec/coroparse.c b/exec/coroparse.c
626 +index bee0a8c..08f8f14 100644
627 +--- a/exec/coroparse.c
628 ++++ b/exec/coroparse.c
629 +@@ -596,7 +596,7 @@ static int main_config_parser_cb(const char *path,
630 + * Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
631 + * are using path, so initialize key_name to valid value
632 + */
633 +- strncpy(key_name, path, sizeof(key_name));
634 ++ strncpy(key_name, path, sizeof(key_name) - 1);
635 +
636 + switch (type) {
637 + case PARSER_CB_START:
638 diff --git a/debian/patches/corosync-cfgtool-Fix-i-matching.patch b/debian/patches/corosync-cfgtool-Fix-i-matching.patch
639 new file mode 100644
640 index 00000000..bb8cb73d
641 --- /dev/null
642 +++ b/debian/patches/corosync-cfgtool-Fix-i-matching.patch
643 @@ -0,0 +1,115 @@
644 +From: Jan Friesse <jfriesse@redhat.com>
645 +Date: Wed, 13 Feb 2019 12:54:55 +0100
646 +Subject: corosync-cfgtool: Fix -i matching
647 +
648 +Previously it was required to use link id together with IP address (ex.
649 +"0 127.0.0.1") as a -i parameter.
650 +
651 +This was reported as not very user friendly. Solution is to split
652 +returned interface name and try match link id and ip address
653 +separately.
654 +
655 +Also fix typo in description of parameter -s.
656 +
657 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
658 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
659 +(cherry picked from commit 4f9e46e7a820986c81a528cae0e0f44a6f17db3c)
660 +---
661 + tools/corosync-cfgtool.c | 42 +++++++++++++++++++++++-------------------
662 + man/corosync-cfgtool.8 | 6 +++---
663 + 2 files changed, 26 insertions(+), 22 deletions(-)
664 +
665 +diff --git a/tools/corosync-cfgtool.c b/tools/corosync-cfgtool.c
666 +index ed29694..a43ee1e 100644
667 +--- a/tools/corosync-cfgtool.c
668 ++++ b/tools/corosync-cfgtool.c
669 +@@ -1,5 +1,5 @@
670 + /*
671 +- * Copyright (c) 2006-2017 Red Hat, Inc.
672 ++ * Copyright (c) 2006-2019 Red Hat, Inc.
673 + *
674 + * All rights reserved.
675 + *
676 +@@ -160,25 +160,29 @@ linkstatusget_do (char *interface_name, int brief)
677 + printf ("Could not get the link status, the error is: %d\n", result);
678 + } else {
679 + for (i = 0; i < interface_count; i++) {
680 ++ char *cur_iface_name_space = strchr(interface_names[i], ' ');
681 ++ int show_current_iface;
682 ++
683 + s = 0;
684 +- if ( (interface_name &&
685 +- interface_names[i][0] != '\0' &&
686 +- (interface_name[0]=='\0' ||
687 +- strcasecmp (interface_name, interface_names[i]) == 0)) ||
688 +- !interface_name ) {
689 +-
690 +- /*
691 +- * Interface_name is "<linkid> <IP address>"
692 +- * separate them out
693 +- */
694 +- char *space = strchr(interface_names[i], ' ');
695 +- if (!space) {
696 +- continue;
697 +- }
698 +- *space = '\0';
699 ++ /*
700 ++ * Interface_name is "<linkid> <IP address>"
701 ++ * separate them out
702 ++ */
703 ++ if (!cur_iface_name_space) {
704 ++ continue;
705 ++ }
706 ++ *cur_iface_name_space = '\0';
707 ++
708 ++ show_current_iface = 1;
709 ++ if (interface_name != NULL && interface_name[0] != '\0' &&
710 ++ strcmp(interface_name, interface_names[i]) != 0 &&
711 ++ strcmp(interface_name, cur_iface_name_space + 1) != 0) {
712 ++ show_current_iface = 0;
713 ++ }
714 +
715 ++ if (show_current_iface) {
716 + printf ("LINK ID %s\n", interface_names[i]);
717 +- printf ("\taddr\t= %s\n", space+1);
718 ++ printf ("\taddr\t= %s\n", cur_iface_name_space + 1);
719 + if((!brief) && (strcmp(interface_status[i], "OK") != 0) &&
720 + (!strstr(interface_status[i], "FAULTY"))) {
721 + len = strlen(interface_status[i]);
722 +@@ -361,8 +365,8 @@ static void usage_do (void)
723 + printf ("corosync-cfgtool [[-i <interface ip>] [-b] -s] [-R] [-L] [-k nodeid] [-a nodeid] [-h] [-H]\n\n");
724 + printf ("A tool for displaying and configuring active parameters within corosync.\n");
725 + printf ("options:\n");
726 +- printf ("\t-i\tFinds only information about the specified interface IP address when used with -s..\n");
727 +- printf ("\t-s\tDisplays the status of the current links on this node(UDP/UDPU), while extended status for KNET.\n");
728 ++ printf ("\t-i\tFinds only information about the specified interface IP address or link id when used with -s..\n");
729 ++ printf ("\t-s\tDisplays the status of the current links on this node(UDP/UDPU), with extended status for KNET.\n");
730 + printf ("\t-b\tDisplays the brief status of the current links on this node when used with -s.(KNET only)\n");
731 + printf ("\t-R\tTell all instances of corosync in this cluster to reload corosync.conf.\n");
732 + printf ("\t-L\tTell corosync to reopen all logging files.\n");
733 +diff --git a/man/corosync-cfgtool.8 b/man/corosync-cfgtool.8
734 +index 9ac3da9..07e63b4 100644
735 +--- a/man/corosync-cfgtool.8
736 ++++ b/man/corosync-cfgtool.8
737 +@@ -31,7 +31,7 @@
738 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
739 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
740 + .\" */
741 +-.TH "COROSYNC-CFGTOOL" "8" "2018-10-15" "" ""
742 ++.TH "COROSYNC-CFGTOOL" "8" "2019-02-13" "" ""
743 + .SH "NAME"
744 + corosync-cfgtool \- An administrative tool for corosync.
745 + .SH "SYNOPSIS"
746 +@@ -42,10 +42,10 @@ A tool for displaying and configuring active parameters within corosync.
747 + .SH "OPTIONS"
748 + .TP
749 + .B -i
750 +-Finds only information about the specified interface IP address with -s.
751 ++Finds only information about the specified interface IP address or link id with -s.
752 + .TP
753 + .B -s
754 +-Displays the status of the current links on this node for UDP/UDPU, while extended status
755 ++Displays the status of the current links on this node for UDP/UDPU, with extended status
756 + for KNET. If any interfaces are faulty, 1 is returned by the binary. If all interfaces are
757 + active 0 is returned to the shell.
758 + After each link, the nodes on that link are displayed in order with their status,
759 diff --git a/debian/patches/corosync.conf.5-fix-grammar.patch b/debian/patches/corosync.conf.5-fix-grammar.patch
760 index e28efba4..c0331169 100644
761 --- a/debian/patches/corosync.conf.5-fix-grammar.patch
762 +++ b/debian/patches/corosync.conf.5-fix-grammar.patch
763 @@ -1,13 +1,19 @@
764 From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
765 Date: Sat, 22 Dec 2018 18:56:01 +0100
766 Subject: corosync.conf.5: fix grammar
767 +MIME-Version: 1.0
768 +Content-Type: text/plain; charset="utf-8"
769 +Content-Transfer-Encoding: 8bit
770
771 +Signed-off-by: Ferenc Wágner <wferi@debian.org>
772 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
773 +(cherry picked from commit 059c22a1545371175d38d7e7171ec6c3db64a99e)
774 ---
775 man/corosync.conf.5 | 2 +-
776 1 file changed, 1 insertion(+), 1 deletion(-)
777
778 diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
779 -index 0e752bc..433a9b2 100644
780 +index 0b2ee03..a72650b 100644
781 --- a/man/corosync.conf.5
782 +++ b/man/corosync.conf.5
783 @@ -322,7 +322,7 @@ otherwise use first IPv4 address).
784 diff --git a/debian/patches/corosync.conf.5-typography-fixes.patch b/debian/patches/corosync.conf.5-typography-fixes.patch
785 index ebfb7f07..4e901a1e 100644
786 --- a/debian/patches/corosync.conf.5-typography-fixes.patch
787 +++ b/debian/patches/corosync.conf.5-typography-fixes.patch
788 @@ -1,13 +1,19 @@
789 From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
790 Date: Sat, 22 Dec 2018 18:58:27 +0100
791 Subject: corosync.conf.5: typography fixes
792 +MIME-Version: 1.0
793 +Content-Type: text/plain; charset="utf-8"
794 +Content-Transfer-Encoding: 8bit
795
796 +Signed-off-by: Ferenc Wágner <wferi@debian.org>
797 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
798 +(cherry picked from commit 4d0e764310b318a35da984cc125ef99010502172)
799 ---
800 man/corosync.conf.5 | 6 +++++-
801 1 file changed, 5 insertions(+), 1 deletion(-)
802
803 diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
804 -index 433a9b2..dd6f3ba 100644
805 +index a72650b..aa928bc 100644
806 --- a/man/corosync.conf.5
807 +++ b/man/corosync.conf.5
808 @@ -320,7 +320,11 @@ otherwise use first IPv6 address) and
809 diff --git a/debian/patches/cpg-Add-CPG_REASON_UNDEFINED.patch b/debian/patches/cpg-Add-CPG_REASON_UNDEFINED.patch
810 new file mode 100644
811 index 00000000..a69b53ac
812 --- /dev/null
813 +++ b/debian/patches/cpg-Add-CPG_REASON_UNDEFINED.patch
814 @@ -0,0 +1,152 @@
815 +From: Jan Friesse <jfriesse@redhat.com>
816 +Date: Tue, 16 Apr 2019 12:52:31 +0200
817 +Subject: cpg: Add CPG_REASON_UNDEFINED
818 +
819 +Previously the reason field for the member_list items
820 +in cpg_totem_confchg_fn was unset what may be little confusing.
821 +
822 +Solution is to add a special value CPG_REASON_UNDEFINED and use it for
823 +the member_list items.
824 +
825 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
826 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
827 +(cherry picked from commit 41f9e966bb1cfa70d0f6ec1ce46d9c845845b599)
828 +---
829 + include/corosync/cpg.h | 3 ++-
830 + man/cpg_initialize.3.in | 18 ++++++++++--------
831 + man/cpg_model_initialize.3.in | 18 ++++++++++--------
832 + exec/cpg.c | 3 ++-
833 + 4 files changed, 24 insertions(+), 18 deletions(-)
834 +
835 +diff --git a/include/corosync/cpg.h b/include/corosync/cpg.h
836 +index 5ebd478..600bbf7 100644
837 +--- a/include/corosync/cpg.h
838 ++++ b/include/corosync/cpg.h
839 +@@ -1,5 +1,5 @@
840 + /*
841 +- * Copyright (c) 2006-2011 Red Hat, Inc.
842 ++ * Copyright (c) 2006-2019 Red Hat, Inc.
843 + *
844 + * All rights reserved.
845 + *
846 +@@ -80,6 +80,7 @@ typedef enum {
847 + * @brief The cpg_reason_t enum
848 + */
849 + typedef enum {
850 ++ CPG_REASON_UNDEFINED = 0,
851 + CPG_REASON_JOIN = 1,
852 + CPG_REASON_LEAVE = 2,
853 + CPG_REASON_NODEDOWN = 3,
854 +diff --git a/man/cpg_initialize.3.in b/man/cpg_initialize.3.in
855 +index bdecc1e..38c7de5 100644
856 +--- a/man/cpg_initialize.3.in
857 ++++ b/man/cpg_initialize.3.in
858 +@@ -1,5 +1,5 @@
859 + .\"/*
860 +-.\" * Copyright (c) 2006-2009 Red Hat, Inc.
861 ++.\" * Copyright (c) 2006-2019 Red Hat, Inc.
862 + .\" *
863 + .\" * All rights reserved.
864 + .\" *
865 +@@ -31,7 +31,7 @@
866 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
867 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
868 + .\" */
869 +-.TH CPG_INITIALIZE 3 2004-08-31 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
870 ++.TH CPG_INITIALIZE 3 2019-04-16 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
871 + .SH NAME
872 + cpg_initialize \- Create a new connection to the CPG service
873 + .SH SYNOPSIS
874 +@@ -132,18 +132,20 @@ struct cpg_address {
875 + .IP
876 + .PP
877 + where nodeid is a 32 bit unique node identifier, pid is the process ID of the process that has joined/left the group
878 +-or sent the message, and reason is an integer code indicating why the node joined/left the group.
879 ++or sent the message, and reason is an integer code indicating why the node joined/left the group (this value is not
880 ++set for the member_list items).
881 + .PP
882 + .IP
883 + .RS
884 + .ne 18
885 + .nf
886 + .PP
887 +-CPG_REASON_JOIN - the process joined a group using cpg_join().
888 +-CPG_REASON_LEAVE - the process left a group using cpg_leave()
889 +-CPG_REASON_NODEDOWN - the process left a group because the node left the cluster.
890 +-CPG_REASON_NODEUP - the process joined a group because it was already a member of a group on a node that has just joined the cluster
891 +-CPG_REASON_PROCDOWN - the process left a group without calling cpg_leave()
892 ++CPG_REASON_JOIN - the process joined a group using cpg_join().
893 ++CPG_REASON_LEAVE - the process left a group using cpg_leave()
894 ++CPG_REASON_NODEDOWN - the process left a group because the node left the cluster.
895 ++CPG_REASON_NODEUP - the process joined a group because it was already a member of a group on a node that has just joined the cluster
896 ++CPG_REASON_PROCDOWN - the process left a group without calling cpg_leave()
897 ++CPG_REASON_UNDEFINED - a special value used for the member_list items
898 + .ta
899 + .fi
900 + .RE
901 +diff --git a/man/cpg_model_initialize.3.in b/man/cpg_model_initialize.3.in
902 +index e06325d..17ca16a 100644
903 +--- a/man/cpg_model_initialize.3.in
904 ++++ b/man/cpg_model_initialize.3.in
905 +@@ -1,5 +1,5 @@
906 + .\"/*
907 +-.\" * Copyright (c) 2010 Red Hat, Inc.
908 ++.\" * Copyright (c) 2010-2019 Red Hat, Inc.
909 + .\" *
910 + .\" * All rights reserved.
911 + .\" *
912 +@@ -32,7 +32,7 @@
913 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
914 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
915 + .\" */
916 +-.TH CPG_MODEL_INITIALIZE 3 2010-04-07 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
917 ++.TH CPG_MODEL_INITIALIZE 3 2019-04-16 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
918 + .SH NAME
919 + cpg_model_initialize \- Create a new connection to the CPG service
920 + .SH SYNOPSIS
921 +@@ -166,18 +166,20 @@ struct cpg_address {
922 + .IP
923 + .PP
924 + where nodeid is a 32 bit unique node identifier, pid is the process ID of the process that has joined/left the group
925 +-or sent the message, and reason is an integer code indicating why the node joined/left the group.
926 ++or sent the message, and reason is an integer code indicating why the node joined/left the group (this value is not
927 ++set for the member_list items).
928 + .PP
929 + .IP
930 + .RS
931 + .ne 18
932 + .nf
933 + .PP
934 +-CPG_REASON_JOIN - the process joined a group using cpg_join().
935 +-CPG_REASON_LEAVE - the process left a group using cpg_leave()
936 +-CPG_REASON_NODEDOWN - the process left a group because the node left the cluster.
937 +-CPG_REASON_NODEUP - the process joined a group because it was already a member of a group on a node that has just joined the cluster
938 +-CPG_REASON_PROCDOWN - the process left a group without calling cpg_leave()
939 ++CPG_REASON_JOIN - the process joined a group using cpg_join().
940 ++CPG_REASON_LEAVE - the process left a group using cpg_leave()
941 ++CPG_REASON_NODEDOWN - the process left a group because the node left the cluster.
942 ++CPG_REASON_NODEUP - the process joined a group because it was already a member of a group on a node that has just joined the cluster
943 ++CPG_REASON_PROCDOWN - the process left a group without calling cpg_leave()
944 ++CPG_REASON_UNDEFINED - a special value used for the member_list items
945 + .ta
946 + .fi
947 + .RE
948 +diff --git a/exec/cpg.c b/exec/cpg.c
949 +index b7ac579..e39ca34 100644
950 +--- a/exec/cpg.c
951 ++++ b/exec/cpg.c
952 +@@ -1,5 +1,5 @@
953 + /*
954 +- * Copyright (c) 2006-2015 Red Hat, Inc.
955 ++ * Copyright (c) 2006-2019 Red Hat, Inc.
956 + *
957 + * All rights reserved.
958 + *
959 +@@ -712,6 +712,7 @@ static int notify_lib_joinlist(
960 + if (!founded) {
961 + retgi->nodeid = pi->nodeid;
962 + retgi->pid = pi->pid;
963 ++ retgi->reason = CPG_REASON_UNDEFINED;
964 + retgi++;
965 + }
966 + }
967 diff --git a/debian/patches/crypto-re-introduce-secauth-parameter.patch b/debian/patches/crypto-re-introduce-secauth-parameter.patch
968 new file mode 100644
969 index 00000000..84e009e2
970 --- /dev/null
971 +++ b/debian/patches/crypto-re-introduce-secauth-parameter.patch
972 @@ -0,0 +1,62 @@
973 +From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
974 +Date: Wed, 10 Apr 2019 09:43:33 +0200
975 +Subject: crypto: re-introduce secauth parameter
976 +MIME-Version: 1.0
977 +Content-Type: text/plain; charset="utf-8"
978 +Content-Transfer-Encoding: 8bit
979 +
980 +with the following semantics:
981 +- default off
982 +- implies crypto_hash SHA256 and crypto_cipher AES256
983 +- crypto_* have higher precedence
984 +- only applicable for knet, like crypto_*
985 +
986 +this should make upgrading from Corosync 2.x less painful for users that
987 +have an explicit secauth=on in their configuration.
988 +
989 +Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
990 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
991 +(cherry picked from commit b97ca8e9f026aaaf2fe9cf697d89803004587f60)
992 +---
993 + exec/totemconfig.c | 8 ++++++++
994 + man/corosync.conf.5 | 8 ++++++++
995 + 2 files changed, 16 insertions(+)
996 +
997 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
998 +index 4f69fd5..1954f76 100644
999 +--- a/exec/totemconfig.c
1000 ++++ b/exec/totemconfig.c
1001 +@@ -450,6 +450,14 @@ static int totem_get_crypto(struct totem_config *totem_config, const char **erro
1002 + tmp_model = "nss";
1003 + }
1004 +
1005 ++ if (icmap_get_string("totem.secauth", &str) == CS_OK) {
1006 ++ if (strcmp(str, "on") == 0) {
1007 ++ tmp_cipher = "aes256";
1008 ++ tmp_hash = "sha256";
1009 ++ }
1010 ++ free(str);
1011 ++ }
1012 ++
1013 + if (icmap_get_string("totem.crypto_cipher", &str) == CS_OK) {
1014 + if (strcmp(str, "none") == 0) {
1015 + tmp_cipher = "none";
1016 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1017 +index 887a52b..e2fd9ed 100644
1018 +--- a/man/corosync.conf.5
1019 ++++ b/man/corosync.conf.5
1020 +@@ -227,6 +227,14 @@ transmission is only supported for the knet transport.
1021 +
1022 + The default is none.
1023 +
1024 ++.TP
1025 ++secauth
1026 ++This implies crypto_cipher=aes256 and crypto_hash=sha256, unless those options
1027 ++are explicitly set. Encrypted transmission is only supported for the knet
1028 ++transport.
1029 ++
1030 ++The default is off.
1031 ++
1032 + .TP
1033 + keyfile
1034 + This specifies the fully qualified path to the shared key used to
1035 diff --git a/debian/patches/doc-Update-INSTALL-file.patch b/debian/patches/doc-Update-INSTALL-file.patch
1036 new file mode 100644
1037 index 00000000..0404de43
1038 --- /dev/null
1039 +++ b/debian/patches/doc-Update-INSTALL-file.patch
1040 @@ -0,0 +1,124 @@
1041 +From: Jan Friesse <jfriesse@redhat.com>
1042 +Date: Wed, 16 Jan 2019 14:39:42 +0100
1043 +Subject: doc: Update INSTALL file
1044 +
1045 +- Add LibQB and Knet links
1046 +- Remove old (pre udpu) config file example
1047 +- Change corosync.conf man page to contain useful information about
1048 +token timeout
1049 +
1050 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1051 +Reviewed-by: Fabio M. Di Nitto <fdinitto@redhat.com>
1052 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1053 +(cherry picked from commit ce29717491160dec3104245af1fa98910e1e6951)
1054 +---
1055 + INSTALL | 58 ++++++++---------------------------------------------
1056 + man/corosync.conf.5 | 5 ++++-
1057 + 2 files changed, 12 insertions(+), 51 deletions(-)
1058 +
1059 +diff --git a/INSTALL b/INSTALL
1060 +index 85655ca..bfe684d 100644
1061 +--- a/INSTALL
1062 ++++ b/INSTALL
1063 +@@ -43,7 +43,8 @@ balance:~/corosync# make install
1064 + * A notice about dependencies *
1065 + -------------------------------
1066 + We have strived very hard to avoid dependencies as much as possible, but there
1067 +-are two required libraries: LibQB and KNET.
1068 ++are two required libraries: LibQB (https://github.com/ClusterLabs/libqb)
1069 ++and KNET (https://kronosnet.org/).
1070 +
1071 + Optional dependencies are support for DBUS, SNMP and libstatgrab.
1072 +
1073 +@@ -102,54 +103,11 @@ And you should get traps
1074 + ------------------------
1075 + * Configuring Corosync *
1076 + ------------------------
1077 +-The corosync executive will automatically determine cluster membership by
1078 +-communicating on a specified multicast address and port.
1079 +-
1080 +-The directory conf contains the file corosync.conf.example
1081 +-
1082 +-# Please read the corosync.conf.5 manual page
1083 +-totem {
1084 +- version: 2
1085 +- secauth: off
1086 +- threads: 0
1087 +- interface {
1088 +- ringnumber: 0
1089 +- bindnetaddr: 192.168.1.1
1090 +- mcastaddr: 226.94.1.1
1091 +- mcastport: 5405
1092 +- }
1093 +-}
1094 +-
1095 +-logging {
1096 +- fileline: off
1097 +- to_stderr: yes
1098 +- to_file: yes
1099 +- to_syslog: yes
1100 +- logfile: /tmp/corosync.log
1101 +- debug: off
1102 +- timestamp: on
1103 +-}
1104 +-
1105 +-The totem section contains three values. All three values must be set
1106 +-or the corosync executive wll exit with an error.
1107 +-
1108 +-bindnetaddr specifies the address which the corosync Executive should bind to.
1109 +-This address should always end in zero. If the local interface taffic
1110 +-should routed over is 192.168.5.92, set bindnetaddr to 192.168.5.0.
1111 +-
1112 +-mcastaddr is a multicast address. The default should work but you may have
1113 +-a different network configuration. Avoid 224.x.x.x because this is a "config"
1114 +-multicast address.
1115 +-
1116 +-mcastport specifies the UDP port number. It is possible to use the same
1117 +-multicast address on a network with the corosync services configured for
1118 +-different UDP ports.
1119 +-
1120 +-The timeout section contains seven values. This section is not normally used,
1121 +-but rather used to override the program defaults for the purposes of fine
1122 +-tuning for a given networking/processor combination or for debugging purposes.
1123 +-Be careful to use the same timeout values on each of the nodes in the cluster
1124 +-or unpredictable results may occur.
1125 ++The configuration directory (usually /etc/corosync) contains an example
1126 ++configuration file (corosync.conf.example). Please copy it as corosync.conf
1127 ++and edit it as needed. At the very minimum, the nodelist section will have to be changed
1128 ++to list all cluster nodes. For more information about the configuration file
1129 ++please read the corosync.conf.5 manual page.
1130 +
1131 + Generate a private key
1132 + ----------------------
1133 +@@ -161,7 +119,7 @@ First generate the key on one of the nodes:
1134 +
1135 + balance# corosync-keygen
1136 + Corosync Authentication key generator.
1137 +-Gathering 1024 bits for key from /dev/random.
1138 ++Gathering 8192 bits for key from /dev/random.
1139 + Writing corosync key to /etc/corosync/authkey.
1140 +
1141 + After this is complete, a private key will be in the file /etc/corosync/authkey.
1142 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1143 +index 0e752bc..0b2ee03 100644
1144 +--- a/man/corosync.conf.5
1145 ++++ b/man/corosync.conf.5
1146 +@@ -32,7 +32,7 @@
1147 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1148 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
1149 + .\" */
1150 +-.TH COROSYNC_CONF 5 2019-01-10 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
1151 ++.TH COROSYNC_CONF 5 2019-01-16 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
1152 + .SH NAME
1153 + corosync.conf - corosync executive configuration file
1154 +
1155 +@@ -347,6 +347,9 @@ For real token timeout used by totem it's possible to read cmap value of
1156 + .B runtime.config.totem.token
1157 + key.
1158 +
1159 ++Be careful to use the same timeout values on each of the nodes in the cluster
1160 ++or unpredictable results may occur.
1161 ++
1162 + The default is 1000 milliseconds.
1163 +
1164 + .TP
1165 diff --git a/debian/patches/keygen-Reflect-change-in-knet.patch b/debian/patches/keygen-Reflect-change-in-knet.patch
1166 new file mode 100644
1167 index 00000000..068f481f
1168 --- /dev/null
1169 +++ b/debian/patches/keygen-Reflect-change-in-knet.patch
1170 @@ -0,0 +1,100 @@
1171 +From: Jan Friesse <jfriesse@redhat.com>
1172 +Date: Tue, 9 Apr 2019 17:09:34 +0200
1173 +Subject: keygen: Reflect change in knet
1174 +
1175 +Knet commit 1cb36f0cffd4559971826ca4774a88c5b05882fb reduced minimal
1176 +key length to 1024-bit. Keygen should keep compatibility with already
1177 +released 3.0.[0-1] so default key length should be 2048 bits. It's
1178 +possible to use -s argument to generate shorter key - keygen respects
1179 +minimum/maximum as defined by knet.
1180 +
1181 +Also fix man page to reflect this change.
1182 +
1183 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1184 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1185 +(cherry picked from commit c260bce45b1f5b4a82c74513c4b3302d32daf179)
1186 +---
1187 + tools/corosync-keygen.c | 4 ++--
1188 + man/corosync-keygen.8 | 21 +++++++++------------
1189 + 2 files changed, 11 insertions(+), 14 deletions(-)
1190 +
1191 +diff --git a/tools/corosync-keygen.c b/tools/corosync-keygen.c
1192 +index 40e4d6e..243661a 100644
1193 +--- a/tools/corosync-keygen.c
1194 ++++ b/tools/corosync-keygen.c
1195 +@@ -1,6 +1,6 @@
1196 + /*
1197 + * Copyright (c) 2004 MontaVista Software, Inc.
1198 +- * Copyright (c) 2005-2017 Red Hat, Inc.
1199 ++ * Copyright (c) 2005-2019 Red Hat, Inc.
1200 + *
1201 + * All rights reserved.
1202 + *
1203 +@@ -52,7 +52,7 @@
1204 +
1205 + #define DEFAULT_KEYFILE COROSYSCONFDIR "/authkey"
1206 +
1207 +-#define DEFAULT_KEYFILE_LEN TOTEM_PRIVATE_KEY_LEN_MIN
1208 ++#define DEFAULT_KEYFILE_LEN 256
1209 +
1210 + #define DEFAULT_RANDOM_DEV "/dev/urandom"
1211 +
1212 +diff --git a/man/corosync-keygen.8 b/man/corosync-keygen.8
1213 +index 0839621..8767ddc 100644
1214 +--- a/man/corosync-keygen.8
1215 ++++ b/man/corosync-keygen.8
1216 +@@ -1,5 +1,5 @@
1217 + .\"/*
1218 +-.\" * Copyright (C) 2010-2017 Red Hat, Inc.
1219 ++.\" * Copyright (C) 2010-2019 Red Hat, Inc.
1220 + .\" *
1221 + .\" * All rights reserved.
1222 + .\" *
1223 +@@ -31,7 +31,7 @@
1224 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1225 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
1226 + .\" */
1227 +-.TH COROSYNC-KEYGEN 8 2017-07-03
1228 ++.TH COROSYNC-KEYGEN 8 2019-04-09
1229 + .SH NAME
1230 + corosync-keygen \- Generate an authentication key for Corosync.
1231 + .SH SYNOPSIS
1232 +@@ -69,7 +69,7 @@ Random number source file. Default is /dev/urandom. As an example /dev/random ma
1233 + used when really superb randomness is needed.
1234 + .TP
1235 + .B -s size
1236 +-Size of the generated key in bytes. Default is 1024 bytes. Allowed range is <1024, 4096>.
1237 ++Size of the generated key in bytes. Default is 256 bytes. Allowed range is <128, 4096>.
1238 + .TP
1239 + .TP
1240 + .B -l
1241 +@@ -84,7 +84,7 @@ Generate the key.
1242 + .nf
1243 + # corosync-keygen
1244 + Corosync Cluster Engine Authentication key generator.
1245 +-Gathering 8192 bits for key from /dev/urandom.
1246 ++Gathering 2048 bits for key from /dev/urandom.
1247 + Writing corosync key to /etc/corosync/authkey
1248 + .fi
1249 +
1250 +@@ -101,15 +101,12 @@ Writing corosync key to /tmp/authkey.
1251 + Generate superb key using /dev/random
1252 + .nf
1253 + # corosync-keygen -r /dev/random
1254 +-Corosync Cluster Engine Authentication key generator.
1255 +-Gathering 8192 bits for key from /dev/random.
1256 ++Gathering 2048 bits for key from /dev/random.
1257 + Press keys on your keyboard to generate entropy.
1258 +-Press keys on your keyboard to generate entropy (7928 bits still needed).
1259 +-Press keys on your keyboard to generate entropy (7880 bits still needed).
1260 +- ...
1261 +-Press keys on your keyboard to generate entropy (104 bits still needed).
1262 +-Press keys on your keyboard to generate entropy (56 bits still needed).
1263 +-Press keys on your keyboard to generate entropy (8 bits still needed).
1264 ++Press keys on your keyboard to generate entropy (1128 bits still needed).
1265 ++Press keys on your keyboard to generate entropy (504 bits still needed).
1266 ++Press keys on your keyboard to generate entropy (128 bits still needed).
1267 ++Press keys on your keyboard to generate entropy (32 bits still needed).
1268 + Writing corosync key to /etc/corosync/authkey.
1269 + .fi
1270 +
1271 diff --git a/debian/patches/knet-Fix-a-couple-of-errors-when-adding-a-new-link.patch b/debian/patches/knet-Fix-a-couple-of-errors-when-adding-a-new-link.patch
1272 new file mode 100644
1273 index 00000000..1b3fd495
1274 --- /dev/null
1275 +++ b/debian/patches/knet-Fix-a-couple-of-errors-when-adding-a-new-link.patch
1276 @@ -0,0 +1,82 @@
1277 +From: Christine Caulfield <ccaulfie@redhat.com>
1278 +Date: Thu, 2 May 2019 14:22:47 +0100
1279 +Subject: knet: Fix a couple of errors when adding a new link
1280 +
1281 +When adding a new link for the first time you will often see:
1282 +1) knet_link_set_ping_timers for nodeid 1, link 1 failed: Invalid
1283 +argument (22)
1284 +2) New config has different knet transport for link 1. Internal value
1285 +was NOT changed. To reconfigure an interface it must be deleted and
1286 +recreated. A working interface needs to be available to corosync at all
1287 +times
1288 +
1289 +1) is caused by setting the ping timers twice, once in
1290 +totemknet_member_add() and once in totemknet_refresh_config().
1291 +The first time we don't know the value
1292 +so it's zero and thus display an error. For this we simply check
1293 +for the zero and skip the knet API call. It's not ideal, but
1294 +totemconfig needs a lot of reconfiguring itself before we can
1295 +make this more sane.
1296 +
1297 +2) was caused by simply comparing an unconfigured link with
1298 +a configured one, so OF COURSE, they are going to be different!
1299 +
1300 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
1301 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
1302 +(cherry picked from commit 01ce5a96ef9dea2d517d84abec7aecc6af99e7aa)
1303 +---
1304 + exec/totemconfig.c | 3 ++-
1305 + exec/totemknet.c | 26 +++++++++++++++-----------
1306 + 2 files changed, 17 insertions(+), 12 deletions(-)
1307 +
1308 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
1309 +index 3b4dbae..091eedc 100644
1310 +--- a/exec/totemconfig.c
1311 ++++ b/exec/totemconfig.c
1312 +@@ -1152,7 +1152,8 @@ static void check_things_have_not_changed(struct totem_config *totem_config)
1313 + int changed = 0;
1314 +
1315 + for (i = 0; i<INTERFACE_MAX; i++) {
1316 +- if (totem_config->interfaces[i].configured) {
1317 ++ if (totem_config->interfaces[i].configured &&
1318 ++ totem_config->orig_interfaces[i].configured) {
1319 + if (totem_config->interfaces[i].knet_transport !=
1320 + totem_config->orig_interfaces[i].knet_transport) {
1321 + log_printf(LOGSYS_LEVEL_ERROR,
1322 +diff --git a/exec/totemknet.c b/exec/totemknet.c
1323 +index 77cb65a..2c3f47f 100644
1324 +--- a/exec/totemknet.c
1325 ++++ b/exec/totemknet.c
1326 +@@ -1306,17 +1306,21 @@ int totemknet_member_add (
1327 + KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_link_set_priority for nodeid %d, link %d failed", member->nodeid, link_no);
1328 + }
1329 +
1330 +- err = knet_link_set_ping_timers(instance->knet_handle, member->nodeid, link_no,
1331 +- instance->totem_config->interfaces[link_no].knet_ping_interval,
1332 +- instance->totem_config->interfaces[link_no].knet_ping_timeout,
1333 +- instance->totem_config->interfaces[link_no].knet_ping_precision);
1334 +- if (err) {
1335 +- KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_link_set_ping_timers for nodeid %d, link %d failed", member->nodeid, link_no);
1336 +- }
1337 +- err = knet_link_set_pong_count(instance->knet_handle, member->nodeid, link_no,
1338 +- instance->totem_config->interfaces[link_no].knet_pong_count);
1339 +- if (err) {
1340 +- KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_link_set_pong_count for nodeid %d, link %d failed", member->nodeid, link_no);
1341 ++ /* ping timeouts maybe 0 here for a newly added interface so we leave this till later, it will
1342 ++ get done in totemknet_refresh_config */
1343 ++ if (instance->totem_config->interfaces[link_no].knet_ping_interval != 0) {
1344 ++ err = knet_link_set_ping_timers(instance->knet_handle, member->nodeid, link_no,
1345 ++ instance->totem_config->interfaces[link_no].knet_ping_interval,
1346 ++ instance->totem_config->interfaces[link_no].knet_ping_timeout,
1347 ++ instance->totem_config->interfaces[link_no].knet_ping_precision);
1348 ++ if (err) {
1349 ++ KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_link_set_ping_timers for nodeid %d, link %d failed", member->nodeid, link_no);
1350 ++ }
1351 ++ err = knet_link_set_pong_count(instance->knet_handle, member->nodeid, link_no,
1352 ++ instance->totem_config->interfaces[link_no].knet_pong_count);
1353 ++ if (err) {
1354 ++ KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_link_set_pong_count for nodeid %d, link %d failed", member->nodeid, link_no);
1355 ++ }
1356 + }
1357 +
1358 + err = knet_link_set_enable(instance->knet_handle, member->nodeid, link_no, 1);
1359 diff --git a/debian/patches/knet-Fix-initialising-of-knet-access-lists.patch b/debian/patches/knet-Fix-initialising-of-knet-access-lists.patch
1360 new file mode 100644
1361 index 00000000..b50865ec
1362 --- /dev/null
1363 +++ b/debian/patches/knet-Fix-initialising-of-knet-access-lists.patch
1364 @@ -0,0 +1,70 @@
1365 +From: Christine Caulfield <ccaulfie@redhat.com>
1366 +Date: Tue, 19 Mar 2019 10:47:58 +0000
1367 +Subject: knet: Fix initialising of knet access lists.
1368 +
1369 +It needs to be done at both reload and initialize time.
1370 +Also disable access lists if the config key is removed.
1371 +
1372 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
1373 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
1374 +(cherry picked from commit 482df5d67b6b9fe021a1252537c4c499a66de0f8)
1375 +---
1376 + exec/totemknet.c | 31 ++++++++++++++++++++++---------
1377 + 1 file changed, 22 insertions(+), 9 deletions(-)
1378 +
1379 +diff --git a/exec/totemknet.c b/exec/totemknet.c
1380 +index 7984b55..884eefe 100644
1381 +--- a/exec/totemknet.c
1382 ++++ b/exec/totemknet.c
1383 +@@ -737,6 +737,24 @@ static void timer_function_netif_check_timeout (
1384 + }
1385 + }
1386 +
1387 ++static void knet_set_access_list_config(struct totemknet_instance *instance)
1388 ++{
1389 ++#ifdef HAVE_KNET_ACCESS_LIST
1390 ++ uint32_t value = 0; /* disable by default */
1391 ++ cs_error_t err;
1392 ++
1393 ++ if (icmap_get_uint32("totem.knet_enable_access_lists", &value) == CS_OK) {
1394 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "knet_enable access list: %d", value);
1395 ++ }
1396 ++
1397 ++ err = knet_handle_enable_access_lists(instance->knet_handle, value);
1398 ++ if (err) {
1399 ++ KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_access_lists failed");
1400 ++ }
1401 ++#endif
1402 ++}
1403 ++
1404 ++
1405 + /* NOTE: this relies on the fact that totem_reload_notify() is called first */
1406 + static void totemknet_refresh_config(
1407 + int32_t event,
1408 +@@ -764,15 +782,7 @@ static void totemknet_refresh_config(
1409 + return;
1410 + }
1411 +
1412 +-#ifdef HAVE_KNET_ACCESS_LIST
1413 +- if (icmap_get_uint32("totem.knet_enable_access_lists", &value) == CS_OK) {
1414 +- knet_log_printf (LOGSYS_LEVEL_DEBUG, "knet_enable access list: %d", value);
1415 +- err = knet_handle_enable_access_lists(instance->knet_handle, value);
1416 +- if (err) {
1417 +- KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_access_lists failed");
1418 +- }
1419 +- }
1420 +-#endif
1421 ++ knet_set_access_list_config(instance);
1422 +
1423 + if (icmap_get_uint32("totem.knet_pmtud_interval", &value) == CS_OK) {
1424 +
1425 +@@ -944,6 +954,9 @@ int totemknet_initialize (
1426 + KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_CRIT, "knet_handle_new failed");
1427 + goto exit_error;
1428 + }
1429 ++
1430 ++ knet_set_access_list_config(instance);
1431 ++
1432 + res = knet_handle_pmtud_setfreq(instance->knet_handle, instance->totem_config->knet_pmtud_interval);
1433 + if (res) {
1434 + KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_pmtud_setfreq failed");
1435 diff --git a/debian/patches/knet-Use-block_unlisted_ips.patch b/debian/patches/knet-Use-block_unlisted_ips.patch
1436 new file mode 100644
1437 index 00000000..c3ff3092
1438 --- /dev/null
1439 +++ b/debian/patches/knet-Use-block_unlisted_ips.patch
1440 @@ -0,0 +1,67 @@
1441 +From: Jan Friesse <jfriesse@redhat.com>
1442 +Date: Fri, 24 May 2019 09:33:13 +0200
1443 +Subject: knet: Use block_unlisted_ips
1444 +
1445 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1446 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1447 +(cherry picked from commit 9bba026bcd99bfc27c24e749262210513bd43ccc)
1448 +---
1449 + exec/coroparse.c | 3 ---
1450 + exec/totemknet.c | 7 +++----
1451 + man/corosync.conf.5 | 7 +------
1452 + 3 files changed, 4 insertions(+), 13 deletions(-)
1453 +
1454 +diff --git a/exec/coroparse.c b/exec/coroparse.c
1455 +index 87bbceb..0acb4c2 100644
1456 +--- a/exec/coroparse.c
1457 ++++ b/exec/coroparse.c
1458 +@@ -708,9 +708,6 @@ static int main_config_parser_cb(const char *path,
1459 + (strcmp(path, "totem.miss_count_const") == 0) ||
1460 + (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
1461 + (strcmp(path, "totem.knet_compression_threshold") == 0) ||
1462 +-#ifdef HAVE_KNET_ACCESS_LIST
1463 +- (strcmp(path, "totem.knet_enable_access_lists") == 0) ||
1464 +-#endif
1465 + (strcmp(path, "totem.netmtu") == 0)) {
1466 + val_type = ICMAP_VALUETYPE_UINT32;
1467 + if (safe_atoq(value, &val, val_type) != 0) {
1468 +diff --git a/exec/totemknet.c b/exec/totemknet.c
1469 +index 884eefe..2af69b3 100644
1470 +--- a/exec/totemknet.c
1471 ++++ b/exec/totemknet.c
1472 +@@ -740,12 +740,11 @@ static void timer_function_netif_check_timeout (
1473 + static void knet_set_access_list_config(struct totemknet_instance *instance)
1474 + {
1475 + #ifdef HAVE_KNET_ACCESS_LIST
1476 +- uint32_t value = 0; /* disable by default */
1477 ++ uint32_t value;
1478 + cs_error_t err;
1479 +
1480 +- if (icmap_get_uint32("totem.knet_enable_access_lists", &value) == CS_OK) {
1481 +- knet_log_printf (LOGSYS_LEVEL_DEBUG, "knet_enable access list: %d", value);
1482 +- }
1483 ++ value = instance->totem_config->block_unlisted_ips;
1484 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "knet_enable access list: %d", value);
1485 +
1486 + err = knet_handle_enable_access_lists(instance->knet_handle, value);
1487 + if (err) {
1488 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1489 +index 953c830..0e1ef88 100644
1490 +--- a/man/corosync.conf.5
1491 ++++ b/man/corosync.conf.5
1492 +@@ -566,14 +566,9 @@ knet_pmtud_interval
1493 + How often the knet PMTUd runs to look for network MTU changes.
1494 + Value in seconds, default: 30
1495 +
1496 +-.TP
1497 +-knet_enable_access_lists
1498 +-Allow knet to drop packets from IP addresses that are not known to corosync.
1499 +-Value is 0 (off) and 1 (on). Default: 0.
1500 +-
1501 + .TP
1502 + block_unlisted_ips
1503 +-Allow UDPU to drop packets from IP addresses that are not known
1504 ++Allow UDPU and KNET to drop packets from IP addresses that are not known
1505 + (nodes which don't exist in the nodelist) to corosync.
1506 + Value is yes or no.
1507 +
1508 diff --git a/debian/patches/knet-allow-corosync-to-use-knet-access-lists.patch b/debian/patches/knet-allow-corosync-to-use-knet-access-lists.patch
1509 new file mode 100644
1510 index 00000000..f5cb424d
1511 --- /dev/null
1512 +++ b/debian/patches/knet-allow-corosync-to-use-knet-access-lists.patch
1513 @@ -0,0 +1,93 @@
1514 +From: "Fabio M. Di Nitto" <fdinitto@redhat.com>
1515 +Date: Sun, 10 Mar 2019 08:23:38 +0100
1516 +Subject: knet: allow corosync to use knet access lists
1517 +MIME-Version: 1.0
1518 +Content-Type: text/plain; charset="utf-8"
1519 +Content-Transfer-Encoding: 8bit
1520 +
1521 +currently knet acl are only available on master
1522 +but they might be backported
1523 +to stable1 as they don´t break onwire protocol.
1524 +
1525 +Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
1526 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1527 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
1528 +(cherry picked from commit 5c9a2b1c0676aa7581b31b5cfb6ae2d969abd1b2)
1529 +---
1530 + configure.ac | 9 +++++++++
1531 + exec/coroparse.c | 3 +++
1532 + exec/totemknet.c | 10 ++++++++++
1533 + man/corosync.conf.5 | 5 +++++
1534 + 4 files changed, 27 insertions(+)
1535 +
1536 +diff --git a/configure.ac b/configure.ac
1537 +index a27ba95..82479f9 100644
1538 +--- a/configure.ac
1539 ++++ b/configure.ac
1540 +@@ -180,6 +180,15 @@ AC_CHECK_LIB([z], [crc32],
1541 + AM_CONDITIONAL([HAVE_CRC32], true),
1542 + AM_CONDITIONAL([HAVE_CRC32], false))
1543 +
1544 ++# this hack is necessary to check for symbols on out of tree builds
1545 ++# but it is as horrible as it gets and in theory users should be
1546 ++# invoking ./configure with proper LIBRARY_PATH set.
1547 ++OLDLIBS="$LIBS"
1548 ++LIBS="$knet_LIBS $LIBS"
1549 ++AC_CHECK_LIB([knet],[knet_handle_enable_access_lists],
1550 ++ [AC_DEFINE_UNQUOTED([HAVE_KNET_ACCESS_LIST], 1, [have knet access list])])
1551 ++LIBS="$OLDLIBS"
1552 ++
1553 + # Checks for library functions.
1554 + AC_FUNC_ALLOCA
1555 + AC_FUNC_CLOSEDIR_VOID
1556 +diff --git a/exec/coroparse.c b/exec/coroparse.c
1557 +index 0acb4c2..87bbceb 100644
1558 +--- a/exec/coroparse.c
1559 ++++ b/exec/coroparse.c
1560 +@@ -708,6 +708,9 @@ static int main_config_parser_cb(const char *path,
1561 + (strcmp(path, "totem.miss_count_const") == 0) ||
1562 + (strcmp(path, "totem.knet_pmtud_interval") == 0) ||
1563 + (strcmp(path, "totem.knet_compression_threshold") == 0) ||
1564 ++#ifdef HAVE_KNET_ACCESS_LIST
1565 ++ (strcmp(path, "totem.knet_enable_access_lists") == 0) ||
1566 ++#endif
1567 + (strcmp(path, "totem.netmtu") == 0)) {
1568 + val_type = ICMAP_VALUETYPE_UINT32;
1569 + if (safe_atoq(value, &val, val_type) != 0) {
1570 +diff --git a/exec/totemknet.c b/exec/totemknet.c
1571 +index 2c3f47f..7984b55 100644
1572 +--- a/exec/totemknet.c
1573 ++++ b/exec/totemknet.c
1574 +@@ -764,6 +764,16 @@ static void totemknet_refresh_config(
1575 + return;
1576 + }
1577 +
1578 ++#ifdef HAVE_KNET_ACCESS_LIST
1579 ++ if (icmap_get_uint32("totem.knet_enable_access_lists", &value) == CS_OK) {
1580 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "knet_enable access list: %d", value);
1581 ++ err = knet_handle_enable_access_lists(instance->knet_handle, value);
1582 ++ if (err) {
1583 ++ KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_enable_access_lists failed");
1584 ++ }
1585 ++ }
1586 ++#endif
1587 ++
1588 + if (icmap_get_uint32("totem.knet_pmtud_interval", &value) == CS_OK) {
1589 +
1590 + instance->totem_config->knet_pmtud_interval = value;
1591 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1592 +index 5fef28a..674179d 100644
1593 +--- a/man/corosync.conf.5
1594 ++++ b/man/corosync.conf.5
1595 +@@ -566,6 +566,11 @@ knet_pmtud_interval
1596 + How often the knet PMTUd runs to look for network MTU changes.
1597 + Value in seconds, default: 30
1598 +
1599 ++.TP
1600 ++knet_enable_access_lists
1601 ++Allow knet to drop packets from IP addresses that are not known to corosync.
1602 ++Value is 0 (off) and 1 (on). Default: 0.
1603 ++
1604 + .PP
1605 + Within the
1606 + .B logging
1607 diff --git a/debian/patches/man-Add-vqsim-man-page-into-distributed-tarball.patch b/debian/patches/man-Add-vqsim-man-page-into-distributed-tarball.patch
1608 new file mode 100644
1609 index 00000000..c13e4f97
1610 --- /dev/null
1611 +++ b/debian/patches/man-Add-vqsim-man-page-into-distributed-tarball.patch
1612 @@ -0,0 +1,40 @@
1613 +From: Jan Friesse <jfriesse@redhat.com>
1614 +Date: Mon, 10 Jun 2019 08:04:50 +0200
1615 +Subject: man: Add vqsim man page into distributed tarball
1616 +
1617 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1618 +(cherry picked from commit 8ced7e545dde485ac57886e8713330ec82eaa35c)
1619 +---
1620 + man/Makefile.am | 5 ++++-
1621 + 1 file changed, 4 insertions(+), 1 deletion(-)
1622 +
1623 +diff --git a/man/Makefile.am b/man/Makefile.am
1624 +index 8e4eda3..2ef5dcd 100644
1625 +--- a/man/Makefile.am
1626 ++++ b/man/Makefile.am
1627 +@@ -37,6 +37,8 @@ MAINTAINERCLEANFILES = Makefile.in
1628 + xml_man = corosync-xmlproc.8 \
1629 + corosync.xml.5
1630 +
1631 ++corosync_vqsim_man = corosync-vqsim.8
1632 ++
1633 + INDEX_HTML = index.html
1634 +
1635 + autogen_man = cpg_context_get.3 \
1636 +@@ -116,6 +118,7 @@ autogen_common = ipc_common.sh.errors
1637 +
1638 + EXTRA_DIST = $(INDEX_HTML) \
1639 + $(xml_man) \
1640 ++ $(corosync_vqsim_man) \
1641 + $(autogen_man:%=%.in) \
1642 + $(autogen_common)
1643 +
1644 +@@ -140,7 +143,7 @@ dist_man_MANS = corosync.conf.5 \
1645 + cmap_keys.8
1646 +
1647 + if BUILD_VQSIM
1648 +-dist_man_MANS += corosync-vqsim.8
1649 ++dist_man_MANS += $(corosync_vqsim_man)
1650 + endif
1651 +
1652 + if INSTALL_XMLCONF
1653 diff --git a/debian/patches/man-Enahnce-block_unlisted_ips-description.patch b/debian/patches/man-Enahnce-block_unlisted_ips-description.patch
1654 new file mode 100644
1655 index 00000000..effd8231
1656 --- /dev/null
1657 +++ b/debian/patches/man-Enahnce-block_unlisted_ips-description.patch
1658 @@ -0,0 +1,33 @@
1659 +From: Jan Friesse <jfriesse@redhat.com>
1660 +Date: Fri, 31 May 2019 09:34:33 +0200
1661 +Subject: man: Enahnce block_unlisted_ips description
1662 +
1663 +Thanks Christine Caulfield <ccaulfie@redhat.com> for
1664 +Englishify and refining the description.
1665 +
1666 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1667 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1668 +(cherry picked from commit d775f1425d6ebbfa25c7ba43c0fc69902507a8d6)
1669 +---
1670 + man/corosync.conf.5 | 8 ++++++++
1671 + 1 file changed, 8 insertions(+)
1672 +
1673 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1674 +index ba1397f..3b77733 100644
1675 +--- a/man/corosync.conf.5
1676 ++++ b/man/corosync.conf.5
1677 +@@ -572,6 +572,14 @@ Allow UDPU and KNET to drop packets from IP addresses that are not known
1678 + (nodes which don't exist in the nodelist) to corosync.
1679 + Value is yes or no.
1680 +
1681 ++This feature is mainly to protect against the joining of nodes
1682 ++with outdated configurations after a cluster split.
1683 ++Another use case is to allow the atomic merge of two independent clusters.
1684 ++
1685 ++Changing the default value is not recommended, the overhead is tiny and
1686 ++an existing cluster may fail if corosync is started on an unlisted node
1687 ++with an old configuration.
1688 ++
1689 + The default value is yes.
1690 +
1691 + .PP
1692 diff --git a/debian/patches/man-Enhance-corosync.conf-mp-a-bit.patch b/debian/patches/man-Enhance-corosync.conf-mp-a-bit.patch
1693 new file mode 100644
1694 index 00000000..33098378
1695 --- /dev/null
1696 +++ b/debian/patches/man-Enhance-corosync.conf-mp-a-bit.patch
1697 @@ -0,0 +1,37 @@
1698 +From: Jan Friesse <jfriesse@redhat.com>
1699 +Date: Tue, 28 May 2019 10:08:37 +0200
1700 +Subject: man: Enhance corosync.conf mp a bit
1701 +
1702 +Fix issues found by Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>
1703 +
1704 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
1705 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
1706 +(cherry picked from commit 183d5da5eb3d74043464dbc5d6e92f8b38a2e9cb)
1707 +---
1708 + man/corosync.conf.5 | 6 +++---
1709 + 1 file changed, 3 insertions(+), 3 deletions(-)
1710 +
1711 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1712 +index 0e1ef88..ba1397f 100644
1713 +--- a/man/corosync.conf.5
1714 ++++ b/man/corosync.conf.5
1715 +@@ -191,7 +191,7 @@ version
1716 + This specifies the version of the configuration file. Currently the only
1717 + valid version for this directive is 2.
1718 +
1719 +-.PP
1720 ++.TP
1721 + clear_node_high_bit
1722 + This configuration option is optional and is only relevant when no nodeid is
1723 + specified. Some corosync clients require a signed 32 bit nodeid that is greater
1724 +@@ -432,8 +432,8 @@ The default is 180 milliseconds.
1725 + .TP
1726 + token_retransmits_before_loss_const
1727 + This value identifies how many token retransmits should be attempted before
1728 +-forming a new configuration. If this value is set, retransmit and hold will
1729 +-be automatically calculated from retransmits_before_loss and token.
1730 ++forming a new configuration. It is also used for token_retransmit
1731 ++and hold calculations.
1732 +
1733 + The default is 4 retransmissions.
1734 +
1735 diff --git a/debian/patches/man-Enhance-token_retransmit-description.patch b/debian/patches/man-Enhance-token_retransmit-description.patch
1736 new file mode 100644
1737 index 00000000..9b9f3def
1738 --- /dev/null
1739 +++ b/debian/patches/man-Enhance-token_retransmit-description.patch
1740 @@ -0,0 +1,28 @@
1741 +From: yuan ren <yren@suse.com>
1742 +Date: Thu, 16 May 2019 18:31:44 +0800
1743 +Subject: man: Enhance token_retransmit description
1744 +
1745 +Signed-off-by: yuan ren <yren@suse.com>
1746 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
1747 +(cherry picked from commit 3e8b525e3289e19c773e18c7fce9812393356ddc)
1748 +---
1749 + man/corosync.conf.5 | 6 +++++-
1750 + 1 file changed, 5 insertions(+), 1 deletion(-)
1751 +
1752 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
1753 +index e2fd9ed..5fef28a 100644
1754 +--- a/man/corosync.conf.5
1755 ++++ b/man/corosync.conf.5
1756 +@@ -394,7 +394,11 @@ the token is retransmitted. This will be automatically calculated if token
1757 + is modified. It is not recommended to alter this value without guidance from
1758 + the corosync community.
1759 +
1760 +-The default is 238 milliseconds.
1761 ++The minimum is 30 milliseconds. If not set and error occur, make sure
1762 ++token / (token_retransmits_before_loss_const + 0.2) is more than 30.
1763 ++
1764 ++The default is 238 milliseconds for two nodes cluster. Three or more nodes reference
1765 ++.B token_coefficient.
1766 +
1767 + .TP
1768 + knet_compression_model
1769 diff --git a/debian/patches/nozzle-Add-support-for-libnozzle-devices.patch b/debian/patches/nozzle-Add-support-for-libnozzle-devices.patch
1770 new file mode 100644
1771 index 00000000..47f9bda6
1772 --- /dev/null
1773 +++ b/debian/patches/nozzle-Add-support-for-libnozzle-devices.patch
1774 @@ -0,0 +1,707 @@
1775 +From: Christine Caulfield <ccaulfie@redhat.com>
1776 +Date: Tue, 15 Jan 2019 15:18:18 +0000
1777 +Subject: nozzle: Add support for libnozzle devices
1778 +
1779 +A nozzle device is a pseudo ethernet device that routes network
1780 +traffic through a channel on the corosync knet network (NOT cpg or any
1781 +corosync internal service) to other nodes in the cluster. It allows
1782 +applications to take advantage of knet features such as multipathing,
1783 +automatic failover, link switching etc.
1784 +
1785 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
1786 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
1787 +(cherry picked from commit eab55e7384c33f16d3d9b2c9c9d0878ddd234e38)
1788 +---
1789 + configure.ac | 6 +
1790 + exec/Makefile.am | 4 +-
1791 + exec/cfg.c | 1 +
1792 + exec/totemknet.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1793 + man/corosync.conf.5 | 68 +++++++--
1794 + 5 files changed, 476 insertions(+), 16 deletions(-)
1795 +
1796 +diff --git a/configure.ac b/configure.ac
1797 +index c85edf8..95cdb35 100644
1798 +--- a/configure.ac
1799 ++++ b/configure.ac
1800 +@@ -174,6 +174,7 @@ LIBS="$SAVE_LIBS"
1801 + AC_CHECK_LIB([pthread], [pthread_create])
1802 + AC_CHECK_LIB([socket], [socket])
1803 + PKG_CHECK_MODULES([knet],[libknet])
1804 ++PKG_CHECK_MODULES([nozzle],[libnozzle], [AC_DEFINE_UNQUOTED([HAVE_LIBNOZZLE], 1, [Have libnozzle])], [have_nozzle="no"])
1805 + AC_CHECK_LIB([nsl], [t_open])
1806 + AC_CHECK_LIB([rt], [sched_getscheduler])
1807 + AC_CHECK_LIB([z], [crc32],
1808 +@@ -404,6 +405,11 @@ ENV_CFLAGS="$CFLAGS"
1809 + ENV_CPPFLAGS="$CPPFLAGS"
1810 + ENV_LDFLAGS="$LDFLAGS"
1811 +
1812 ++# Add nozzle to Package features if enabled
1813 ++if test "x$have_nozzle" != xno; then
1814 ++ PACKAGE_FEATURES="$PACKAGE_FEATURES nozzle"
1815 ++fi
1816 ++
1817 + # debug build stuff
1818 + if test "x${enable_debug}" = xyes; then
1819 + AC_DEFINE_UNQUOTED([DEBUG], [1], [Compiling Debugging code])
1820 +diff --git a/exec/Makefile.am b/exec/Makefile.am
1821 +index 4602663..1c31f8c 100644
1822 +--- a/exec/Makefile.am
1823 ++++ b/exec/Makefile.am
1824 +@@ -59,10 +59,10 @@ endif
1825 +
1826 + corosync_CPPFLAGS = -DLOGCONFIG_USE_ICMAP=1
1827 +
1828 +-corosync_CFLAGS = $(statgrab_CFLAGS) $(libsystemd_CFLAGS) $(knet_CFLAGS)
1829 ++corosync_CFLAGS = $(statgrab_CFLAGS) $(libsystemd_CFLAGS) $(knet_CFLAGS) $(nozzle_CFLAGS)
1830 +
1831 + corosync_LDADD = ../common_lib/libcorosync_common.la \
1832 +- $(LIBQB_LIBS) $(statgrab_LIBS) $(libsystemd_LIBS) $(knet_LIBS)
1833 ++ $(LIBQB_LIBS) $(statgrab_LIBS) $(libsystemd_LIBS) $(knet_LIBS) $(nozzle_LIBS)
1834 +
1835 + corosync_DEPENDENCIES = ../common_lib/libcorosync_common.la
1836 +
1837 +diff --git a/exec/cfg.c b/exec/cfg.c
1838 +index dec7dbf..c02f739 100644
1839 +--- a/exec/cfg.c
1840 ++++ b/exec/cfg.c
1841 +@@ -701,6 +701,7 @@ static void message_handler_req_exec_cfg_reload_config (
1842 + remove_deleted_entries(temp_map, "nodelist.");
1843 + remove_deleted_entries(temp_map, "quorum.");
1844 + remove_deleted_entries(temp_map, "uidgid.config.");
1845 ++ remove_deleted_entries(temp_map, "nozzle.");
1846 +
1847 + /* Remove entries that cannot be changed */
1848 + remove_ro_entries(temp_map);
1849 +diff --git a/exec/totemknet.c b/exec/totemknet.c
1850 +index 1098bdb..77cb65a 100644
1851 +--- a/exec/totemknet.c
1852 ++++ b/exec/totemknet.c
1853 +@@ -1,6 +1,5 @@
1854 +-
1855 + /*
1856 +- * Copyright (c) 2016-2018 Red Hat, Inc.
1857 ++ * Copyright (c) 2016-2019 Red Hat, Inc.
1858 + *
1859 + * All rights reserved.
1860 + *
1861 +@@ -45,6 +44,7 @@
1862 + #include <sys/ioctl.h>
1863 + #include <sys/param.h>
1864 + #include <netinet/in.h>
1865 ++#include <net/ethernet.h>
1866 + #include <arpa/inet.h>
1867 + #include <unistd.h>
1868 + #include <fcntl.h>
1869 +@@ -60,6 +60,10 @@
1870 +
1871 + #include <qb/qbdefs.h>
1872 + #include <qb/qbloop.h>
1873 ++#ifdef HAVE_LIBNOZZLE
1874 ++#include <libgen.h>
1875 ++#include <libnozzle.h>
1876 ++#endif
1877 +
1878 + #include <corosync/sq.h>
1879 + #include <corosync/swab.h>
1880 +@@ -68,6 +72,7 @@
1881 + #include <corosync/totem/totemip.h>
1882 + #include "totemknet.h"
1883 +
1884 ++#include "main.h"
1885 + #include "util.h"
1886 +
1887 + #include <libknet.h>
1888 +@@ -77,6 +82,10 @@
1889 + #define MSG_NOSIGNAL 0
1890 + #endif
1891 +
1892 ++#ifdef HAVE_LIBNOZZLE
1893 ++static int setup_nozzle(void *knet_context);
1894 ++#endif
1895 ++
1896 + /* Should match that used by cfg */
1897 + #define CFG_INTERFACE_STATUS_MAX_LEN 512
1898 +
1899 +@@ -162,6 +171,13 @@ struct totemknet_instance {
1900 +
1901 + int logpipes[2];
1902 + int knet_fd;
1903 ++#ifdef HAVE_LIBNOZZLE
1904 ++ char *nozzle_name;
1905 ++ char *nozzle_ipaddr;
1906 ++ char *nozzle_prefix;
1907 ++ char *nozzle_macaddr;
1908 ++ nozzle_t nozzle_handle;
1909 ++#endif
1910 + };
1911 +
1912 + /* Awkward. But needed to get stats from knet */
1913 +@@ -217,6 +233,46 @@ do { \
1914 + } while(0)
1915 +
1916 +
1917 ++#ifdef HAVE_LIBNOZZLE
1918 ++static inline int is_ether_addr_multicast(const uint8_t *addr)
1919 ++{
1920 ++ return (addr[0] & 0x01);
1921 ++}
1922 ++static inline int is_ether_addr_zero(const uint8_t *addr)
1923 ++{
1924 ++ return (!addr[0] && !addr[1] && !addr[2] && !addr[3] && !addr[4] && !addr[5]);
1925 ++}
1926 ++
1927 ++static int ether_host_filter_fn(void *private_data,
1928 ++ const unsigned char *outdata,
1929 ++ ssize_t outdata_len,
1930 ++ uint8_t tx_rx,
1931 ++ knet_node_id_t this_host_id,
1932 ++ knet_node_id_t src_host_id,
1933 ++ int8_t *channel,
1934 ++ knet_node_id_t *dst_host_ids,
1935 ++ size_t *dst_host_ids_entries)
1936 ++{
1937 ++ struct ether_header *eth_h = (struct ether_header *)outdata;
1938 ++ uint8_t *dst_mac = (uint8_t *)eth_h->ether_dhost;
1939 ++ uint16_t dst_host_id;
1940 ++
1941 ++ if (is_ether_addr_zero(dst_mac))
1942 ++ return -1;
1943 ++
1944 ++ if (is_ether_addr_multicast(dst_mac)) {
1945 ++ return 1;
1946 ++ }
1947 ++
1948 ++ memmove(&dst_host_id, &dst_mac[4], 2);
1949 ++
1950 ++ dst_host_ids[0] = ntohs(dst_host_id);
1951 ++ *dst_host_ids_entries = 1;
1952 ++
1953 ++ return 0;
1954 ++}
1955 ++#endif
1956 ++
1957 + static int dst_host_filter_callback_fn(void *private_data,
1958 + const unsigned char *outdata,
1959 + ssize_t outdata_len,
1960 +@@ -230,7 +286,17 @@ static int dst_host_filter_callback_fn(void *private_data,
1961 + struct totem_message_header *header = (struct totem_message_header *)outdata;
1962 + int res;
1963 +
1964 +- *channel = 0;
1965 ++#ifdef HAVE_LIBNOZZLE
1966 ++ if (*channel != 0) {
1967 ++ return ether_host_filter_fn(private_data,
1968 ++ outdata, outdata_len,
1969 ++ tx_rx,
1970 ++ this_host_id, src_host_id,
1971 ++ channel,
1972 ++ dst_host_ids,
1973 ++ dst_host_ids_entries);
1974 ++ }
1975 ++#endif
1976 + if (header->target_nodeid) {
1977 + dst_host_ids[0] = header->target_nodeid;
1978 + *dst_host_ids_entries = 1;
1979 +@@ -1334,6 +1400,11 @@ int totemknet_reconfigure (
1980 + KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR, "knet_handle_compress failed");
1981 + }
1982 + }
1983 ++
1984 ++#ifdef HAVE_LIBNOZZLE
1985 ++ /* Set up nozzle device(s) */
1986 ++ setup_nozzle(instance);
1987 ++#endif
1988 + return (res);
1989 + }
1990 +
1991 +@@ -1454,3 +1525,339 @@ static void log_flush_messages (void *knet_context)
1992 + }
1993 + }
1994 + }
1995 ++
1996 ++
1997 ++#ifdef HAVE_LIBNOZZLE
1998 ++#define NOZZLE_NAME "nozzle.name"
1999 ++#define NOZZLE_IPADDR "nozzle.ipaddr"
2000 ++#define NOZZLE_PREFIX "nozzle.ipprefix"
2001 ++#define NOZZLE_MACADDR "nozzle.macaddr"
2002 ++
2003 ++#define NOZZLE_CHANNEL 1
2004 ++
2005 ++
2006 ++static char *get_nozzle_script_dir(void *knet_context)
2007 ++{
2008 ++ struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
2009 ++ char filename[PATH_MAX + FILENAME_MAX + 1];
2010 ++ static char updown_dirname[PATH_MAX + FILENAME_MAX + 1];
2011 ++ int res;
2012 ++ const char *dirname_res;
2013 ++
2014 ++ /*
2015 ++ * Build script directory based on corosync.conf file location
2016 ++ */
2017 ++ res = snprintf(filename, sizeof(filename), "%s",
2018 ++ corosync_get_config_file());
2019 ++ if (res >= sizeof(filename)) {
2020 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "nozzle up/down path too long");
2021 ++ return NULL;
2022 ++ }
2023 ++
2024 ++ dirname_res = dirname(filename);
2025 ++
2026 ++ res = snprintf(updown_dirname, sizeof(updown_dirname), "%s/%s",
2027 ++ dirname_res, "updown.d");
2028 ++ if (res >= sizeof(updown_dirname)) {
2029 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "nozzle up/down path too long");
2030 ++ return NULL;
2031 ++ }
2032 ++ return updown_dirname;
2033 ++}
2034 ++
2035 ++/*
2036 ++ * Deliberately doesn't return the status as caller doesn't care.
2037 ++ * The result will be logged though
2038 ++ */
2039 ++static void run_nozzle_script(struct totemknet_instance *instance, int type, const char *typename)
2040 ++{
2041 ++ int res;
2042 ++ char *exec_string;
2043 ++
2044 ++ res = nozzle_run_updown(instance->nozzle_handle, type, &exec_string);
2045 ++ if (res == -1 && errno != ENOENT) {
2046 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "exec nozzle %s script failed: %s", typename, strerror(errno));
2047 ++ } else if (res == -2) {
2048 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "nozzle %s script failed", typename);
2049 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "%s", exec_string);
2050 ++ }
2051 ++}
2052 ++
2053 ++/*
2054 ++ * Reparse IP address to add in our node ID
2055 ++ * IPv6 addresses must end in '::'
2056 ++ * IPv4 addresses must just be valid
2057 ++ * '/xx' lengths are optional for IPv6, mandatory for IPv4
2058 ++ *
2059 ++ * Returns the modified IP address as a string to pass into libnozzle
2060 ++ */
2061 ++static int reparse_nozzle_ip_address(struct totemknet_instance *instance,
2062 ++ const char *input_addr,
2063 ++ const char *prefix, int nodeid,
2064 ++ char *output_addr, size_t output_len)
2065 ++{
2066 ++ char *coloncolon;
2067 ++ int bits;
2068 ++ int max_prefix = 64;
2069 ++ uint32_t nodeid_mask;
2070 ++ uint32_t addr_mask;
2071 ++ uint32_t masked_nodeid;
2072 ++ struct in_addr *addr;
2073 ++ struct totem_ip_address totemip;
2074 ++
2075 ++ coloncolon = strstr(input_addr, "::");
2076 ++ if (!coloncolon) {
2077 ++ max_prefix = 30;
2078 ++ }
2079 ++
2080 ++ bits = atoi(prefix);
2081 ++ if (bits < 8 || bits > max_prefix) {
2082 ++ knet_log_printf(LOGSYS_LEVEL_ERROR, "nozzle IP address prefix must be >= 8 and <= %d (got %d)", max_prefix, bits);
2083 ++ return -1;
2084 ++ }
2085 ++
2086 ++ /* IPv6 is easy */
2087 ++ if (coloncolon) {
2088 ++ memcpy(output_addr, input_addr, coloncolon-input_addr);
2089 ++ sprintf(output_addr + (coloncolon-input_addr), "::%x", nodeid);
2090 ++ return 0;
2091 ++ }
2092 ++
2093 ++ /* For IPv4 we need to parse the address into binary, mask off the required bits,
2094 ++ * add in the masked_nodeid and 'print' it out again
2095 ++ */
2096 ++ nodeid_mask = UINT32_MAX & ((1<<(32 - bits)) - 1);
2097 ++ addr_mask = UINT32_MAX ^ nodeid_mask;
2098 ++ masked_nodeid = nodeid & nodeid_mask;
2099 ++
2100 ++ if (totemip_parse(&totemip, input_addr, AF_INET)) {
2101 ++ knet_log_printf(LOGSYS_LEVEL_ERROR, "Failed to parse IPv4 nozzle IP address");
2102 ++ return -1;
2103 ++ }
2104 ++ addr = (struct in_addr *)&totemip.addr;
2105 ++ addr->s_addr &= htonl(addr_mask);
2106 ++ addr->s_addr |= htonl(masked_nodeid);
2107 ++
2108 ++ inet_ntop(AF_INET, addr, output_addr, output_len);
2109 ++ return 0;
2110 ++}
2111 ++
2112 ++static int create_nozzle_device(void *knet_context, const char *name,
2113 ++ const char *ipaddr, const char *prefix,
2114 ++ const char *macaddr)
2115 ++{
2116 ++ struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
2117 ++ char device_name[IFNAMSIZ+1];
2118 ++ size_t size = IFNAMSIZ;
2119 ++ int8_t channel = NOZZLE_CHANNEL;
2120 ++ nozzle_t nozzle_dev;
2121 ++ int nozzle_fd;
2122 ++ int res;
2123 ++ char *updown_dir;
2124 ++ char parsed_ipaddr[INET6_ADDRSTRLEN];
2125 ++ char mac[19];
2126 ++
2127 ++ memset(device_name, 0, size);
2128 ++ memset(&mac, 0, sizeof(mac));
2129 ++ strncpy(device_name, name, size);
2130 ++
2131 ++ updown_dir = get_nozzle_script_dir(knet_context);
2132 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "nozzle script dir is %s", updown_dir);
2133 ++
2134 ++ nozzle_dev = nozzle_open(device_name, size, updown_dir);
2135 ++ if (!nozzle_dev) {
2136 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to init nozzle device %s: %s", device_name, strerror(errno));
2137 ++ return -1;
2138 ++ }
2139 ++ instance->nozzle_handle = nozzle_dev;
2140 ++
2141 ++ if (nozzle_set_mac(nozzle_dev, macaddr) < 0) {
2142 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to add set nozzle MAC to %s: %s", mac, strerror(errno));
2143 ++ goto out_clean;
2144 ++ }
2145 ++
2146 ++ if (reparse_nozzle_ip_address(instance, ipaddr, prefix, instance->our_nodeid, parsed_ipaddr, sizeof(parsed_ipaddr))) {
2147 ++ /* Prints its own errors */
2148 ++ goto out_clean;
2149 ++ }
2150 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "Local nozzle IP address is %s / %d", parsed_ipaddr, atoi(prefix));
2151 ++ if (ipaddr) {
2152 ++ if (nozzle_add_ip(nozzle_dev, parsed_ipaddr, prefix) < 0) {
2153 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to add set nozzle IP addr to %s/%s: %s", parsed_ipaddr, prefix, strerror(errno));
2154 ++ goto out_clean;
2155 ++ }
2156 ++ }
2157 ++
2158 ++ nozzle_fd = nozzle_get_fd(nozzle_dev);
2159 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "Opened '%s' on fd %d", device_name, nozzle_fd);
2160 ++
2161 ++ res = knet_handle_add_datafd(instance->knet_handle, &nozzle_fd, &channel);
2162 ++ if (res != 0) {
2163 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to add nozzle FD to knet: %s", strerror(errno));
2164 ++ goto out_clean;
2165 ++ }
2166 ++
2167 ++ run_nozzle_script(instance, NOZZLE_PREUP, "pre-up");
2168 ++
2169 ++ res = nozzle_set_up(nozzle_dev);
2170 ++ if (res != 0) {
2171 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to set nozzle interface UP: %s", strerror(errno));
2172 ++ goto out_clean;
2173 ++ }
2174 ++ run_nozzle_script(instance, NOZZLE_UP, "up");
2175 ++
2176 ++ return 0;
2177 ++
2178 ++out_clean:
2179 ++ nozzle_close(nozzle_dev);
2180 ++ return -1;
2181 ++}
2182 ++
2183 ++static int remove_nozzle_device(void *knet_context)
2184 ++{
2185 ++ struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
2186 ++ int res;
2187 ++ int datafd;
2188 ++
2189 ++ res = knet_handle_get_datafd(instance->knet_handle, NOZZLE_CHANNEL, &datafd);
2190 ++ if (res != 0) {
2191 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Can't find datafd for channel %d: %s", NOZZLE_CHANNEL, strerror(errno));
2192 ++ return -1;
2193 ++ }
2194 ++
2195 ++ res = knet_handle_remove_datafd(instance->knet_handle, datafd);
2196 ++ if (res != 0) {
2197 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Can't remove datafd for nozzle channel %d: %s", NOZZLE_CHANNEL, strerror(errno));
2198 ++ return -1;
2199 ++ }
2200 ++
2201 ++ run_nozzle_script(instance, NOZZLE_DOWN, "pre-down");
2202 ++ res = nozzle_set_down(instance->nozzle_handle);
2203 ++ if (res != 0) {
2204 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Can't set nozzle device down: %s", strerror(errno));
2205 ++ return -1;
2206 ++ }
2207 ++ run_nozzle_script(instance, NOZZLE_POSTDOWN, "post-down");
2208 ++
2209 ++ res = nozzle_close(instance->nozzle_handle);
2210 ++ if (res != 0) {
2211 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Can't close nozzle device: %s", strerror(errno));
2212 ++ return -1;
2213 ++ }
2214 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "Removed nozzle device");
2215 ++ return 0;
2216 ++}
2217 ++
2218 ++static void free_nozzle(struct totemknet_instance *instance)
2219 ++{
2220 ++ free(instance->nozzle_name);
2221 ++ free(instance->nozzle_ipaddr);
2222 ++ free(instance->nozzle_prefix);
2223 ++ free(instance->nozzle_macaddr);
2224 ++
2225 ++ instance->nozzle_name = instance->nozzle_ipaddr = instance->nozzle_prefix =
2226 ++ instance->nozzle_macaddr = NULL;
2227 ++}
2228 ++
2229 ++static int setup_nozzle(void *knet_context)
2230 ++{
2231 ++ struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
2232 ++ char *ipaddr_str = NULL;
2233 ++ char *name_str = NULL;
2234 ++ char *prefix_str = NULL;
2235 ++ char *macaddr_str = NULL;
2236 ++ char mac[32];
2237 ++ int name_res;
2238 ++ int macaddr_res;
2239 ++ int res;
2240 ++
2241 ++ icmap_get_string(NOZZLE_IPADDR, &ipaddr_str);
2242 ++ icmap_get_string(NOZZLE_PREFIX, &prefix_str);
2243 ++ macaddr_res = icmap_get_string(NOZZLE_MACADDR, &macaddr_str);
2244 ++ name_res = icmap_get_string(NOZZLE_NAME, &name_str);
2245 ++
2246 ++ /* Is is being removed? */
2247 ++ if (name_res == CS_ERR_NOT_EXIST && instance->nozzle_handle) {
2248 ++ remove_nozzle_device(instance);
2249 ++ free_nozzle(instance);
2250 ++ goto out_free;
2251 ++ }
2252 ++
2253 ++ if (!name_str) {
2254 ++ /* no nozzle */
2255 ++ goto out_free;
2256 ++ }
2257 ++
2258 ++ if (!ipaddr_str) {
2259 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "No IP address supplied for Nozzle device");
2260 ++ goto out_free;
2261 ++ }
2262 ++
2263 ++ if (!prefix_str) {
2264 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "No prefix supplied for Nozzle IP address");
2265 ++ goto out_free;
2266 ++ }
2267 ++
2268 ++ if (macaddr_str && strlen(macaddr_str) != 17) {
2269 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "macaddr for nozzle device is not in the correct format '%s'", macaddr_str);
2270 ++ goto out_free;
2271 ++ }
2272 ++ if (!macaddr_str) {
2273 ++ macaddr_str = (char*)"54:54:01:00:00:00";
2274 ++ }
2275 ++
2276 ++ if (instance->nozzle_name &&
2277 ++ (strcmp(name_str, instance->nozzle_name) == 0) &&
2278 ++ (strcmp(ipaddr_str, instance->nozzle_ipaddr) == 0) &&
2279 ++ (strcmp(prefix_str, instance->nozzle_prefix) == 0) &&
2280 ++ ((macaddr_str == NULL && instance->nozzle_macaddr == NULL) ||
2281 ++ strcmp(macaddr_str, instance->nozzle_macaddr) == 0)) {
2282 ++ /* Nothing has changed */
2283 ++ knet_log_printf (LOGSYS_LEVEL_DEBUG, "Nozzle device info not changed");
2284 ++ goto out_free;
2285 ++ }
2286 ++
2287 ++ /* Add nodeid into MAC address */
2288 ++ memcpy(mac, macaddr_str, 12);
2289 ++ snprintf(mac+12, sizeof(mac) - 13, "%02x:%02x",
2290 ++ instance->our_nodeid >> 8,
2291 ++ instance->our_nodeid & 0xFF);
2292 ++ knet_log_printf (LOGSYS_LEVEL_INFO, "Local nozzle MAC address is %s", mac);
2293 ++
2294 ++ if (name_res == CS_OK && name_str) {
2295 ++ /* Reconfigure */
2296 ++ if (instance->nozzle_name) {
2297 ++ remove_nozzle_device(instance);
2298 ++ free_nozzle(instance);
2299 ++ }
2300 ++
2301 ++ res = create_nozzle_device(knet_context, name_str, ipaddr_str, prefix_str,
2302 ++ mac);
2303 ++
2304 ++ instance->nozzle_name = strdup(name_str);
2305 ++ instance->nozzle_ipaddr = strdup(ipaddr_str);
2306 ++ instance->nozzle_prefix = strdup(prefix_str);
2307 ++ instance->nozzle_macaddr = strdup(macaddr_str);
2308 ++ if (!instance->nozzle_name || !instance->nozzle_ipaddr ||
2309 ++ !instance->nozzle_prefix) {
2310 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "strdup failed in nozzle allocation");
2311 ++ /*
2312 ++ * This 'free' will cause a complete reconfigure of the device next time we reload
2313 ++ * but will also let the the current device keep working until then.
2314 ++ * remove_nozzle() only needs the, statically-allocated, nozzle_handle
2315 ++ */
2316 ++ free_nozzle(instance);
2317 ++ }
2318 ++ }
2319 ++
2320 ++out_free:
2321 ++ free(name_str);
2322 ++ free(ipaddr_str);
2323 ++ free(prefix_str);
2324 ++ if (macaddr_res == CS_OK) {
2325 ++ free(macaddr_str);
2326 ++ }
2327 ++
2328 ++ return res;
2329 ++}
2330 ++#endif // HAVE_LIBNOZZLE
2331 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
2332 +index aa928bc..52eb7b1 100644
2333 +--- a/man/corosync.conf.5
2334 ++++ b/man/corosync.conf.5
2335 +@@ -63,9 +63,12 @@ This top level directive contains configuration options related to system.
2336 + .TP
2337 + resources { }
2338 + This top level directive contains configuration options for resources.
2339 ++.TP
2340 ++nozzle { }
2341 ++This top level directive contains configuration options for a libnozzle device.
2342 +
2343 + .PP
2344 +-The
2345 ++The
2346 + .B interface sub-directive of totem is optional for UDP and knet transports.
2347 +
2348 + For knet, multiple interface subsections define parameters for each knet link on the
2349 +@@ -78,7 +81,7 @@ is used to define cluster nodes.
2350 + linknumber
2351 + This specifies the link number for the interface. When using the knet
2352 + protocol, each interface should specify separate link numbers to uniquely
2353 +-identify to the membership protocol which interface to use for which link.
2354 ++identify to the membership protocol which interface to use for which link.
2355 + The linknumber must start at 0. For UDP the only supported linknumber is 0.
2356 +
2357 + .TP
2358 +@@ -88,7 +91,7 @@ mode. (see link_mode below)
2359 +
2360 + .TP
2361 + knet_ping_interval
2362 +-This specifies the interval between knet link pings.
2363 ++This specifies the interval between knet link pings.
2364 + knet_ping_interval and knet_ping_timeout
2365 + are a pair, if one is specified the other should be too, otherwise one will be calculated from
2366 + the token timeout and one will be taken from the config file.
2367 +@@ -96,7 +99,7 @@ the token timeout and one will be taken from the config file.
2368 +
2369 + .TP
2370 + knet_ping_timeout
2371 +-If no ping is received within this time, the knet link is declared dead.
2372 ++If no ping is received within this time, the knet link is declared dead.
2373 + knet_ping_interval and knet_ping_timeout
2374 + are a pair, if one is specified the other should be too, otherwise one will be calculated from
2375 + the token timeout and one will be taken from the config file.
2376 +@@ -120,7 +123,7 @@ bindnetaddr (udp only)
2377 + This specifies the network address the corosync executive should bind
2378 + to when using udp.
2379 +
2380 +-bindnetaddr (udp only)
2381 ++bindnetaddr (udp only)
2382 + should be an IP address configured on the system, or a network
2383 + address.
2384 +
2385 +@@ -160,9 +163,9 @@ mcastport (udp only)
2386 + This specifies the UDP port number. It is possible to use the same multicast
2387 + address on a network with the corosync services configured for different
2388 + UDP ports.
2389 +-Please note corosync uses two UDP ports mcastport (for mcast receives) and
2390 ++Please note corosync uses two UDP ports mcastport (for mcast receives) and
2391 + mcastport - 1 (for mcast sends).
2392 +-If you have multiple clusters on the same network using the same mcastaddr
2393 ++If you have multiple clusters on the same network using the same mcastaddr
2394 + please configure the mcastports with a gap.
2395 +
2396 + .TP
2397 +@@ -243,14 +246,14 @@ link_mode
2398 + This specifies the Kronosnet mode, which may be passive, active, or
2399 + rr (round-robin).
2400 + .B passive:
2401 +-the active link with the lowest priority will be used. If one or more
2402 ++the active link with the lowest priority will be used. If one or more
2403 + links share the same priority the one with the lowest link ID will
2404 + be used.
2405 + .B active:
2406 + All active links will be used simultaneously to send traffic.
2407 + link priority is ignored.
2408 + .B rr:
2409 +-Round-Robin policy. Each packet will be sent to the next active link in
2410 ++Round-Robin policy. Each packet will be sent to the next active link in
2411 + order.
2412 +
2413 + If only one interface directive is specified, passive is automatically chosen.
2414 +@@ -284,7 +287,7 @@ The default is 1500.
2415 +
2416 + .TP
2417 + transport
2418 +-This directive controls the transport mechanism used.
2419 ++This directive controls the transport mechanism used.
2420 + The default is knet. The transport type can also be set to udpu or udp.
2421 + Only knet allows crypto or multiple interfaces per node.
2422 +
2423 +@@ -604,7 +607,7 @@ and
2424 + The default is syslog and stderr.
2425 +
2426 + Please note, if you are using to_logfile and want to rotate the file, use logrotate(8)
2427 +-with the option
2428 ++with the option
2429 + .B
2430 + copytruncate.
2431 + eg.
2432 +@@ -797,6 +800,49 @@ potentially breaking down membership. IPMI watchdogs are particularly
2433 + notorious in this regard: read about kipmid_max_busy_us in IPMI.txt in
2434 + the Linux kernel documentation.
2435 +
2436 ++
2437 ++.PP
2438 ++Within the
2439 ++.B nozzle
2440 ++directive it is possible to specify options for a libnozzle device. This is a pseudo
2441 ++ethernet device that routes network traffic through a channel on the corosync knet network
2442 ++(NOT cpg or any corosync internal service) to other nodes in the cluster. This allows
2443 ++applications to take advantage of knet features such as multipathing, automatic failover,
2444 ++link switching etc. Note that libnozzle is not a reliable transport, but you can tunnel TCP
2445 ++through it for reliable communications.
2446 ++.br
2447 ++libnozzle also supports optional interface up/down scripts that are kept under a
2448 ++/etc/corosync/updown.d/ directory. See the knet documentation for more information.
2449 ++.br
2450 ++Only one nozzle device is allowed.
2451 ++.br
2452 ++The nozzle stanza takes several options:
2453 ++.TP
2454 ++name
2455 ++The name of the network device to be created. On Linux this may be any name at all, other
2456 ++platforms have restrictions on the name.
2457 ++.TP
2458 ++ipaddr
2459 ++The IP address (IPv6 or IPv4) of the interface. The bottom part of this address will be replaced
2460 ++by the local node's nodeid in conjunction with ipprefix. so, eg
2461 ++ipaddr: 192.168.1.0
2462 ++ipprefix: 24
2463 ++will make nodeids 1,2,5 use IP addresses 192.168.1.1, 192.168.1.2 & 192.168.1.5.
2464 ++If a prefix length of 16 is used then the bottom two bytes will be filled in with nodeid numbers.
2465 ++IPv6 addresses must end in '::', the nodeid will be added after the two colons to make the
2466 ++local IP address.
2467 ++Only one IP address is currently supported in the corosync.conf file. Additional IP addresses
2468 ++can be added in the ifup script if necessary.
2469 ++.TP
2470 ++ipprefix
2471 ++specifies the IP address prefix for the nozzle device (see above)
2472 ++.TP
2473 ++macaddr
2474 ++Specifies the MAC address prefix for the nozzle device. As for the IP address, the bottom part
2475 ++of the MAC address will be filled in with the node id. In this case no prefix applies, the bottom
2476 ++two bytes of the MAC address will always be overwritten with the node id. So specifying
2477 ++macaddr: 54:54:12:24:12:12 on nodeid 1 will result in it having a MAC address of 54:54:12:24:00:01
2478 ++
2479 + .SH "TO ADD A NEW NODE TO THE CLUSTER"
2480 + For example to add a node with address 10.24.38.108 with nodeid 3. The node has the name NEW
2481 + (in DNS or /etc/hosts) and is not currently running corosync. The current corosync.conf nodelist
2482 diff --git a/debian/patches/quorumtool-Fix-exit-status-codes.patch b/debian/patches/quorumtool-Fix-exit-status-codes.patch
2483 new file mode 100644
2484 index 00000000..e001d123
2485 --- /dev/null
2486 +++ b/debian/patches/quorumtool-Fix-exit-status-codes.patch
2487 @@ -0,0 +1,237 @@
2488 +From: Jan Friesse <jfriesse@redhat.com>
2489 +Date: Thu, 14 Feb 2019 16:05:59 +0100
2490 +Subject: quorumtool: Fix exit status codes
2491 +
2492 +1. Use EXIT_SUCCESS and EXIT_FAILURE when possible
2493 +2. For -s option return EXIT_SUCCESS when no problem appeared and node
2494 + is quorate, EXIT_FAILURE if problem appeared and exit code 2
2495 + (EXIT_NOT_QUORATE) when no problem appeared but node is not quorate.
2496 +3. Document exit codes in the man page
2497 +
2498 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
2499 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
2500 +(cherry picked from commit db38e3958c4f88d5d06e8f7c83d6d90334d9fbd2)
2501 +---
2502 + tools/corosync-quorumtool.c | 53 ++++++++++++++++++++++++++-------------------
2503 + man/corosync-quorumtool.8 | 17 ++++++++++++++-
2504 + 2 files changed, 47 insertions(+), 23 deletions(-)
2505 +
2506 +diff --git a/tools/corosync-quorumtool.c b/tools/corosync-quorumtool.c
2507 +index 8f128e0..4819951 100644
2508 +--- a/tools/corosync-quorumtool.c
2509 ++++ b/tools/corosync-quorumtool.c
2510 +@@ -1,5 +1,5 @@
2511 + /*
2512 +- * Copyright (c) 2009-2014 Red Hat, Inc.
2513 ++ * Copyright (c) 2009-2019 Red Hat, Inc.
2514 + *
2515 + * All rights reserved.
2516 + *
2517 +@@ -75,6 +75,8 @@ typedef enum {
2518 + SORT_NODENAME
2519 + } sorttype_t;
2520 +
2521 ++#define EXIT_NOT_QUORATE 2
2522 ++
2523 + /*
2524 + * global vars
2525 + */
2526 +@@ -238,7 +240,7 @@ static int set_votes(uint32_t nodeid, int votes)
2527 + votes, nodeid, cs_strerror(err));
2528 + }
2529 +
2530 +- return err==CS_OK?0:err;
2531 ++ return (err == CS_OK ? EXIT_SUCCESS : EXIT_FAILURE);
2532 + }
2533 +
2534 + static int set_expected(int expected_votes)
2535 +@@ -249,7 +251,7 @@ static int set_expected(int expected_votes)
2536 + fprintf(stderr, "Unable to set expected votes: %s\n", cs_strerror(err));
2537 + }
2538 +
2539 +- return err==CS_OK?0:err;
2540 ++ return (err == CS_OK ? EXIT_SUCCESS : EXIT_FAILURE);
2541 + }
2542 +
2543 + /*
2544 +@@ -642,9 +644,9 @@ static int display_quorum_data(int is_quorate,
2545 + }
2546 +
2547 + /*
2548 +- * return 1 if quorate
2549 +- * 0 if not quorate
2550 +- * -1 on error
2551 ++ * return EXIT_SUCCESS if quorate
2552 ++ * EXIT_NOT_QUORATE if not quorate
2553 ++ * EXIT_FAILURE on error
2554 + */
2555 + static int show_status(nodeid_format_t nodeid_format, name_format_t name_format, sorttype_t sort_type)
2556 + {
2557 +@@ -693,15 +695,15 @@ static int show_status(nodeid_format_t nodeid_format, name_format_t name_format,
2558 +
2559 + quorum_err:
2560 + if (err != CS_OK) {
2561 +- return -1;
2562 ++ return EXIT_FAILURE;
2563 + }
2564 +
2565 + err = display_quorum_data(is_quorate, nodeid_format, name_format, sort_type, 0);
2566 + if (err != CS_OK) {
2567 +- return -1;
2568 ++ return EXIT_FAILURE;
2569 + }
2570 +
2571 +- return is_quorate;
2572 ++ return (is_quorate ? EXIT_SUCCESS : EXIT_NOT_QUORATE);
2573 + }
2574 +
2575 + static int monitor_status(nodeid_format_t nodeid_format, name_format_t name_format, sorttype_t sort_type) {
2576 +@@ -754,7 +756,7 @@ static int monitor_status(nodeid_format_t nodeid_format, name_format_t name_form
2577 + }
2578 +
2579 + quorum_err:
2580 +- return -1;
2581 ++ return EXIT_FAILURE;
2582 + }
2583 +
2584 + static int show_nodes(nodeid_format_t nodeid_format, name_format_t name_format, sorttype_t sort_type)
2585 +@@ -788,23 +790,30 @@ static int unregister_qdevice(void)
2586 + {
2587 + int err;
2588 + struct votequorum_info info;
2589 ++ int result;
2590 ++
2591 ++ result = EXIT_FAILURE;
2592 +
2593 + err = votequorum_getinfo(v_handle, our_nodeid, &info);
2594 + if (err != CS_OK) {
2595 + fprintf(stderr, "Unable to get quorum device info: %s\n", cs_strerror(err));
2596 +- return -1;
2597 ++ goto err_exit;
2598 + }
2599 +
2600 + if (!(info.flags & VOTEQUORUM_INFO_QDEVICE_REGISTERED)) {
2601 +- return 0;
2602 ++ result = EXIT_SUCCESS;
2603 ++ goto err_exit;
2604 + }
2605 +
2606 + err = votequorum_qdevice_unregister(v_handle, info.qdevice_name);
2607 + if (err != CS_OK) {
2608 + fprintf(stderr, "Unable to unregister quorum device: %s\n", cs_strerror(err));
2609 +- return -1;
2610 ++ goto err_exit;
2611 + }
2612 +- return 0;
2613 ++
2614 ++ result = EXIT_SUCCESS;
2615 ++err_exit:
2616 ++ return result;
2617 + }
2618 +
2619 + /*
2620 +@@ -888,7 +897,7 @@ int main (int argc, char *argv[]) {
2621 +
2622 + if (init_all()) {
2623 + close_all();
2624 +- exit(1);
2625 ++ exit(EXIT_FAILURE);
2626 + }
2627 +
2628 + while ( (opt = getopt(argc, argv, options)) != -1 ) {
2629 +@@ -898,7 +907,7 @@ int main (int argc, char *argv[]) {
2630 + command_opt = CMD_UNREGISTER_QDEVICE;
2631 + } else {
2632 + fprintf(stderr, "You cannot unregister quorum device, corosync is not using votequorum\n");
2633 +- exit(2);
2634 ++ exit(EXIT_FAILURE);
2635 + }
2636 + break;
2637 + case 's':
2638 +@@ -932,14 +941,14 @@ int main (int argc, char *argv[]) {
2639 + }
2640 + } else {
2641 + fprintf(stderr, "You cannot change expected votes, corosync is not using votequorum\n");
2642 +- exit(2);
2643 ++ exit(EXIT_FAILURE);
2644 + }
2645 + break;
2646 + case 'n':
2647 + l = strtol(optarg, &endptr, 0);
2648 + if ((l == 0 && endptr == optarg) || l < 0) {
2649 + fprintf(stderr, "The nodeid was not valid, try a positive number\n");
2650 +- exit(2);
2651 ++ exit(EXIT_FAILURE);
2652 + }
2653 + nodeid = l;
2654 + nodeid_set = 1;
2655 +@@ -949,14 +958,14 @@ int main (int argc, char *argv[]) {
2656 + votes = strtol(optarg, &endptr, 0);
2657 + if ((votes == 0 && endptr == optarg) || votes < 0) {
2658 + fprintf(stderr, "New votes value was not valid, try a positive number or zero\n");
2659 +- exit(2);
2660 ++ exit(EXIT_FAILURE);
2661 + } else {
2662 + command_opt = CMD_SETVOTES;
2663 + }
2664 + }
2665 + else {
2666 + fprintf(stderr, "You cannot change node votes, corosync is not using votequorum\n");
2667 +- exit(2);
2668 ++ exit(EXIT_FAILURE);
2669 + }
2670 + break;
2671 + case 'o':
2672 +@@ -970,7 +979,7 @@ int main (int argc, char *argv[]) {
2673 + break;
2674 + default:
2675 + fprintf(stderr, "Invalid ordering option. valid orders are a(address), i(node ID) or n(name)\n");
2676 +- exit(2);
2677 ++ exit(EXIT_FAILURE);
2678 + break;
2679 + }
2680 + break;
2681 +@@ -989,7 +998,7 @@ int main (int argc, char *argv[]) {
2682 + switch (command_opt) {
2683 + case CMD_UNKNOWN:
2684 + show_usage(argv[0]);
2685 +- ret = -1;
2686 ++ ret = EXIT_FAILURE;
2687 + break;
2688 + case CMD_SHOWNODES:
2689 + ret = show_nodes(nodeid_format, address_format, sort_opt);
2690 +diff --git a/man/corosync-quorumtool.8 b/man/corosync-quorumtool.8
2691 +index 0fdfccf..24c9112 100644
2692 +--- a/man/corosync-quorumtool.8
2693 ++++ b/man/corosync-quorumtool.8
2694 +@@ -31,7 +31,7 @@
2695 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
2696 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
2697 + .\" */
2698 +-.TH COROSYNC-QUORUMTOOL 8 2012-01-12
2699 ++.TH COROSYNC-QUORUMTOOL 8 2019-02-14
2700 + .SH NAME
2701 + corosync-quorumtool \- Set and display quorum settings.
2702 + .SH SYNOPSIS
2703 +@@ -89,6 +89,21 @@ show this help text
2704 + show version and exit
2705 + .PP
2706 + * Starred items only work if votequorum is the quorum provider for corosync
2707 ++.SH EXIT STATUS
2708 ++corosync-quorumtool may return one of several error codes if it encounters problems.
2709 ++.TP
2710 ++0
2711 ++No problems occurred (quorate for
2712 ++.B -s
2713 ++operation).
2714 ++.TP
2715 ++1
2716 ++Generic error code.
2717 ++.TP
2718 ++2
2719 ++Not quorate (returned only for
2720 ++.B -s
2721 ++operation).
2722 + .SH SEE ALSO
2723 + .BR corosync_overview (7),
2724 + .BR votequorum_overview (3),
2725 diff --git a/debian/patches/set-totem.keyfile-and-totem.key-to-RO.patch b/debian/patches/set-totem.keyfile-and-totem.key-to-RO.patch
2726 new file mode 100644
2727 index 00000000..6bd733e7
2728 --- /dev/null
2729 +++ b/debian/patches/set-totem.keyfile-and-totem.key-to-RO.patch
2730 @@ -0,0 +1,44 @@
2731 +From: =?utf-8?q?Fabian_Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
2732 +Date: Wed, 3 Apr 2019 21:57:30 +0200
2733 +Subject: set totem.keyfile and totem.key to RO
2734 +MIME-Version: 1.0
2735 +Content-Type: text/plain; charset="utf-8"
2736 +Content-Transfer-Encoding: 8bit
2737 +
2738 +so that we get the nice log message when attempting to modify them at
2739 +runtime, just like for totem.crypto_* and co.
2740 +
2741 +Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
2742 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
2743 +(cherry picked from commit 03fba21503f1b8395519190cc537f63100e995f5)
2744 +---
2745 + exec/cfg.c | 2 ++
2746 + exec/main.c | 2 ++
2747 + 2 files changed, 4 insertions(+)
2748 +
2749 +diff --git a/exec/cfg.c b/exec/cfg.c
2750 +index c02f739..f42cb60 100644
2751 +--- a/exec/cfg.c
2752 ++++ b/exec/cfg.c
2753 +@@ -578,6 +578,8 @@ static void remove_ro_entries(icmap_map_t temp_map)
2754 + delete_and_notify_if_changed(temp_map, "totem.secauth");
2755 + delete_and_notify_if_changed(temp_map, "totem.crypto_hash");
2756 + delete_and_notify_if_changed(temp_map, "totem.crypto_cipher");
2757 ++ delete_and_notify_if_changed(temp_map, "totem.keyfile");
2758 ++ delete_and_notify_if_changed(temp_map, "totem.key");
2759 + delete_and_notify_if_changed(temp_map, "totem.version");
2760 + delete_and_notify_if_changed(temp_map, "totem.threads");
2761 + delete_and_notify_if_changed(temp_map, "totem.ip_version");
2762 +diff --git a/exec/main.c b/exec/main.c
2763 +index 8554036..06a519c 100644
2764 +--- a/exec/main.c
2765 ++++ b/exec/main.c
2766 +@@ -1036,6 +1036,8 @@ static void set_icmap_ro_keys_flag (void)
2767 + */
2768 + icmap_set_ro_access("totem.crypto_cipher", CS_FALSE, CS_TRUE);
2769 + icmap_set_ro_access("totem.crypto_hash", CS_FALSE, CS_TRUE);
2770 ++ icmap_set_ro_access("totem.keyfile", CS_FALSE, CS_TRUE);
2771 ++ icmap_set_ro_access("totem.key", CS_FALSE, CS_TRUE);
2772 + icmap_set_ro_access("totem.secauth", CS_FALSE, CS_TRUE);
2773 + icmap_set_ro_access("totem.ip_version", CS_FALSE, CS_TRUE);
2774 + icmap_set_ro_access("totem.rrp_mode", CS_FALSE, CS_TRUE);
2775 diff --git a/debian/patches/spec-Add-support-for-user-flags-configure-option.patch b/debian/patches/spec-Add-support-for-user-flags-configure-option.patch
2776 new file mode 100644
2777 index 00000000..d7254b82
2778 --- /dev/null
2779 +++ b/debian/patches/spec-Add-support-for-user-flags-configure-option.patch
2780 @@ -0,0 +1,43 @@
2781 +From: Jan Friesse <jfriesse@redhat.com>
2782 +Date: Fri, 7 Jun 2019 10:20:04 +0200
2783 +Subject: spec: Add support for user-flags configure option
2784 +
2785 +Passing -ggdb3 (or -g3) during compiler may result in corrupted
2786 +debuginfo files (bug in debugedit - for Fedora filed as a
2787 +https://bugzilla.redhat.com/show_bug.cgi?id=1708786). Until the bug is
2788 +fixed it's possible to ether change configure to add -ggdb2/-g2 or use
2789 +already existing --enable-user-flags option and rely on environment set
2790 +by rpmbuild.
2791 +
2792 +Patch implements second option so RPM distros without broken debugedit
2793 +are not affected.
2794 +
2795 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
2796 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
2797 +(cherry picked from commit 5cced85cd58905638c81892f79e9f457efac338e)
2798 +---
2799 + corosync.spec.in | 4 ++++
2800 + 1 file changed, 4 insertions(+)
2801 +
2802 +diff --git a/corosync.spec.in b/corosync.spec.in
2803 +index 8af686e..c06675d 100644
2804 +--- a/corosync.spec.in
2805 ++++ b/corosync.spec.in
2806 +@@ -14,6 +14,7 @@
2807 + %bcond_with nozzle
2808 + %bcond_with vqsim
2809 + %bcond_with runautogen
2810 ++%bcond_with userflags
2811 +
2812 + %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}
2813 + %global gittarver %{?numcomm:.%{numcomm}}%{?alphatag:-%{alphatag}}%{?dirty:-%{dirty}}
2814 +@@ -107,6 +108,9 @@ BuildRequires: readline-devel
2815 + %endif
2816 + %if %{with vqsim}
2817 + --enable-vqsim \
2818 ++%endif
2819 ++%if %{with userflags}
2820 ++ --enable-user-flags \
2821 + %endif
2822 + --with-initddir=%{_initrddir} \
2823 + --with-systemddir=%{_unitdir} \
2824 diff --git a/debian/patches/totemconfig-Ensure-nodeid-is-specified-for-IPv6.patch b/debian/patches/totemconfig-Ensure-nodeid-is-specified-for-IPv6.patch
2825 new file mode 100644
2826 index 00000000..27b55a98
2827 --- /dev/null
2828 +++ b/debian/patches/totemconfig-Ensure-nodeid-is-specified-for-IPv6.patch
2829 @@ -0,0 +1,48 @@
2830 +From: Jan Friesse <jfriesse@redhat.com>
2831 +Date: Wed, 24 Apr 2019 14:47:47 +0200
2832 +Subject: totemconfig: Ensure nodeid is specified for IPv6
2833 +
2834 +Thanks Yuan Ren <yren@suse.com> for finding this problem.
2835 +
2836 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
2837 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
2838 +(cherry picked from commit 3172a76d12d16dd6c72182e005ac0bc63e58208b)
2839 +---
2840 + exec/totemconfig.c | 17 +++++++++++++++++
2841 + 1 file changed, 17 insertions(+)
2842 +
2843 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
2844 +index b206eeb..6fcd6de 100644
2845 +--- a/exec/totemconfig.c
2846 ++++ b/exec/totemconfig.c
2847 +@@ -1258,6 +1258,16 @@ static int put_nodelist_members_to_config(struct totem_config *totem_config, int
2848 + snprintf(tmp_key, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.ring0_addr", node_pos);
2849 + if (icmap_get_string(tmp_key, &str) == CS_OK) {
2850 + nodeid = generate_nodeid(totem_config, str);
2851 ++ if (nodeid == -1) {
2852 ++ sprintf(error_string_response,
2853 ++ "An IPV6 network requires that a node ID be specified "
2854 ++ "for address '%s'.", node_addr_str);
2855 ++ *error_string = error_string_response;
2856 ++ free(str);
2857 ++
2858 ++ return (-1);
2859 ++ }
2860 ++
2861 + log_printf(LOGSYS_LEVEL_DEBUG,
2862 + "Generated nodeid = 0x%x for %s", nodeid, str);
2863 + free(str);
2864 +@@ -1750,6 +1760,13 @@ extern int totem_config_read (
2865 + icmap_get_string(tmp_key, &str);
2866 +
2867 + totem_config->node_id = generate_nodeid(totem_config, str);
2868 ++ if (totem_config->node_id == -1) {
2869 ++ *error_string = "An IPV6 network requires that a node ID be specified";
2870 ++
2871 ++ free(str);
2872 ++ return (-1);
2873 ++ }
2874 ++
2875 + totem_config->interfaces[0].member_list[local_node_pos].nodeid = totem_config->node_id;
2876 +
2877 + free(str);
2878 diff --git a/debian/patches/totemconfig-Fix-minimum-limit-for-hold-timeout.patch b/debian/patches/totemconfig-Fix-minimum-limit-for-hold-timeout.patch
2879 new file mode 100644
2880 index 00000000..26b553c3
2881 --- /dev/null
2882 +++ b/debian/patches/totemconfig-Fix-minimum-limit-for-hold-timeout.patch
2883 @@ -0,0 +1,67 @@
2884 +From: yuan ren <yren@suse.com>
2885 +Date: Tue, 14 May 2019 19:33:12 +0800
2886 +Subject: totemconfig: Fix minimum limit for hold timeout
2887 +
2888 +Make sure the retransmit timeout have the lowest limit
2889 +`MINIMUM_TIMEOUT`. So, the lowest limit of hold should be
2890 +recalculated.
2891 +
2892 +Also token timeout and retransmits count should
2893 +keep a relational expression.
2894 +
2895 +Signed-off-by: yuan ren <yren@suse.com>
2896 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
2897 +(cherry picked from commit 2a4cd3c4af0256cc79e1ed1c7f070fd469e4cfaf)
2898 +---
2899 + exec/totemconfig.c | 20 ++++++++++++++------
2900 + 1 file changed, 14 insertions(+), 6 deletions(-)
2901 +
2902 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
2903 +index 091eedc..262dcac 100644
2904 +--- a/exec/totemconfig.c
2905 ++++ b/exec/totemconfig.c
2906 +@@ -74,6 +74,7 @@
2907 + #define FAIL_TO_RECV_CONST 2500
2908 + #define SEQNO_UNCHANGED_CONST 30
2909 + #define MINIMUM_TIMEOUT (int)(1000/HZ)*3
2910 ++#define MINIMUM_TIMEOUT_HOLD (int)(MINIMUM_TIMEOUT * 0.8 - (1000/HZ))
2911 + #define MAX_NETWORK_DELAY 50
2912 + #define WINDOW_SIZE 50
2913 + #define MAX_MESSAGES 17
2914 +@@ -313,6 +314,7 @@ static int totem_volatile_config_validate (
2915 + char name_key[ICMAP_KEYNAME_MAXLEN];
2916 + char *name_str;
2917 + int i, num_configured, members;
2918 ++ uint32_t tmp_config_value;
2919 +
2920 + if (totem_config->max_network_delay < MINIMUM_TIMEOUT) {
2921 + snprintf (local_error_reason, sizeof(local_error_reason),
2922 +@@ -336,16 +338,22 @@ static int totem_volatile_config_validate (
2923 + }
2924 +
2925 + if (totem_config->token_retransmit_timeout < MINIMUM_TIMEOUT) {
2926 +- snprintf (local_error_reason, sizeof(local_error_reason),
2927 +- "The token retransmit timeout parameter (%d ms) may not be less than (%d ms).",
2928 +- totem_config->token_retransmit_timeout, MINIMUM_TIMEOUT);
2929 +- goto parse_error;
2930 ++ if (icmap_get_uint32("totem.token_retransmit", &tmp_config_value) == CS_OK) {
2931 ++ snprintf (local_error_reason, sizeof(local_error_reason),
2932 ++ "The token retransmit timeout parameter (%d ms) may not be less than (%d ms).",
2933 ++ totem_config->token_retransmit_timeout, MINIMUM_TIMEOUT);
2934 ++ goto parse_error;
2935 ++ } else {
2936 ++ snprintf (local_error_reason, sizeof(local_error_reason),
2937 ++ "Not appropriate token or token_retransmits_before_loss_const value set");
2938 ++ goto parse_error;
2939 ++ }
2940 + }
2941 +
2942 +- if (totem_config->token_hold_timeout < MINIMUM_TIMEOUT) {
2943 ++ if (totem_config->token_hold_timeout < MINIMUM_TIMEOUT_HOLD) {
2944 + snprintf (local_error_reason, sizeof(local_error_reason),
2945 + "The token hold timeout parameter (%d ms) may not be less than (%d ms).",
2946 +- totem_config->token_hold_timeout, MINIMUM_TIMEOUT);
2947 ++ totem_config->token_hold_timeout, MINIMUM_TIMEOUT_HOLD);
2948 + goto parse_error;
2949 + }
2950 +
2951 diff --git a/debian/patches/totemconfig-Remove-support-for-3des.patch b/debian/patches/totemconfig-Remove-support-for-3des.patch
2952 new file mode 100644
2953 index 00000000..63dcc729
2954 --- /dev/null
2955 +++ b/debian/patches/totemconfig-Remove-support-for-3des.patch
2956 @@ -0,0 +1,138 @@
2957 +From: Jan Friesse <jfriesse@redhat.com>
2958 +Date: Thu, 11 Apr 2019 08:23:29 +0200
2959 +Subject: totemconfig: Remove support for 3des
2960 +
2961 +Triple DES is considered as a "weak cipher" since 2016 so there is
2962 +really no need to support it in the corosync. Thanks to bug in
2963 +Corosync/Knet/NSS which caused 3des to not work at all,
2964 +no matter what library was used, we can just remove support for 3des
2965 +without braking the compatibility.
2966 +
2967 +Also fix coroparse so:
2968 +- totem.crypto_type is removed (this is 1.x construct which was not used
2969 +even in 2.x)
2970 +- Add checking of totem.crypto_model.
2971 +- Enumarate possible values for crypto_model, crypto_cipher and
2972 +crypto_hash error messages
2973 +
2974 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
2975 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
2976 +(cherry picked from commit d05636b738e3cb1cd7a491e4ef492cd44a8bf6a9)
2977 +---
2978 + exec/coroparse.c | 21 ++++++++++-----------
2979 + exec/totemconfig.c | 3 ---
2980 + conf/lenses/corosync.aug | 4 ++--
2981 + man/corosync.conf.5 | 6 +++---
2982 + 4 files changed, 15 insertions(+), 19 deletions(-)
2983 +
2984 +diff --git a/exec/coroparse.c b/exec/coroparse.c
2985 +index 08f8f14..0acb4c2 100644
2986 +--- a/exec/coroparse.c
2987 ++++ b/exec/coroparse.c
2988 +@@ -1,5 +1,5 @@
2989 + /*
2990 +- * Copyright (c) 2006-2018 Red Hat, Inc.
2991 ++ * Copyright (c) 2006-2019 Red Hat, Inc.
2992 + *
2993 + * All rights reserved.
2994 + *
2995 +@@ -747,13 +747,11 @@ static int main_config_parser_cb(const char *path,
2996 + return (0);
2997 + }
2998 + }
2999 +- if (strcmp(path, "totem.crypto_type") == 0) {
3000 ++ if (strcmp(path, "totem.crypto_model") == 0) {
3001 + if ((strcmp(value, "nss") != 0) &&
3002 +- (strcmp(value, "aes256") != 0) &&
3003 +- (strcmp(value, "aes192") != 0) &&
3004 +- (strcmp(value, "aes128") != 0) &&
3005 +- (strcmp(value, "3des") != 0)) {
3006 +- *error_string = "Invalid crypto type";
3007 ++ (strcmp(value, "openssl") != 0)) {
3008 ++ *error_string = "Invalid crypto model. "
3009 ++ "Should be nss or openssl";
3010 +
3011 + return (0);
3012 + }
3013 +@@ -762,9 +760,9 @@ static int main_config_parser_cb(const char *path,
3014 + if ((strcmp(value, "none") != 0) &&
3015 + (strcmp(value, "aes256") != 0) &&
3016 + (strcmp(value, "aes192") != 0) &&
3017 +- (strcmp(value, "aes128") != 0) &&
3018 +- (strcmp(value, "3des") != 0)) {
3019 +- *error_string = "Invalid cipher type";
3020 ++ (strcmp(value, "aes128") != 0)) {
3021 ++ *error_string = "Invalid cipher type. "
3022 ++ "Should be none, aes256, aes192 or aes128";
3023 +
3024 + return (0);
3025 + }
3026 +@@ -776,7 +774,8 @@ static int main_config_parser_cb(const char *path,
3027 + (strcmp(value, "sha256") != 0) &&
3028 + (strcmp(value, "sha384") != 0) &&
3029 + (strcmp(value, "sha512") != 0)) {
3030 +- *error_string = "Invalid hash type";
3031 ++ *error_string = "Invalid hash type. "
3032 ++ "Should be none, md5, sha1, sha256, sha384 or sha512";
3033 +
3034 + return (0);
3035 + }
3036 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
3037 +index d57562a..4f69fd5 100644
3038 +--- a/exec/totemconfig.c
3039 ++++ b/exec/totemconfig.c
3040 +@@ -463,9 +463,6 @@ static int totem_get_crypto(struct totem_config *totem_config, const char **erro
3041 + if (strcmp(str, "aes128") == 0) {
3042 + tmp_cipher = "aes128";
3043 + }
3044 +- if (strcmp(str, "3des") == 0) {
3045 +- tmp_cipher = "3des";
3046 +- }
3047 + free(str);
3048 + }
3049 +
3050 +diff --git a/conf/lenses/corosync.aug b/conf/lenses/corosync.aug
3051 +index 39334f1..edeb4fb 100644
3052 +--- a/conf/lenses/corosync.aug
3053 ++++ b/conf/lenses/corosync.aug
3054 +@@ -51,8 +51,8 @@ let totem =
3055 + |kv "rrp_mode" /none|active|passive/
3056 + |kv "vsftype" /none|ykd/
3057 + |kv "secauth" /on|off/
3058 +- |kv "crypto_type" /nss|aes256|aes192|aes128|3des/
3059 +- |kv "crypto_cipher" /none|nss|aes256|aes192|aes128|3des/
3060 ++ |kv "crypto_model" /nss|openssl/
3061 ++ |kv "crypto_cipher" /none|nss|aes256|aes192|aes128/
3062 + |kv "crypto_hash" /none|md5|sha1|sha256|sha384|sha512/
3063 + |kv "transport" /udp|iba|udpu/
3064 + |kv "version" Rx.integer
3065 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
3066 +index 52eb7b1..887a52b 100644
3067 +--- a/man/corosync.conf.5
3068 ++++ b/man/corosync.conf.5
3069 +@@ -1,6 +1,6 @@
3070 + .\"/*
3071 + .\" * Copyright (c) 2005 MontaVista Software, Inc.
3072 +-.\" * Copyright (c) 2006-2018 Red Hat, Inc.
3073 ++.\" * Copyright (c) 2006-2019 Red Hat, Inc.
3074 + .\" *
3075 + .\" * All rights reserved.
3076 + .\" *
3077 +@@ -32,7 +32,7 @@
3078 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3079 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
3080 + .\" */
3081 +-.TH COROSYNC_CONF 5 2019-01-16 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
3082 ++.TH COROSYNC_CONF 5 2019-04-11 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
3083 + .SH NAME
3084 + corosync.conf - corosync executive configuration file
3085 +
3086 +@@ -221,7 +221,7 @@ The default is none.
3087 + .TP
3088 + crypto_cipher
3089 + This specifies which cipher should be used to encrypt all messages.
3090 +-Valid values are none (no encryption), aes256, aes192, aes128 and 3des.
3091 ++Valid values are none (no encryption), aes256, aes192 and aes128.
3092 + Enabling crypto_cipher, requires also enabling of crypto_hash. Encrypted
3093 + transmission is only supported for the knet transport.
3094 +
3095 diff --git a/debian/patches/totemconfig-fix-autogen-mcastaddr-for-ipv6-4.patch b/debian/patches/totemconfig-fix-autogen-mcastaddr-for-ipv6-4.patch
3096 new file mode 100644
3097 index 00000000..43e02d43
3098 --- /dev/null
3099 +++ b/debian/patches/totemconfig-fix-autogen-mcastaddr-for-ipv6-4.patch
3100 @@ -0,0 +1,51 @@
3101 +From: yuan ren <yren@suse.com>
3102 +Date: Sun, 28 Apr 2019 18:29:37 +0800
3103 +Subject: totemconfig: fix autogen mcastaddr for ipv6-4
3104 +
3105 +When UDP is used as a transport, the error would occur
3106 +"Multicast address family does not match bind address family"
3107 +because there is no ipv6 in /etc/hosts specified but using the
3108 +totem.ip_version: ipv6-4. because
3109 +the mcastaddr generated (if not specified) only according to
3110 +the totem.ip_version.
3111 +
3112 +Solution is to use bindnetaddr (configured or generated from
3113 +nodelist) addr family.
3114 +
3115 +Signed-off-by: yuan ren <yren@suse.com>
3116 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
3117 +(cherry picked from commit 70cda5d55f57b99c564be5e7871d291118553a74)
3118 +---
3119 + exec/totemconfig.c | 10 +++++++++-
3120 + 1 file changed, 9 insertions(+), 1 deletion(-)
3121 +
3122 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
3123 +index 6fcd6de..3b4dbae 100644
3124 +--- a/exec/totemconfig.c
3125 ++++ b/exec/totemconfig.c
3126 +@@ -1370,6 +1370,7 @@ static int get_interface_params(struct totem_config *totem_config,
3127 + uint32_t u32;
3128 + char *str;
3129 + char *cluster_name = NULL;
3130 ++ enum totem_ip_version_enum tmp_ip_version = TOTEM_IP_VERSION_4;
3131 +
3132 + if (reload) {
3133 + for (i=0; i<INTERFACE_MAX; i++) {
3134 +@@ -1460,9 +1461,16 @@ static int get_interface_params(struct totem_config *totem_config,
3135 + * udpu doesn't need mcastaddr and validity of mcastaddr for udp is
3136 + * checked later anyway.
3137 + */
3138 ++
3139 ++ if (totem_config->interfaces[0].bindnet.family == AF_INET) {
3140 ++ tmp_ip_version = TOTEM_IP_VERSION_4;
3141 ++ } else if (totem_config->interfaces[0].bindnet.family == AF_INET6) {
3142 ++ tmp_ip_version = TOTEM_IP_VERSION_6;
3143 ++ }
3144 ++
3145 + (void)get_cluster_mcast_addr (cluster_name,
3146 + linknumber,
3147 +- totem_config->ip_version,
3148 ++ tmp_ip_version,
3149 + &totem_config->interfaces[linknumber].mcast_addr);
3150 + }
3151 +
3152 diff --git a/debian/patches/totemconfig-ipaddr_equal-check-just-addr-part.patch b/debian/patches/totemconfig-ipaddr_equal-check-just-addr-part.patch
3153 new file mode 100644
3154 index 00000000..a3c47f7b
3155 --- /dev/null
3156 +++ b/debian/patches/totemconfig-ipaddr_equal-check-just-addr-part.patch
3157 @@ -0,0 +1,86 @@
3158 +From: Jan Friesse <jfriesse@redhat.com>
3159 +Date: Tue, 23 Apr 2019 12:38:04 +0200
3160 +Subject: totemconfig: ipaddr_equal check just addr part
3161 +
3162 +Checking whole structure is fine for IPv4, but IPv6 contains also scope
3163 +id, what may be problem for local address. It's possible to use a zone
3164 +index, but because it's not required when host name is used, it
3165 +shouldn't be needed when IPv6 address is used.
3166 +
3167 +Example configuration snip which fails without patch:
3168 +
3169 +...
3170 +nodelist {
3171 + node {
3172 + nodeid: 1
3173 + ring0_addr: fe80::1234:5678:9abc:def1
3174 + }
3175 +}
3176 +...
3177 +
3178 +(example succeed when %eth0 is used).
3179 +
3180 +With patch, zone index is not needed.
3181 +
3182 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3183 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3184 +(cherry picked from commit d05c1593a11c91d2f419418188ebc7a23f9cc38a)
3185 +---
3186 + exec/totemconfig.c | 28 ++++++++++++++--------------
3187 + 1 file changed, 14 insertions(+), 14 deletions(-)
3188 +
3189 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
3190 +index 1954f76..b206eeb 100644
3191 +--- a/exec/totemconfig.c
3192 ++++ b/exec/totemconfig.c
3193 +@@ -560,27 +560,28 @@ static int nodelist_byname(const char *find_name, int strip_domain)
3194 + return -1;
3195 + }
3196 +
3197 +-/* Compare two addresses */
3198 +-static int ipaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
3199 ++/* Compare two addresses - only address part (sin_addr/sin6_addr) is checked */
3200 ++static int ipaddr_equal(const struct sockaddr *addr1, const struct sockaddr *addr2)
3201 + {
3202 + int addrlen = 0;
3203 ++ const void *addr1p, *addr2p;
3204 +
3205 +- if (addr1->ss_family != addr2->ss_family)
3206 ++ if (addr1->sa_family != addr2->sa_family)
3207 + return 0;
3208 +
3209 +- if (addr1->ss_family == AF_INET) {
3210 +- addrlen = sizeof(struct sockaddr_in);
3211 ++ if (addr1->sa_family == AF_INET) {
3212 ++ addrlen = sizeof(struct in_addr);
3213 ++ addr1p = &((struct sockaddr_in *)addr1)->sin_addr;
3214 ++ addr2p = &((struct sockaddr_in *)addr2)->sin_addr;
3215 + }
3216 +- if (addr1->ss_family == AF_INET6) {
3217 +- addrlen = sizeof(struct sockaddr_in6);
3218 ++ if (addr1->sa_family == AF_INET6) {
3219 ++ addrlen = sizeof(struct in6_addr);
3220 ++ addr1p = &((struct sockaddr_in6 *)addr1)->sin6_addr;
3221 ++ addr2p = &((struct sockaddr_in6 *)addr2)->sin6_addr;
3222 + }
3223 + assert(addrlen);
3224 +
3225 +- if (memcmp(addr1, addr2, addrlen) == 0)
3226 +- return 1;
3227 +- else
3228 +- return 0;
3229 +-
3230 ++ return (memcmp(addr1p, addr2p, addrlen) == 0);
3231 + }
3232 +
3233 +
3234 +@@ -760,8 +761,7 @@ static int find_local_node(int use_cache)
3235 + for (rp = result; rp != NULL; rp = rp->ai_next) {
3236 + for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) {
3237 + if (ifa->ifa_addr &&
3238 +- ipaddr_equal((struct sockaddr_storage *)rp->ai_addr,
3239 +- (struct sockaddr_storage *)ifa->ifa_addr)) {
3240 ++ ipaddr_equal(rp->ai_addr, ifa->ifa_addr)) {
3241 + freeaddrinfo(result);
3242 + found = 1;
3243 + goto out2;
3244 diff --git a/debian/patches/totemconfig-ipaddr_equal-use-switch.patch b/debian/patches/totemconfig-ipaddr_equal-use-switch.patch
3245 new file mode 100644
3246 index 00000000..f0cd1bbc
3247 --- /dev/null
3248 +++ b/debian/patches/totemconfig-ipaddr_equal-use-switch.patch
3249 @@ -0,0 +1,44 @@
3250 +From: Jan Friesse <jfriesse@redhat.com>
3251 +Date: Tue, 11 Jun 2019 10:24:05 +0200
3252 +Subject: totemconfig: ipaddr_equal use switch
3253 +
3254 +Compiler may have problem understanding relation between addr1p and
3255 +addrlen. Small change makes code a little more readable and compiler
3256 +happy.
3257 +
3258 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3259 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3260 +(cherry picked from commit 299c9c5b7016f4f8e423162791fcf4cb3fe70529)
3261 +---
3262 + exec/totemconfig.c | 11 +++++++----
3263 + 1 file changed, 7 insertions(+), 4 deletions(-)
3264 +
3265 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
3266 +index 0501589..ff86e23 100644
3267 +--- a/exec/totemconfig.c
3268 ++++ b/exec/totemconfig.c
3269 +@@ -630,17 +630,20 @@ static int ipaddr_equal(const struct sockaddr *addr1, const struct sockaddr *add
3270 + if (addr1->sa_family != addr2->sa_family)
3271 + return 0;
3272 +
3273 +- if (addr1->sa_family == AF_INET) {
3274 ++ switch (addr1->sa_family) {
3275 ++ case AF_INET:
3276 + addrlen = sizeof(struct in_addr);
3277 + addr1p = &((struct sockaddr_in *)addr1)->sin_addr;
3278 + addr2p = &((struct sockaddr_in *)addr2)->sin_addr;
3279 +- }
3280 +- if (addr1->sa_family == AF_INET6) {
3281 ++ break;
3282 ++ case AF_INET6:
3283 + addrlen = sizeof(struct in6_addr);
3284 + addr1p = &((struct sockaddr_in6 *)addr1)->sin6_addr;
3285 + addr2p = &((struct sockaddr_in6 *)addr2)->sin6_addr;
3286 ++ break;
3287 ++ default:
3288 ++ assert(0);
3289 + }
3290 +- assert(addrlen);
3291 +
3292 + return (memcmp(addr1p, addr2p, addrlen) == 0);
3293 + }
3294 diff --git a/debian/patches/totemip-Use-res-in-totemip_sa_equal.patch b/debian/patches/totemip-Use-res-in-totemip_sa_equal.patch
3295 new file mode 100644
3296 index 00000000..2a691774
3297 --- /dev/null
3298 +++ b/debian/patches/totemip-Use-res-in-totemip_sa_equal.patch
3299 @@ -0,0 +1,32 @@
3300 +From: Jan Friesse <jfriesse@redhat.com>
3301 +Date: Tue, 11 Jun 2019 10:28:41 +0200
3302 +Subject: totemip: Use res in totemip_sa_equal
3303 +
3304 +Setting res to -1 was not entirely following semantics of "equal"
3305 +operation. Set it to 0 and return it when families differs makes
3306 +compiler happy.
3307 +
3308 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3309 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3310 +(cherry picked from commit d4d48d9268ea5bb43382e4ed8241cccaa9d2e99a)
3311 +---
3312 + exec/totemip.c | 4 ++--
3313 + 1 file changed, 2 insertions(+), 2 deletions(-)
3314 +
3315 +diff --git a/exec/totemip.c b/exec/totemip.c
3316 +index 4c2eafe..7accf71 100644
3317 +--- a/exec/totemip.c
3318 ++++ b/exec/totemip.c
3319 +@@ -97,10 +97,10 @@ int totemip_sa_equal(const struct totem_ip_address *totem_ip,
3320 + {
3321 + int res;
3322 +
3323 +- res = -1;
3324 ++ res = 0;
3325 +
3326 + if (totem_ip->family != sa->sa_family) {
3327 +- return 0;
3328 ++ return (res);
3329 + }
3330 +
3331 + switch (totem_ip->family) {
3332 diff --git a/debian/patches/totemknet-Ignore-icmap_get_string-result.patch b/debian/patches/totemknet-Ignore-icmap_get_string-result.patch
3333 new file mode 100644
3334 index 00000000..432ce704
3335 --- /dev/null
3336 +++ b/debian/patches/totemknet-Ignore-icmap_get_string-result.patch
3337 @@ -0,0 +1,32 @@
3338 +From: Jan Friesse <jfriesse@redhat.com>
3339 +Date: Tue, 11 Jun 2019 10:40:07 +0200
3340 +Subject: totemknet: Ignore icmap_get_string result
3341 +
3342 +... and add comment why it is not a bug.
3343 +
3344 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3345 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3346 +(cherry picked from commit 9b809383e65a57b8604132d93e005d42b42c71a1)
3347 +---
3348 + exec/totemknet.c | 8 ++++++--
3349 + 1 file changed, 6 insertions(+), 2 deletions(-)
3350 +
3351 +diff --git a/exec/totemknet.c b/exec/totemknet.c
3352 +index 774cb2c..8762185 100644
3353 +--- a/exec/totemknet.c
3354 ++++ b/exec/totemknet.c
3355 +@@ -1795,8 +1795,12 @@ static int setup_nozzle(void *knet_context)
3356 + int macaddr_res;
3357 + int res;
3358 +
3359 +- icmap_get_string(NOZZLE_IPADDR, &ipaddr_str);
3360 +- icmap_get_string(NOZZLE_PREFIX, &prefix_str);
3361 ++ /*
3362 ++ * Return value ignored on purpose. icmap_get_string changes
3363 ++ * ipaddr_str/prefix_str only on success.
3364 ++ */
3365 ++ (void)icmap_get_string(NOZZLE_IPADDR, &ipaddr_str);
3366 ++ (void)icmap_get_string(NOZZLE_PREFIX, &prefix_str);
3367 + macaddr_res = icmap_get_string(NOZZLE_MACADDR, &macaddr_str);
3368 + name_res = icmap_get_string(NOZZLE_NAME, &name_str);
3369 +
3370 diff --git a/debian/patches/totemknet-Initialize-return-value-in-setup_nozzle.patch b/debian/patches/totemknet-Initialize-return-value-in-setup_nozzle.patch
3371 new file mode 100644
3372 index 00000000..e2f6bcde
3373 --- /dev/null
3374 +++ b/debian/patches/totemknet-Initialize-return-value-in-setup_nozzle.patch
3375 @@ -0,0 +1,39 @@
3376 +From: Jan Friesse <jfriesse@redhat.com>
3377 +Date: Tue, 11 Jun 2019 11:00:03 +0200
3378 +Subject: totemknet: Initialize return value in setup_nozzle
3379 +
3380 +Also add comment why return value is currently not used.
3381 +
3382 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3383 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3384 +(cherry picked from commit 0839d3af82833342b43a64fbc403227a574bd63b)
3385 +---
3386 + exec/totemknet.c | 8 +++++---
3387 + 1 file changed, 5 insertions(+), 3 deletions(-)
3388 +
3389 +diff --git a/exec/totemknet.c b/exec/totemknet.c
3390 +index eb2ed2c..e6e04d3 100644
3391 +--- a/exec/totemknet.c
3392 ++++ b/exec/totemknet.c
3393 +@@ -1428,8 +1428,10 @@ int totemknet_reconfigure (
3394 + }
3395 +
3396 + #ifdef HAVE_LIBNOZZLE
3397 +- /* Set up nozzle device(s) */
3398 +- setup_nozzle(instance);
3399 ++ /* Set up nozzle device(s). Return code is ignored, because unability
3400 ++ * configure nozzle is not fatal problem, errors are logged and
3401 ++ * there is not much else we can do */
3402 ++ (void)setup_nozzle(instance);
3403 + #endif
3404 + return (res);
3405 + }
3406 +@@ -1793,7 +1795,7 @@ static int setup_nozzle(void *knet_context)
3407 + char mac[32];
3408 + int name_res;
3409 + int macaddr_res;
3410 +- int res;
3411 ++ int res = -1;
3412 +
3413 + /*
3414 + * Return value ignored on purpose. icmap_get_string changes
3415 diff --git a/debian/patches/totemknet-create_nozzle_device-simplify-check.patch b/debian/patches/totemknet-create_nozzle_device-simplify-check.patch
3416 new file mode 100644
3417 index 00000000..e3260daf
3418 --- /dev/null
3419 +++ b/debian/patches/totemknet-create_nozzle_device-simplify-check.patch
3420 @@ -0,0 +1,34 @@
3421 +From: Jan Friesse <jfriesse@redhat.com>
3422 +Date: Tue, 11 Jun 2019 10:32:40 +0200
3423 +Subject: totemknet: create_nozzle_device simplify check
3424 +
3425 +ipaddr existence is checked for being not NULL by caller setup_nozzle.
3426 +Also ipaddr was passed to reparse_nozzle_ip_address function unchecked
3427 +so code would crash before reaching the actual check.
3428 +
3429 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3430 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3431 +(cherry picked from commit 9a0e7b584e3b217e0bdf1a017b5995cbce27f708)
3432 +---
3433 + exec/totemknet.c | 8 +++-----
3434 + 1 file changed, 3 insertions(+), 5 deletions(-)
3435 +
3436 +diff --git a/exec/totemknet.c b/exec/totemknet.c
3437 +index 2af69b3..774cb2c 100644
3438 +--- a/exec/totemknet.c
3439 ++++ b/exec/totemknet.c
3440 +@@ -1707,11 +1707,9 @@ static int create_nozzle_device(void *knet_context, const char *name,
3441 + goto out_clean;
3442 + }
3443 + knet_log_printf (LOGSYS_LEVEL_INFO, "Local nozzle IP address is %s / %d", parsed_ipaddr, atoi(prefix));
3444 +- if (ipaddr) {
3445 +- if (nozzle_add_ip(nozzle_dev, parsed_ipaddr, prefix) < 0) {
3446 +- knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to add set nozzle IP addr to %s/%s: %s", parsed_ipaddr, prefix, strerror(errno));
3447 +- goto out_clean;
3448 +- }
3449 ++ if (nozzle_add_ip(nozzle_dev, parsed_ipaddr, prefix) < 0) {
3450 ++ knet_log_printf (LOGSYS_LEVEL_ERROR, "Unable to add set nozzle IP addr to %s/%s: %s", parsed_ipaddr, prefix, strerror(errno));
3451 ++ goto out_clean;
3452 + }
3453 +
3454 + nozzle_fd = nozzle_get_fd(nozzle_dev);
3455 diff --git a/debian/patches/totemknet-macaddr_str-is-always-set.patch b/debian/patches/totemknet-macaddr_str-is-always-set.patch
3456 new file mode 100644
3457 index 00000000..c2574cae
3458 --- /dev/null
3459 +++ b/debian/patches/totemknet-macaddr_str-is-always-set.patch
3460 @@ -0,0 +1,27 @@
3461 +From: Jan Friesse <jfriesse@redhat.com>
3462 +Date: Tue, 11 Jun 2019 10:44:17 +0200
3463 +Subject: totemknet: macaddr_str is always set
3464 +
3465 +Check for NULL was invalid, because macaddr_str is ether defined in cmap
3466 +or set to "54:54:01:00:00:00".
3467 +
3468 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3469 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3470 +(cherry picked from commit 0d82e23517e299dec877e632c9c9a4d441789be8)
3471 +---
3472 + exec/totemknet.c | 2 +-
3473 + 1 file changed, 1 insertion(+), 1 deletion(-)
3474 +
3475 +diff --git a/exec/totemknet.c b/exec/totemknet.c
3476 +index 8762185..eb2ed2c 100644
3477 +--- a/exec/totemknet.c
3478 ++++ b/exec/totemknet.c
3479 +@@ -1838,7 +1838,7 @@ static int setup_nozzle(void *knet_context)
3480 + (strcmp(name_str, instance->nozzle_name) == 0) &&
3481 + (strcmp(ipaddr_str, instance->nozzle_ipaddr) == 0) &&
3482 + (strcmp(prefix_str, instance->nozzle_prefix) == 0) &&
3483 +- ((macaddr_str == NULL && instance->nozzle_macaddr == NULL) ||
3484 ++ (instance->nozzle_macaddr == NULL ||
3485 + strcmp(macaddr_str, instance->nozzle_macaddr) == 0)) {
3486 + /* Nothing has changed */
3487 + knet_log_printf (LOGSYS_LEVEL_DEBUG, "Nozzle device info not changed");
3488 diff --git a/debian/patches/totemsrp-Word-spelling-mistake.patch b/debian/patches/totemsrp-Word-spelling-mistake.patch
3489 new file mode 100644
3490 index 00000000..99e1ffaa
3491 --- /dev/null
3492 +++ b/debian/patches/totemsrp-Word-spelling-mistake.patch
3493 @@ -0,0 +1,24 @@
3494 +From: yuan ren <yren@suse.com>
3495 +Date: Fri, 29 Mar 2019 15:43:10 +0800
3496 +Subject: totemsrp: Word spelling mistake
3497 +
3498 +Signed-off-by: yuan ren <reyren179@gmail.com>
3499 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
3500 +(cherry picked from commit 24a72e9780f30d29e0097700b68bd2056845bc31)
3501 +---
3502 + exec/totemsrp.c | 2 +-
3503 + 1 file changed, 1 insertion(+), 1 deletion(-)
3504 +
3505 +diff --git a/exec/totemsrp.c b/exec/totemsrp.c
3506 +index ab27924..a48d97b 100644
3507 +--- a/exec/totemsrp.c
3508 ++++ b/exec/totemsrp.c
3509 +@@ -434,7 +434,7 @@ struct totemsrp_instance {
3510 +
3511 + void (*totemsrp_log_printf) (
3512 + int level,
3513 +- int sybsys,
3514 ++ int subsys,
3515 + const char *function,
3516 + const char *file,
3517 + int line,
3518 diff --git a/debian/patches/udpu-Drop-packets-from-unlisted-IPs.patch b/debian/patches/udpu-Drop-packets-from-unlisted-IPs.patch
3519 new file mode 100644
3520 index 00000000..591e4873
3521 --- /dev/null
3522 +++ b/debian/patches/udpu-Drop-packets-from-unlisted-IPs.patch
3523 @@ -0,0 +1,254 @@
3524 +From: Jan Friesse <jfriesse@redhat.com>
3525 +Date: Fri, 24 May 2019 08:48:01 +0200
3526 +Subject: udpu: Drop packets from unlisted IPs
3527 +
3528 +This feature allows corosync to block packets received from unknown
3529 +nodes (nodes with IP address which is not in the nodelist). This is
3530 +mainly for situations when "forgotten" node is booted and tries to join
3531 +cluster which already removed such node from configuration. Another use
3532 +case is to allow atomic reconfiguration and rejoin of two separate
3533 +clusters.
3534 +
3535 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3536 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3537 +(cherry picked from commit 72737d39292feb7c9253c26418e1e25ef0a7fad9)
3538 +---
3539 + include/corosync/totem/totem.h | 2 ++
3540 + include/corosync/totem/totemip.h | 2 ++
3541 + exec/totemconfig.c | 55 +++++++++++++++++++++++++++++++++++++++-
3542 + exec/totemip.c | 27 ++++++++++++++++++++
3543 + exec/totemudpu.c | 34 +++++++++++++++++++++++++
3544 + man/corosync.conf.5 | 10 +++++++-
3545 + 6 files changed, 128 insertions(+), 2 deletions(-)
3546 +
3547 +diff --git a/include/corosync/totem/totem.h b/include/corosync/totem/totem.h
3548 +index d9d8e46..00ee0ab 100644
3549 +--- a/include/corosync/totem/totem.h
3550 ++++ b/include/corosync/totem/totem.h
3551 +@@ -233,6 +233,8 @@ struct totem_config {
3552 +
3553 + enum totem_ip_version_enum ip_version;
3554 +
3555 ++ unsigned int block_unlisted_ips;
3556 ++
3557 + void (*totem_memb_ring_id_create_or_load) (
3558 + struct memb_ring_id *memb_ring_id,
3559 + unsigned int nodeid);
3560 +diff --git a/include/corosync/totem/totemip.h b/include/corosync/totem/totemip.h
3561 +index b8da3c9..91b2266 100644
3562 +--- a/include/corosync/totem/totemip.h
3563 ++++ b/include/corosync/totem/totemip.h
3564 +@@ -86,6 +86,8 @@ struct totem_ip_if_address
3565 +
3566 + extern int totemip_equal(const struct totem_ip_address *addr1,
3567 + const struct totem_ip_address *addr2);
3568 ++extern int totemip_sa_equal(const struct totem_ip_address *totem_ip,
3569 ++ const struct sockaddr *sa);
3570 + extern int totemip_compare(const void *a, const void *b);
3571 + extern int totemip_is_mcast(struct totem_ip_address *addr);
3572 + extern void totemip_copy(struct totem_ip_address *addr1,
3573 +diff --git a/exec/totemconfig.c b/exec/totemconfig.c
3574 +index 262dcac..0501589 100644
3575 +--- a/exec/totemconfig.c
3576 ++++ b/exec/totemconfig.c
3577 +@@ -79,6 +79,7 @@
3578 + #define WINDOW_SIZE 50
3579 + #define MAX_MESSAGES 17
3580 + #define MISS_COUNT_CONST 5
3581 ++#define BLOCK_UNLISTED_IPS 1
3582 +
3583 + /* These currently match the defaults in libknet.h */
3584 + #define KNET_PING_INTERVAL 1000
3585 +@@ -138,6 +139,8 @@ static void *totem_get_param_by_name(struct totem_config *totem_config, const ch
3586 + return &totem_config->knet_compression_level;
3587 + if (strcmp(param_name, "totem.knet_compression_model") == 0)
3588 + return &totem_config->knet_compression_model;
3589 ++ if (strcmp(param_name, "totem.block_unlisted_ips") == 0)
3590 ++ return &totem_config->block_unlisted_ips;
3591 +
3592 + return NULL;
3593 + }
3594 +@@ -235,6 +238,55 @@ static void totem_volatile_config_set_string_value (struct totem_config *totem_c
3595 + icmap_set_string(runtime_key_name, (char *)*config_value);
3596 + }
3597 +
3598 ++/*
3599 ++ * Read string value stored in key_name from icmap, use it as a boolean (yes/no) type, convert it
3600 ++ * to integer value (1/0) and store into totem_config.
3601 ++ *
3602 ++ * If key is not found or key_name == delete_key default value is used
3603 ++ * and stored into totem_config.
3604 ++ */
3605 ++static void totem_volatile_config_set_boolean_value (struct totem_config *totem_config,
3606 ++ const char *key_name, const char *deleted_key, unsigned int default_value)
3607 ++{
3608 ++ char runtime_key_name[ICMAP_KEYNAME_MAXLEN];
3609 ++ char *str;
3610 ++ int val;
3611 ++
3612 ++ str = NULL;
3613 ++ val = default_value;
3614 ++
3615 ++ if ((deleted_key != NULL && strcmp(deleted_key, key_name) == 0) ||
3616 ++ (icmap_get_string(key_name, &str) != CS_OK)) {
3617 ++ /*
3618 ++ * Do nothing. str is NULL (icmap_get_string ether not called or
3619 ++ * not changed str).
3620 ++ */
3621 ++ } else {
3622 ++ if (strcmp(str, "yes") == 0) {
3623 ++ val = 1;
3624 ++ } else if (strcmp(str, "no") == 0) {
3625 ++ val = 0;
3626 ++ }
3627 ++ free(str);
3628 ++ }
3629 ++
3630 ++ /*
3631 ++ * Store totem_config value to cmap runtime section
3632 ++ */
3633 ++ if (strlen("runtime.config.") + strlen(key_name) >= ICMAP_KEYNAME_MAXLEN) {
3634 ++ /*
3635 ++ * This shouldn't happen
3636 ++ */
3637 ++ return ;
3638 ++ }
3639 ++
3640 ++ strcpy(runtime_key_name, "runtime.config.");
3641 ++ strcat(runtime_key_name, key_name);
3642 ++
3643 ++ *(uint32_t *)totem_get_param_by_name(totem_config, key_name) = val;
3644 ++
3645 ++ icmap_set_uint32(runtime_key_name, val);
3646 ++}
3647 +
3648 + /*
3649 + * Read and validate config values from cmap and store them into totem_config. If key doesn't exists,
3650 +@@ -302,7 +354,8 @@ static void totem_volatile_config_read (struct totem_config *totem_config, const
3651 +
3652 + totem_volatile_config_set_string_value(totem_config, "totem.knet_compression_model", deleted_key, "none");
3653 +
3654 +-
3655 ++ totem_volatile_config_set_boolean_value(totem_config, "totem.block_unlisted_ips", deleted_key,
3656 ++ BLOCK_UNLISTED_IPS);
3657 + }
3658 +
3659 + static int totem_volatile_config_validate (
3660 +diff --git a/exec/totemip.c b/exec/totemip.c
3661 +index 36d0a72..4c2eafe 100644
3662 +--- a/exec/totemip.c
3663 ++++ b/exec/totemip.c
3664 +@@ -92,6 +92,33 @@ int totemip_equal(const struct totem_ip_address *addr1,
3665 +
3666 + }
3667 +
3668 ++int totemip_sa_equal(const struct totem_ip_address *totem_ip,
3669 ++ const struct sockaddr *sa)
3670 ++{
3671 ++ int res;
3672 ++
3673 ++ res = -1;
3674 ++
3675 ++ if (totem_ip->family != sa->sa_family) {
3676 ++ return 0;
3677 ++ }
3678 ++
3679 ++ switch (totem_ip->family) {
3680 ++ case AF_INET:
3681 ++ res = (memcmp(totem_ip->addr,
3682 ++ &((const struct sockaddr_in *)sa)->sin_addr, sizeof(struct in_addr)) == 0);
3683 ++ break;
3684 ++ case AF_INET6:
3685 ++ res = (memcmp(totem_ip->addr,
3686 ++ &((const struct sockaddr_in6 *)sa)->sin6_addr, sizeof(struct in6_addr)) == 0);
3687 ++ break;
3688 ++ default:
3689 ++ assert(0);
3690 ++ }
3691 ++
3692 ++ return (res);
3693 ++}
3694 ++
3695 + /* Copy a totem_ip_address */
3696 + void totemip_copy(struct totem_ip_address *addr1,
3697 + const struct totem_ip_address *addr2)
3698 +diff --git a/exec/totemudpu.c b/exec/totemudpu.c
3699 +index 252962d..914a328 100644
3700 +--- a/exec/totemudpu.c
3701 ++++ b/exec/totemudpu.c
3702 +@@ -444,6 +444,32 @@ int totemudpu_finalize (
3703 + return (res);
3704 + }
3705 +
3706 ++static struct totemudpu_member *find_member_by_sockaddr(
3707 ++ const void *udpu_context,
3708 ++ const struct sockaddr *sa)
3709 ++{
3710 ++ struct qb_list_head *list;
3711 ++ struct totemudpu_member *member;
3712 ++ struct totemudpu_member *res_member;
3713 ++ const struct totemudpu_instance *instance = (const struct totemudpu_instance *)udpu_context;
3714 ++
3715 ++ res_member = NULL;
3716 ++
3717 ++ qb_list_for_each(list, &(instance->member_list)) {
3718 ++ member = qb_list_entry (list,
3719 ++ struct totemudpu_member,
3720 ++ list);
3721 ++
3722 ++ if (totemip_sa_equal(&member->member, sa)) {
3723 ++ res_member = member;
3724 ++ break ;
3725 ++ }
3726 ++ }
3727 ++
3728 ++ return (res_member);
3729 ++}
3730 ++
3731 ++
3732 + static int net_deliver_fn (
3733 + int fd,
3734 + int revents,
3735 +@@ -513,6 +539,14 @@ static int net_deliver_fn (
3736 + return (0);
3737 + }
3738 +
3739 ++ if (instance->totem_config->block_unlisted_ips &&
3740 ++ find_member_by_sockaddr(instance, (const struct sockaddr *)&system_from) == NULL) {
3741 ++ log_printf(instance->totemudpu_log_level_debug, "Packet rejected from %s",
3742 ++ totemip_sa_print((const struct sockaddr *)&system_from));
3743 ++
3744 ++ return (0);
3745 ++ }
3746 ++
3747 + iovec->iov_len = bytes_received;
3748 +
3749 + /*
3750 +diff --git a/man/corosync.conf.5 b/man/corosync.conf.5
3751 +index 674179d..953c830 100644
3752 +--- a/man/corosync.conf.5
3753 ++++ b/man/corosync.conf.5
3754 +@@ -32,7 +32,7 @@
3755 + .\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3756 + .\" * THE POSSIBILITY OF SUCH DAMAGE.
3757 + .\" */
3758 +-.TH COROSYNC_CONF 5 2019-04-11 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
3759 ++.TH COROSYNC_CONF 5 2019-05-24 "corosync Man Page" "Corosync Cluster Engine Programmer's Manual"
3760 + .SH NAME
3761 + corosync.conf - corosync executive configuration file
3762 +
3763 +@@ -571,6 +571,14 @@ knet_enable_access_lists
3764 + Allow knet to drop packets from IP addresses that are not known to corosync.
3765 + Value is 0 (off) and 1 (on). Default: 0.
3766 +
3767 ++.TP
3768 ++block_unlisted_ips
3769 ++Allow UDPU to drop packets from IP addresses that are not known
3770 ++(nodes which don't exist in the nodelist) to corosync.
3771 ++Value is yes or no.
3772 ++
3773 ++The default value is yes.
3774 ++
3775 + .PP
3776 + Within the
3777 + .B logging
3778 diff --git a/debian/patches/vqsim-Check-length-of-copied-optarg.patch b/debian/patches/vqsim-Check-length-of-copied-optarg.patch
3779 new file mode 100644
3780 index 00000000..ef2afb67
3781 --- /dev/null
3782 +++ b/debian/patches/vqsim-Check-length-of-copied-optarg.patch
3783 @@ -0,0 +1,37 @@
3784 +From: Jan Friesse <jfriesse@redhat.com>
3785 +Date: Tue, 11 Jun 2019 15:30:00 +0200
3786 +Subject: vqsim: Check length of copied optarg
3787 +
3788 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3789 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3790 +(cherry picked from commit 0390200dd427d1d3e75bba8584dbfbb794b52b49)
3791 +---
3792 + vqsim/vqmain.c | 8 ++++++--
3793 + 1 file changed, 6 insertions(+), 2 deletions(-)
3794 +
3795 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
3796 +index 16f7714..25d0fad 100644
3797 +--- a/vqsim/vqmain.c
3798 ++++ b/vqsim/vqmain.c
3799 +@@ -759,7 +759,11 @@ int main(int argc, char **argv)
3800 + while ((ch = getopt (argc, argv, "c:o:nh")) != EOF) {
3801 + switch (ch) {
3802 + case 'c':
3803 +- strncpy(corosync_config_file, optarg, sizeof(corosync_config_file));
3804 ++ if (strlen(optarg) >= sizeof(sizeof(corosync_config_file) - 1)) {
3805 ++ fprintf(stderr, "Corosync config file path too long\n");
3806 ++ exit(1);
3807 ++ }
3808 ++ strncpy(corosync_config_file, optarg, sizeof(corosync_config_file) - 1);
3809 + break;
3810 + case 'o':
3811 + output_file_name = optarg;
3812 +@@ -777,7 +781,7 @@ int main(int argc, char **argv)
3813 + output_file = fopen(output_file_name, "w");
3814 + if (!output_file) {
3815 + fprintf(stderr, "Unable to open %s for output: %s\n", output_file_name, strerror(errno));
3816 +- exit(-1);
3817 ++ exit(3);
3818 + }
3819 + }
3820 + else {
3821 diff --git a/debian/patches/vqsim-Check-length-of-received-message.patch b/debian/patches/vqsim-Check-length-of-received-message.patch
3822 new file mode 100644
3823 index 00000000..a4d54327
3824 --- /dev/null
3825 +++ b/debian/patches/vqsim-Check-length-of-received-message.patch
3826 @@ -0,0 +1,42 @@
3827 +From: Jan Friesse <jfriesse@redhat.com>
3828 +Date: Tue, 11 Jun 2019 14:48:41 +0200
3829 +Subject: vqsim: Check length of received message
3830 +
3831 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3832 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3833 +(cherry picked from commit 7267149e050cc8963eb38c7a31bb26c84d1f2338)
3834 +---
3835 + vqsim/vqmain.c | 16 +++++++++++++---
3836 + 1 file changed, 13 insertions(+), 3 deletions(-)
3837 +
3838 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
3839 +index aaba512..98729b9 100644
3840 +--- a/vqsim/vqmain.c
3841 ++++ b/vqsim/vqmain.c
3842 +@@ -222,13 +222,23 @@ static int vq_parent_read_fn(int32_t fd, int32_t revents, void *data)
3843 + msglen = read(fd, msgbuf, sizeof(msgbuf));
3844 + if (msglen < 0) {
3845 + perror("read failed");
3846 +- }
3847 +-
3848 +- if (msglen > 0) {
3849 ++ } else if (msglen < sizeof(*msg)) {
3850 ++ fprintf(stderr, "Received message is too short\n");
3851 ++ } else {
3852 + msg = (void*)msgbuf;
3853 + switch (msg->type) {
3854 + case VQMSG_QUORUM:
3855 + qmsg = (void*)msgbuf;
3856 ++ /*
3857 ++ * Check length of message.
3858 ++ * SOCK_SEQPACKET is used so this check is not strictly needed.
3859 ++ */
3860 ++ if (msglen < sizeof(*qmsg) ||
3861 ++ qmsg->view_list_entries > MAX_NODES ||
3862 ++ msglen < sizeof(*qmsg) + sizeof(qmsg->view_list[0]) * qmsg->view_list_entries) {
3863 ++ fprintf(stderr, "Received quorum message is too short or corrupted\n");
3864 ++ return (0);
3865 ++ }
3866 + save_quorum_state(vqn, qmsg);
3867 + if (!sync_cmds) {
3868 + print_quorum_state(vqn);
3869 diff --git a/debian/patches/vqsim-Check-result-of-icmap_set_uint32.patch b/debian/patches/vqsim-Check-result-of-icmap_set_uint32.patch
3870 new file mode 100644
3871 index 00000000..25690b75
3872 --- /dev/null
3873 +++ b/debian/patches/vqsim-Check-result-of-icmap_set_uint32.patch
3874 @@ -0,0 +1,31 @@
3875 +From: Jan Friesse <jfriesse@redhat.com>
3876 +Date: Tue, 11 Jun 2019 15:26:29 +0200
3877 +Subject: vqsim: Check result of icmap_set_uint32
3878 +
3879 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3880 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3881 +(cherry picked from commit 1d8c1a4c9712517b24985941b8fac2d45eef4784)
3882 +---
3883 + vqsim/vqsim_vq_engine.c | 2 ++
3884 + 1 file changed, 2 insertions(+)
3885 +
3886 +diff --git a/vqsim/vqsim_vq_engine.c b/vqsim/vqsim_vq_engine.c
3887 +index eb35d35..b8460f3 100644
3888 +--- a/vqsim/vqsim_vq_engine.c
3889 ++++ b/vqsim/vqsim_vq_engine.c
3890 +@@ -208,6 +208,7 @@ static void set_local_node_pos(struct corosync_api_v1 *api)
3891 + if (nodeid == our_nodeid) {
3892 + found = 1;
3893 + res = icmap_set_uint32("nodelist.local_node_pos", node_pos);
3894 ++ assert(res == CS_OK);
3895 + }
3896 + }
3897 + }
3898 +@@ -217,6 +218,7 @@ static void set_local_node_pos(struct corosync_api_v1 *api)
3899 + * first node in corosync.conf
3900 + */
3901 + res = icmap_set_uint32("nodelist.local_node_pos", 0);
3902 ++ assert(res == CS_OK);
3903 + }
3904 + }
3905 +
3906 diff --git a/debian/patches/vqsim-Check-write-result.patch b/debian/patches/vqsim-Check-write-result.patch
3907 new file mode 100644
3908 index 00000000..303f661c
3909 --- /dev/null
3910 +++ b/debian/patches/vqsim-Check-write-result.patch
3911 @@ -0,0 +1,33 @@
3912 +From: Jan Friesse <jfriesse@redhat.com>
3913 +Date: Tue, 11 Jun 2019 14:46:34 +0200
3914 +Subject: vqsim: Check write result
3915 +
3916 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3917 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3918 +(cherry picked from commit e953cfeb873f495cd9c59ba999be2b103363718b)
3919 +---
3920 + vqsim/vqmain.c | 8 +++++++-
3921 + 1 file changed, 7 insertions(+), 1 deletion(-)
3922 +
3923 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
3924 +index 0eca43c..aaba512 100644
3925 +--- a/vqsim/vqmain.c
3926 ++++ b/vqsim/vqmain.c
3927 +@@ -138,10 +138,16 @@ static void print_quorum_state(struct vq_node *node)
3928 + static void propogate_vq_message(struct vq_node *vqn, const char *msg, int len)
3929 + {
3930 + struct vq_node *other_vqn;
3931 ++ ssize_t write_res;
3932 +
3933 + /* Send it to everyone in that node's partition (including itself) */
3934 + TAILQ_FOREACH(other_vqn, &vqn->partition->nodelist, entries) {
3935 +- write(other_vqn->fd, msg, len);
3936 ++ write_res = write(other_vqn->fd, msg, len);
3937 ++ /*
3938 ++ * Read counterpart is not ready for receiving non-complete message so
3939 ++ * ensure all required information was send.
3940 ++ */
3941 ++ assert(write_res == len);
3942 + }
3943 + }
3944 +
3945 diff --git a/debian/patches/vqsim-Do-not-access-unitialized-argv-0.patch b/debian/patches/vqsim-Do-not-access-unitialized-argv-0.patch
3946 new file mode 100644
3947 index 00000000..04973dff
3948 --- /dev/null
3949 +++ b/debian/patches/vqsim-Do-not-access-unitialized-argv-0.patch
3950 @@ -0,0 +1,24 @@
3951 +From: Jan Friesse <jfriesse@redhat.com>
3952 +Date: Tue, 11 Jun 2019 11:04:48 +0200
3953 +Subject: vqsim: Do not access unitialized argv[0]
3954 +
3955 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
3956 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
3957 +(cherry picked from commit 1af23e9c2dd3830beb2cd16277a44ae50ad483db)
3958 +---
3959 + vqsim/parser.c | 2 +-
3960 + 1 file changed, 1 insertion(+), 1 deletion(-)
3961 +
3962 +diff --git a/vqsim/parser.c b/vqsim/parser.c
3963 +index d13e678..2857184 100644
3964 +--- a/vqsim/parser.c
3965 ++++ b/vqsim/parser.c
3966 +@@ -196,7 +196,7 @@ void parse_input_command(char *rl_cmd)
3967 + }
3968 +
3969 + /* Ignore null commands */
3970 +- if (strlen(argv[0]) == 0) {
3971 ++ if (argc < 1 || strlen(argv[0]) == 0) {
3972 + free(cmd);
3973 + resume_kb_input(0);
3974 + return;
3975 diff --git a/debian/patches/vqsim-Enhance-vqsim.patch b/debian/patches/vqsim-Enhance-vqsim.patch
3976 new file mode 100644
3977 index 00000000..7e95761f
3978 --- /dev/null
3979 +++ b/debian/patches/vqsim-Enhance-vqsim.patch
3980 @@ -0,0 +1,1155 @@
3981 +From: Christine Caulfield <ccaulfie@redhat.com>
3982 +Date: Fri, 26 Apr 2019 10:54:32 +0100
3983 +Subject: vqsim: Enhance vqsim
3984 +
3985 +1. Enable scripting of vqsim and add man page
3986 +
3987 +I've added a 'sleep' command to help with scripting as well as
3988 +documentation on how to do it.
3989 +
3990 +2. Make 'sync' operation much more robust and useful
3991 +
3992 +Refactored a lot of code to make sure that in sync mode the
3993 +prompt appears at the 'right' time. What we do is wait for all
3994 +of the nodes in all partitions to have the same ring_id. If this
3995 +doesn't happen then the timeout will fire as before.
3996 +
3997 +3. Rename binary to corosync-vqsim and add a sub-package for it
3998 +
3999 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
4000 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
4001 +(cherry picked from commit c3d69712c614deea688b7cfe0975976ecca60a2d)
4002 +---
4003 + configure.ac | 1 +
4004 + man/Makefile.am | 4 +
4005 + vqsim/Makefile.am | 22 ++--
4006 + vqsim/vqsim.h | 82 +++++++++++++++
4007 + corosync.spec.in | 26 +++++
4008 + vqsim/parser.c | 141 ++++++++++++++++++++-----
4009 + vqsim/vqmain.c | 274 +++++++++++++++++++++++++++++++++---------------
4010 + vqsim/vqsim_vq_engine.c | 12 ++-
4011 + man/corosync-vqsim.8 | 94 +++++++++++++++++
4012 + 9 files changed, 533 insertions(+), 123 deletions(-)
4013 + create mode 100644 vqsim/vqsim.h
4014 + create mode 100644 man/corosync-vqsim.8
4015 +
4016 +diff --git a/configure.ac b/configure.ac
4017 +index 14c0e17..a27ba95 100644
4018 +--- a/configure.ac
4019 ++++ b/configure.ac
4020 +@@ -470,6 +470,7 @@ if test "x${enable_vqsim}" = xyes; then
4021 + [],
4022 + AC_MSG_WARN([vqsim will lack readline support]))
4023 + PACKAGE_FEATURES="$PACKAGE_FEATURES vqsim"
4024 ++ WITH_LIST="$WITH_LIST --with vqsim"
4025 + fi
4026 + AM_CONDITIONAL(VQSIM_READLINE, [test "x${ac_cv_header_readline_readline_h}" = xyes])
4027 +
4028 +diff --git a/man/Makefile.am b/man/Makefile.am
4029 +index d1b7f94..8e4eda3 100644
4030 +--- a/man/Makefile.am
4031 ++++ b/man/Makefile.am
4032 +@@ -139,6 +139,10 @@ dist_man_MANS = corosync.conf.5 \
4033 + cmap_overview.3 \
4034 + cmap_keys.8
4035 +
4036 ++if BUILD_VQSIM
4037 ++dist_man_MANS += corosync-vqsim.8
4038 ++endif
4039 ++
4040 + if INSTALL_XMLCONF
4041 + dist_man_MANS += $(xml_man)
4042 + endif
4043 +diff --git a/vqsim/Makefile.am b/vqsim/Makefile.am
4044 +index 2a76544..9a7fbf6 100644
4045 +--- a/vqsim/Makefile.am
4046 ++++ b/vqsim/Makefile.am
4047 +@@ -30,23 +30,25 @@
4048 + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
4049 + # THE POSSIBILITY OF SUCH DAMAGE.
4050 +
4051 +-MAINTAINERCLEANFILES = Makefile.in
4052 ++MAINTAINERCLEANFILES = Makefile.in
4053 +
4054 + if BUILD_VQSIM
4055 +
4056 +-noinst_PROGRAMS = vqsim
4057 ++noinst_HEADERS = vqsim.h
4058 +
4059 +-vqsim_LDADD = $(top_builddir)/common_lib/libcorosync_common.la \
4060 +- ../exec/corosync-votequorum.o ../exec/corosync-icmap.o ../exec/corosync-logsys.o \
4061 +- ../exec/corosync-coroparse.o ../exec/corosync-logconfig.o \
4062 +- ../exec/corosync-util.o \
4063 +- $(LIBQB_LIBS)
4064 ++bin_PROGRAMS = corosync-vqsim
4065 ++
4066 ++corosync_vqsim_LDADD = $(top_builddir)/common_lib/libcorosync_common.la \
4067 ++ ../exec/corosync-votequorum.o ../exec/corosync-icmap.o \
4068 ++ ../exec/corosync-coroparse.o ../exec/corosync-logconfig.o \
4069 ++ ../exec/corosync-util.o ../exec/corosync-logsys.o \
4070 ++ $(LIBQB_LIBS)
4071 + if VQSIM_READLINE
4072 +-vqsim_LDADD += -lreadline
4073 ++corosync_vqsim_LDADD += -lreadline
4074 + endif
4075 +
4076 +-vqsim_DEPENDENCIES = $(top_builddir)/common_lib/libcorosync_common.la
4077 ++corosync_vqsim_DEPENDENCIES = $(top_builddir)/common_lib/libcorosync_common.la
4078 +
4079 +-vqsim_SOURCES = vqmain.c parser.c vq_object.c vqsim_vq_engine.c
4080 ++corosync_vqsim_SOURCES = vqmain.c parser.c vq_object.c vqsim_vq_engine.c
4081 +
4082 + endif
4083 +diff --git a/vqsim/vqsim.h b/vqsim/vqsim.h
4084 +new file mode 100644
4085 +index 0000000..0c4c973
4086 +--- /dev/null
4087 ++++ b/vqsim/vqsim.h
4088 +@@ -0,0 +1,82 @@
4089 ++
4090 ++typedef enum {VQMSG_QUIT=1,
4091 ++ VQMSG_SYNC, /* set nodelist */
4092 ++ VQMSG_QUORUM, /* quorum state of this 'node' */
4093 ++ VQMSG_EXEC, /* message for exec_handler */
4094 ++ VQMSG_QDEVICE, /* quorum device enable/disable */
4095 ++ VQMSG_QUORUMQUIT, /* quit if you don't have quorum */
4096 ++} vqsim_msg_type_t;
4097 ++
4098 ++typedef struct vq_instance *vq_object_t;
4099 ++
4100 ++struct vqsim_msg_header
4101 ++{
4102 ++ vqsim_msg_type_t type;
4103 ++ int from_nodeid;
4104 ++ int param;
4105 ++};
4106 ++
4107 ++/* This is the sync sent from the controller process */
4108 ++struct vqsim_sync_msg
4109 ++{
4110 ++ struct vqsim_msg_header header;
4111 ++ struct memb_ring_id ring_id;
4112 ++ size_t view_list_entries;
4113 ++ unsigned int view_list[];
4114 ++};
4115 ++
4116 ++/* This is just info sent from each VQ instance */
4117 ++struct vqsim_quorum_msg
4118 ++{
4119 ++ struct vqsim_msg_header header;
4120 ++ int quorate;
4121 ++ struct memb_ring_id ring_id;
4122 ++ size_t view_list_entries;
4123 ++ unsigned int view_list[];
4124 ++};
4125 ++
4126 ++struct vqsim_exec_msg
4127 ++{
4128 ++ struct vqsim_msg_header header;
4129 ++ char execmsg[];
4130 ++};
4131 ++
4132 ++struct vqsim_lib_msg
4133 ++{
4134 ++ struct vqsim_msg_header header;
4135 ++ char libmsg[];
4136 ++};
4137 ++
4138 ++#define MAX_NODES 1024
4139 ++#define MAX_PARTITIONS 16
4140 ++
4141 ++/* In vq_object.c */
4142 ++vq_object_t vq_create_instance(qb_loop_t *poll_loop, int nodeid);
4143 ++void vq_quit(vq_object_t instance);
4144 ++int vq_set_nodelist(vq_object_t instance, struct memb_ring_id *ring_id, int *nodeids, int nodeids_entries);
4145 ++int vq_get_parent_fd(vq_object_t instance);
4146 ++int vq_set_qdevice(vq_object_t instance, struct memb_ring_id *ring_id, int onoff);
4147 ++int vq_quit_if_inquorate(vq_object_t instance);
4148 ++pid_t vq_get_pid(vq_object_t instance);
4149 ++
4150 ++/* in vqsim_vq_engine.c - effectively the constructor */
4151 ++int fork_new_instance(int nodeid, int *vq_sock, pid_t *child_pid);
4152 ++
4153 ++/* In parser.c */
4154 ++void parse_input_command(char *cmd);
4155 ++
4156 ++/* These are in vqmain.c */
4157 ++int cmd_stop_node(int nodeid);
4158 ++void cmd_stop_all_nodes(void);
4159 ++int cmd_start_new_node(int nodeid, int partition);
4160 ++void cmd_set_autofence(int onoff);
4161 ++void cmd_set_sync(int onoff);
4162 ++void cmd_set_assert(int onoff);
4163 ++void cmd_move_nodes(int partition, int num_nodes, int *nodelist);
4164 ++void cmd_join_partitions(int part1, int part2);
4165 ++void cmd_update_all_partitions(int newring);
4166 ++void cmd_qdevice_poll(int nodeid, int onoff);
4167 ++void cmd_show_node_states(void);
4168 ++void cmd_set_timeout(uint64_t seconds);
4169 ++void cmd_start_sync_command(void);
4170 ++void resume_kb_input(int show_state);
4171 +diff --git a/corosync.spec.in b/corosync.spec.in
4172 +index 07c004c..8af686e 100644
4173 +--- a/corosync.spec.in
4174 ++++ b/corosync.spec.in
4175 +@@ -12,6 +12,7 @@
4176 + %bcond_with systemd
4177 + %bcond_with xmlconf
4178 + %bcond_with nozzle
4179 ++%bcond_with vqsim
4180 + %bcond_with runautogen
4181 +
4182 + %global gitver %{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}
4183 +@@ -70,6 +71,9 @@ Requires(preun): /sbin/chkconfig
4184 + %if %{with xmlconf}
4185 + Requires: libxslt
4186 + %endif
4187 ++%if %{with vqsim}
4188 ++BuildRequires: readline-devel
4189 ++%endif
4190 +
4191 + %prep
4192 + %setup -q -n %{name}-%{version}%{?gittarver}
4193 +@@ -100,6 +104,9 @@ Requires: libxslt
4194 + %endif
4195 + %if %{with nozzle}
4196 + --enable-nozzle \
4197 ++%endif
4198 ++%if %{with vqsim}
4199 ++ --enable-vqsim \
4200 + %endif
4201 + --with-initddir=%{_initrddir} \
4202 + --with-systemddir=%{_unitdir} \
4203 +@@ -266,6 +273,25 @@ The Corosync Cluster Engine APIs.
4204 + %{_mandir}/man3/sam_*3*
4205 + %{_mandir}/man3/cmap_*3*
4206 +
4207 ++%if %{with vqsim}
4208 ++%package -n corosync-vqsim
4209 ++Summary: The Corosync Cluster Engine - Votequorum Simulator
4210 ++Requires: corosynclib%{?_isa} = %{version}-%{release}
4211 ++Requires: pkgconfig
4212 ++
4213 ++%description -n corosync-vqsim
4214 ++A command-line simulator for the corosync votequorum subsystem.
4215 ++It uses the same code as the corosync quorum system but forks
4216 ++them into subprocesses to simulate nodes.
4217 ++Nodes can be added and removed as well as partitioned (to simulate
4218 ++network splits)
4219 ++
4220 ++%files -n corosync-vqsim
4221 ++%doc LICENSE
4222 ++%{_bindir}/corosync-vqsim
4223 ++%{_mandir}/man8/corosync-vqsim.8*
4224 ++%endif
4225 ++
4226 + %changelog
4227 + * @date@ Autotools generated version <nobody@nowhere.org> - @version@-1-@numcomm@.@alphatag@.@dirty@
4228 + - Autotools generated version
4229 +diff --git a/vqsim/parser.c b/vqsim/parser.c
4230 +index 2fc1043..d13e678 100644
4231 +--- a/vqsim/parser.c
4232 ++++ b/vqsim/parser.c
4233 +@@ -30,21 +30,31 @@ static void do_usage(void)
4234 + printf(" Enable quorum device in specified nodes\n");
4235 + printf("autofence on|off\n");
4236 + printf(" automatically 'down' nodes on inquorate side on netsplit\n");
4237 ++ printf("timeout <n> (default 250)\n");
4238 ++ printf(" Wait a maximum of <n> milli-seconds for the next command to complete.\n");
4239 ++ printf("sync on|off (default on)\n");
4240 ++ printf(" enable/disable synchronous execution of commands (wait for completion)\n");
4241 ++ printf("assert on|off (default off)\n");
4242 ++ printf(" Abort the simulation run if a timeout expires\n");
4243 + printf("show Show current nodes status\n");
4244 + printf("exit\n\n");
4245 + }
4246 +
4247 +
4248 +-typedef void (*cmd_routine_t)(int argc, char **argv);
4249 ++/* Commands return 0 if they return immediately, >1 if we are waiting for replies from nodes */
4250 ++typedef int (*cmd_routine_t)(int argc, char **argv);
4251 +
4252 +-static void run_up_cmd(int argc, char **argv);
4253 +-static void run_down_cmd(int argc, char **argv);
4254 +-static void run_join_cmd(int argc, char **argv);
4255 +-static void run_move_cmd(int argc, char **argv);
4256 +-static void run_exit_cmd(int argc, char **argv);
4257 +-static void run_show_cmd(int argc, char **argv);
4258 +-static void run_autofence_cmd(int argc, char **argv);
4259 +-static void run_qdevice_cmd(int argc, char **argv);
4260 ++static int run_up_cmd(int argc, char **argv);
4261 ++static int run_down_cmd(int argc, char **argv);
4262 ++static int run_join_cmd(int argc, char **argv);
4263 ++static int run_move_cmd(int argc, char **argv);
4264 ++static int run_exit_cmd(int argc, char **argv);
4265 ++static int run_show_cmd(int argc, char **argv);
4266 ++static int run_timeout_cmd(int argc, char **argv);
4267 ++static int run_assert_cmd(int argc, char **argv);
4268 ++static int run_autofence_cmd(int argc, char **argv);
4269 ++static int run_qdevice_cmd(int argc, char **argv);
4270 ++static int run_sync_cmd(int argc, char **argv);
4271 +
4272 + static struct cmd_list_struct {
4273 + const char *cmd;
4274 +@@ -59,6 +69,9 @@ static struct cmd_list_struct {
4275 + { "autofence", 1, run_autofence_cmd},
4276 + { "qdevice", 1, run_qdevice_cmd},
4277 + { "show", 0, run_show_cmd},
4278 ++ { "timeout", 1, run_timeout_cmd},
4279 ++ { "sync", 1, run_sync_cmd},
4280 ++ { "assert", 1, run_assert_cmd},
4281 + { "exit", 0, run_exit_cmd},
4282 + { "quit", 0, run_exit_cmd},
4283 + { "q", 0, run_exit_cmd},
4284 +@@ -135,11 +148,16 @@ void parse_input_command(char *rl_cmd)
4285 + int last_arg_start = 0;
4286 + int last_was_space = 0;
4287 + int len;
4288 ++ int ret = 0;
4289 + char *cmd;
4290 +
4291 + /* ^D quits */
4292 + if (rl_cmd == NULL) {
4293 +- run_exit_cmd(0, NULL);
4294 ++ (void)run_exit_cmd(0, NULL);
4295 ++ }
4296 ++ /* '#' starts a comment */
4297 ++ if (rl_cmd[0] == '#') {
4298 ++ return;
4299 + }
4300 +
4301 + cmd = strdup(rl_cmd);
4302 +@@ -180,7 +198,8 @@ void parse_input_command(char *rl_cmd)
4303 + /* Ignore null commands */
4304 + if (strlen(argv[0]) == 0) {
4305 + free(cmd);
4306 +- return;
4307 ++ resume_kb_input(0);
4308 ++ return;
4309 + }
4310 + #ifdef HAVE_READLINE_HISTORY_H
4311 + add_history(rl_cmd);
4312 +@@ -193,7 +212,7 @@ void parse_input_command(char *rl_cmd)
4313 + if (argc < cmd_list[i].min_args) {
4314 + break;
4315 + }
4316 +- cmd_list[i].cmd_runner(argc, argv);
4317 ++ ret = cmd_list[i].cmd_runner(argc, argv);
4318 + valid_cmd = 1;
4319 + }
4320 + }
4321 +@@ -201,64 +220,86 @@ void parse_input_command(char *rl_cmd)
4322 + do_usage();
4323 + }
4324 + free(cmd);
4325 ++
4326 ++ /* ret==0 means we can return immediately to command-line input */
4327 ++ if (ret == 0) {
4328 ++ resume_kb_input(ret);
4329 ++ }
4330 + }
4331 +
4332 +
4333 +
4334 +-static void run_up_cmd(int argc, char **argv)
4335 ++static int run_up_cmd(int argc, char **argv)
4336 + {
4337 + int partition;
4338 + int num_nodes;
4339 + int *nodelist;
4340 + int i,j;
4341 ++ int succeeded = 0;
4342 +
4343 + if (argc <= 1) {
4344 +- return;
4345 ++ return 0;
4346 + }
4347 +
4348 ++ cmd_start_sync_command();
4349 ++
4350 + for (i=1; i<argc; i++) {
4351 + if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
4352 + for (j=0; j<num_nodes; j++) {
4353 +- cmd_start_new_node(nodelist[j], partition);
4354 ++ if (!cmd_start_new_node(nodelist[j], partition)) {
4355 ++ succeeded++;
4356 ++ }
4357 + }
4358 + free(nodelist);
4359 + }
4360 + }
4361 ++ return succeeded;
4362 + }
4363 +
4364 +-static void run_down_cmd(int argc, char **argv)
4365 ++static int run_down_cmd(int argc, char **argv)
4366 + {
4367 + int nodeid;
4368 + int i;
4369 ++ int succeeded = 0;
4370 ++
4371 ++ cmd_start_sync_command();
4372 +
4373 + for (i=1; i<argc; i++) {
4374 + nodeid = atoi(argv[1]);
4375 +- cmd_stop_node(nodeid);
4376 ++ if (!cmd_stop_node(nodeid)) {
4377 ++ succeeded++;
4378 ++ }
4379 + }
4380 ++ return succeeded;
4381 + }
4382 +
4383 +-static void run_join_cmd(int argc, char **argv)
4384 ++static int run_join_cmd(int argc, char **argv)
4385 + {
4386 + int i;
4387 +
4388 + if (argc < 2) {
4389 + printf("join needs at least two partition numbers\n");
4390 +- return;
4391 ++ return 0;
4392 + }
4393 +
4394 ++ cmd_start_sync_command();
4395 ++
4396 + for (i=2; i<argc; i++) {
4397 + cmd_join_partitions(atoi(argv[1]), atoi(argv[i]));
4398 + }
4399 + cmd_update_all_partitions(1);
4400 ++ return 1;
4401 + }
4402 +
4403 +-static void run_move_cmd(int argc, char **argv)
4404 ++static int run_move_cmd(int argc, char **argv)
4405 + {
4406 + int i;
4407 + int partition;
4408 + int num_nodes;
4409 + int *nodelist;
4410 +
4411 ++ cmd_start_sync_command();
4412 ++
4413 + for (i=1; i<argc; i++) {
4414 + if (parse_partition_nodelist(argv[i], &partition, &num_nodes, &nodelist) == 0) {
4415 + cmd_move_nodes(partition, num_nodes, nodelist);
4416 +@@ -266,9 +307,10 @@ static void run_move_cmd(int argc, char **argv)
4417 + }
4418 + }
4419 + cmd_update_all_partitions(1);
4420 ++ return 1;
4421 + }
4422 +
4423 +-static void run_autofence_cmd(int argc, char **argv)
4424 ++static int run_autofence_cmd(int argc, char **argv)
4425 + {
4426 + int onoff = -1;
4427 +
4428 +@@ -284,9 +326,10 @@ static void run_autofence_cmd(int argc, char **argv)
4429 + else {
4430 + cmd_set_autofence(onoff);
4431 + }
4432 ++ return 0;
4433 + }
4434 +
4435 +-static void run_qdevice_cmd(int argc, char **argv)
4436 ++static int run_qdevice_cmd(int argc, char **argv)
4437 + {
4438 + int i,j;
4439 + int partition;
4440 +@@ -303,7 +346,7 @@ static void run_qdevice_cmd(int argc, char **argv)
4441 +
4442 + if (onoff == -1) {
4443 + fprintf(stderr, "ERR: qdevice should be 'on' or 'off'\n");
4444 +- return;
4445 ++ return 0;
4446 + }
4447 +
4448 + for (i=2; i<argc; i++) {
4449 +@@ -315,17 +358,61 @@ static void run_qdevice_cmd(int argc, char **argv)
4450 + }
4451 + }
4452 + cmd_update_all_partitions(0);
4453 ++ return 0;
4454 + }
4455 +
4456 +-static void run_show_cmd(int argc, char **argv)
4457 ++static int run_show_cmd(int argc, char **argv)
4458 + {
4459 + cmd_show_node_states();
4460 ++ return 0;
4461 + }
4462 +
4463 +-static void run_exit_cmd(int argc, char **argv)
4464 ++static int run_timeout_cmd(int argc, char **argv)
4465 + {
4466 +- cmd_stop_all_nodes();
4467 +- exit(0);
4468 ++ cmd_set_timeout(atol(argv[1]));
4469 ++ return 0;
4470 ++}
4471 ++
4472 ++static int run_sync_cmd(int argc, char **argv)
4473 ++{
4474 ++ int onoff = -1;
4475 ++
4476 ++ if (strcasecmp(argv[1], "on") == 0) {
4477 ++ onoff = 1;
4478 ++ }
4479 ++ if (strcasecmp(argv[1], "off") == 0) {
4480 ++ onoff = 0;
4481 ++ }
4482 ++ if (onoff == -1) {
4483 ++ fprintf(stderr, "ERR: sync value must be 'on' or 'off'\n");
4484 ++ }
4485 ++ else {
4486 ++ cmd_set_sync(onoff);
4487 ++ }
4488 ++ return 0;
4489 + }
4490 +
4491 ++static int run_assert_cmd(int argc, char **argv)
4492 ++{
4493 ++ int onoff = -1;
4494 +
4495 ++ if (strcasecmp(argv[1], "on") == 0) {
4496 ++ onoff = 1;
4497 ++ }
4498 ++ if (strcasecmp(argv[1], "off") == 0) {
4499 ++ onoff = 0;
4500 ++ }
4501 ++ if (onoff == -1) {
4502 ++ fprintf(stderr, "ERR: assert value must be 'on' or 'off'\n");
4503 ++ }
4504 ++ else {
4505 ++ cmd_set_assert(onoff);
4506 ++ }
4507 ++ return 0;
4508 ++}
4509 ++
4510 ++static int run_exit_cmd(int argc, char **argv)
4511 ++{
4512 ++ cmd_stop_all_nodes();
4513 ++ exit(0);
4514 ++}
4515 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
4516 +index c3a1327..0eca43c 100644
4517 +--- a/vqsim/vqmain.c
4518 ++++ b/vqsim/vqmain.c
4519 +@@ -25,6 +25,7 @@
4520 + /* Easier than including the config file with a ton of conflicting dependencies */
4521 + extern int coroparse_configparse (icmap_map_t config_map, const char **error_string);
4522 + extern int corosync_log_config_read (const char **error_string);
4523 ++static int stdin_read_fn(int32_t fd, int32_t revents, void *data);
4524 +
4525 + /* 'Keep the compiler happy' time */
4526 + const char *corosync_get_config_file(void);
4527 +@@ -56,21 +57,22 @@ static qb_loop_t *poll_loop;
4528 + static int autofence;
4529 + static int check_for_quorum;
4530 + static FILE *output_file;
4531 +-static int nosync;
4532 ++static int sync_cmds = 1;
4533 + static qb_loop_timer_handle kb_timer;
4534 +-static ssize_t wait_count;
4535 +-static ssize_t wait_count_to_unblock;
4536 ++static int waiting_for_sync = 0;
4537 ++static int is_tty;
4538 ++static int assert_on_timeout;
4539 ++static uint64_t command_timeout = 250000000L;
4540 +
4541 + static struct vq_node *find_by_pid(pid_t pid);
4542 + static void send_partition_to_nodes(struct vq_partition *partition, int newring);
4543 +-static void start_kb_input(void);
4544 + static void start_kb_input_timeout(void *data);
4545 ++static void finish_wait_timeout(void *data);
4546 +
4547 + #ifndef HAVE_READLINE_READLINE_H
4548 + #define INPUT_BUF_SIZE 1024
4549 + static char input_buf[INPUT_BUF_SIZE];
4550 + static size_t input_buf_term = 0;
4551 +-static int is_tty;
4552 + #endif
4553 +
4554 + /* 'Keep the compiler happy' time */
4555 +@@ -78,7 +80,6 @@ static char corosync_config_file[PATH_MAX + 1] = COROSYSCONFDIR "/corosync.conf"
4556 +
4557 + const char *corosync_get_config_file(void)
4558 + {
4559 +-
4560 + return (corosync_config_file);
4561 + }
4562 +
4563 +@@ -144,6 +145,65 @@ static void propogate_vq_message(struct vq_node *vqn, const char *msg, int len)
4564 + }
4565 + }
4566 +
4567 ++
4568 ++static void cmd_show_prompt_if_needed(void)
4569 ++{
4570 ++ qb_loop_timer_del(poll_loop, kb_timer);
4571 ++ if (is_tty) {
4572 ++ printf("vqsim> ");
4573 ++ fflush(stdout);
4574 ++ } else {
4575 ++ printf("#vqsim> ");
4576 ++ fflush(stdout);
4577 ++ }
4578 ++
4579 ++}
4580 ++
4581 ++void resume_kb_input(int show_status)
4582 ++{
4583 ++ /* If running synchronously, we don't display
4584 ++ the quorum messages as they come in. So run 'show' commamnd
4585 ++ */
4586 ++ if (show_status && waiting_for_sync) {
4587 ++ cmd_show_node_states();
4588 ++ }
4589 ++
4590 ++ waiting_for_sync = 0;
4591 ++
4592 ++ if (qb_loop_poll_add(poll_loop,
4593 ++ QB_LOOP_MED,
4594 ++ STDIN_FILENO,
4595 ++ POLLIN | POLLERR,
4596 ++ NULL,
4597 ++ stdin_read_fn)) {
4598 ++ if (errno != EEXIST) {
4599 ++ perror("qb_loop_poll_add1 returned error");
4600 ++ }
4601 ++ }
4602 ++ /* Always shows the prompt here, cos we cleared waiting_for_sync */
4603 ++ cmd_show_prompt_if_needed();
4604 ++}
4605 ++
4606 ++/* Return true (1) if all nodes in each partition have the same ring id, false(0) otherwise */
4607 ++static int all_nodes_consistent(void)
4608 ++{
4609 ++ int i;
4610 ++ struct vq_node *vqn;
4611 ++ struct memb_ring_id last_ring_id;
4612 ++
4613 ++ for (i=0; i<MAX_PARTITIONS; i++) {
4614 ++ memset(&last_ring_id, 0, sizeof(last_ring_id));
4615 ++ TAILQ_FOREACH(vqn, &partitions[i].nodelist, entries) {
4616 ++ if (last_ring_id.seq &&
4617 ++ last_ring_id.seq != vqn->last_ring_id.seq) {
4618 ++ return 0;
4619 ++ }
4620 ++ last_ring_id.seq = vqn->last_ring_id.seq;
4621 ++ }
4622 ++ }
4623 ++ return 1;
4624 ++}
4625 ++
4626 + static int vq_parent_read_fn(int32_t fd, int32_t revents, void *data)
4627 + {
4628 + char msgbuf[8192];
4629 +@@ -162,13 +222,18 @@ static int vq_parent_read_fn(int32_t fd, int32_t revents, void *data)
4630 + msg = (void*)msgbuf;
4631 + switch (msg->type) {
4632 + case VQMSG_QUORUM:
4633 +- if (!nosync && --wait_count_to_unblock <= 0)
4634 +- qb_loop_timer_del(poll_loop, kb_timer);
4635 + qmsg = (void*)msgbuf;
4636 + save_quorum_state(vqn, qmsg);
4637 +- print_quorum_state(vqn);
4638 +- if (!nosync && wait_count_to_unblock <= 0)
4639 +- start_kb_input();
4640 ++ if (!sync_cmds) {
4641 ++ print_quorum_state(vqn);
4642 ++ }
4643 ++
4644 ++ /* Have the partitions stabilised? */
4645 ++ if (sync_cmds && waiting_for_sync &&
4646 ++ all_nodes_consistent()) {
4647 ++ qb_loop_timer_del(poll_loop, kb_timer);
4648 ++ resume_kb_input(sync_cmds);
4649 ++ }
4650 + break;
4651 + case VQMSG_EXEC:
4652 + /* Message from votequorum, pass around the partition */
4653 +@@ -204,7 +269,7 @@ static int read_corosync_conf(void)
4654 + logsys_format_set(NULL);
4655 + res = coroparse_configparse(icmap_get_global_map(), &error_string);
4656 + if (res == -1) {
4657 +- log_printf (LOGSYS_LEVEL_INFO, "Error loading corosyc.conf %s", error_string);
4658 ++ log_printf (LOGSYS_LEVEL_INFO, "Error loading corosync.conf %s", error_string);
4659 + return -1;
4660 + }
4661 + else {
4662 +@@ -234,8 +299,6 @@ static void remove_node(struct vq_node *node)
4663 + TAILQ_REMOVE(&part->nodelist, node, entries);
4664 + free(node);
4665 +
4666 +- wait_count--;
4667 +-
4668 + /* Rebuild quorum */
4669 + send_partition_to_nodes(part, 1);
4670 + }
4671 +@@ -263,7 +326,7 @@ static int32_t sigchld_handler(int32_t sig, void *data)
4672 + sprintf(text, "(exit code %d)", WEXITSTATUS(status));
4673 + break;
4674 + }
4675 +- printf("%d:%02d Quit %s\n", vqn->partition->num, vqn->nodeid, exit_status);
4676 ++ printf("%d:%02d: Quit %s\n", vqn->partition->num, vqn->nodeid, exit_status);
4677 +
4678 + remove_node(vqn);
4679 + }
4680 +@@ -322,20 +385,24 @@ static void init_partitions(void)
4681 + }
4682 + }
4683 +
4684 ++static int nodes_in_partition(int part)
4685 ++{
4686 ++ struct vq_node *vqn;
4687 ++ int partnodes = 0;
4688 ++
4689 ++ TAILQ_FOREACH(vqn, &partitions[part].nodelist, entries) {
4690 ++ partnodes++;
4691 ++ }
4692 ++ return partnodes;
4693 ++}
4694 ++
4695 ++
4696 + static pid_t create_node(int nodeid, int partno)
4697 + {
4698 + struct vq_node *newvq;
4699 +
4700 + newvq = malloc(sizeof(struct vq_node));
4701 + if (newvq) {
4702 +- if (!nosync) {
4703 +- /* Number of expected "quorum" vq messages is a square
4704 +- of the total nodes count, so increment the node
4705 +- counter and set new square of this value as
4706 +- a "to observe" counter */
4707 +- wait_count++;
4708 +- wait_count_to_unblock = wait_count * wait_count;
4709 +- }
4710 + newvq->last_quorate = -1; /* mark "uninitialized" */
4711 + newvq->instance = vq_create_instance(poll_loop, nodeid);
4712 + if (!newvq->instance) {
4713 +@@ -439,29 +506,39 @@ static struct vq_node *find_by_pid(pid_t pid)
4714 + }
4715 +
4716 + /* Routines called from the parser */
4717 +-void cmd_start_new_node(int nodeid, int partition)
4718 ++
4719 ++
4720 ++/*
4721 ++ * The parser calls this before running a command where
4722 ++ * we might have to wait for a result to come back.
4723 ++ */
4724 ++void cmd_start_sync_command()
4725 ++{
4726 ++ if (sync_cmds) {
4727 ++ qb_loop_poll_del(poll_loop, STDIN_FILENO);
4728 ++ qb_loop_timer_add(poll_loop,
4729 ++ QB_LOOP_MED,
4730 ++ command_timeout,
4731 ++ NULL,
4732 ++ finish_wait_timeout,
4733 ++ &kb_timer);
4734 ++ waiting_for_sync = 1;
4735 ++ }
4736 ++}
4737 ++
4738 ++int cmd_start_new_node(int nodeid, int partition)
4739 + {
4740 + struct vq_node *node;
4741 +
4742 + node = find_node(nodeid);
4743 + if (node) {
4744 + fprintf(stderr, "ERR: nodeid %d already exists in partition %d\n", nodeid, node->partition->num);
4745 +- return;
4746 ++ return -1;
4747 + }
4748 +- qb_loop_poll_del(poll_loop, STDIN_FILENO);
4749 +- create_node(nodeid, partition);
4750 +- if (!nosync) {
4751 +- /* Delay kb input handling by 0.25 second when we've just
4752 +- added a node; expect that the delay will be cancelled
4753 +- substantially earlier once it has reported its quorum info
4754 +- (the delay is in fact a failsafe input enabler here) */
4755 +- qb_loop_timer_add(poll_loop,
4756 +- QB_LOOP_MED,
4757 +- 250000000,
4758 +- NULL,
4759 +- start_kb_input_timeout,
4760 +- &kb_timer);
4761 ++ if (create_node(nodeid, partition) == -1) {
4762 ++ return -1;
4763 + }
4764 ++ return 0;
4765 + }
4766 +
4767 + void cmd_stop_all_nodes()
4768 +@@ -489,20 +566,21 @@ void cmd_show_node_states()
4769 + fprintf(output_file, "#autofence: %s\n", autofence?"on":"off");
4770 + }
4771 +
4772 +-void cmd_stop_node(int nodeid)
4773 ++int cmd_stop_node(int nodeid)
4774 + {
4775 + struct vq_node *node;
4776 +
4777 + node = find_node(nodeid);
4778 + if (!node) {
4779 + fprintf(stderr, "ERR: nodeid %d is not up\n", nodeid);
4780 +- return;
4781 ++ return -1;
4782 + }
4783 +
4784 + /* Remove processor */
4785 + vq_quit(node->instance);
4786 +
4787 + /* Node will be removed when the child process exits */
4788 ++ return 0;
4789 + }
4790 +
4791 + /* Move all nodes in 'nodelist' into partition 'partition' */
4792 +@@ -510,6 +588,13 @@ void cmd_move_nodes(int partition, int num_nodes, int *nodelist)
4793 + {
4794 + int i;
4795 + struct vq_node *node;
4796 ++ struct vq_node *vqn;
4797 ++ int total_nodes = num_nodes;
4798 ++
4799 ++ /* Work out the number of nodes affected */
4800 ++ TAILQ_FOREACH(vqn, &partitions[partition].nodelist, entries) {
4801 ++ total_nodes++;
4802 ++ }
4803 +
4804 + for (i=0; i<num_nodes; i++) {
4805 + node = find_node(nodelist[i]);
4806 +@@ -532,6 +617,11 @@ void cmd_move_nodes(int partition, int num_nodes, int *nodelist)
4807 + void cmd_join_partitions(int part1, int part2)
4808 + {
4809 + struct vq_node *vqn;
4810 ++ int total_nodes=0;
4811 ++
4812 ++ /* Work out the number of nodes affected */
4813 ++ total_nodes += nodes_in_partition(part1);
4814 ++ total_nodes += nodes_in_partition(part2);
4815 +
4816 + /* TAILQ_FOREACH is not delete safe *sigh* */
4817 + retry:
4818 +@@ -551,6 +641,18 @@ void cmd_set_autofence(int onoff)
4819 + fprintf(output_file, "#autofence: %s\n", onoff?"on":"off");
4820 + }
4821 +
4822 ++void cmd_set_sync(int onoff)
4823 ++{
4824 ++ autofence = onoff;
4825 ++ fprintf(output_file, "#sync: %s\n", onoff?"on":"off");
4826 ++ sync_cmds = onoff;
4827 ++}
4828 ++
4829 ++void cmd_set_assert(int onoff)
4830 ++{
4831 ++ assert_on_timeout = onoff;
4832 ++}
4833 ++
4834 + void cmd_update_all_partitions(int newring)
4835 + {
4836 + int i;
4837 +@@ -571,6 +673,24 @@ void cmd_qdevice_poll(int nodeid, int onoff)
4838 + }
4839 + }
4840 +
4841 ++/* If we get called then a command has timed-out */
4842 ++static void finish_wait_timeout(void *data)
4843 ++{
4844 ++ if (command_timeout) {
4845 ++ fprintf(stderr, "ERR: Partition(s) not stable within timeout\n");
4846 ++ if (assert_on_timeout) {
4847 ++ exit(2);
4848 ++ }
4849 ++ }
4850 ++
4851 ++ resume_kb_input(sync_cmds);
4852 ++}
4853 ++
4854 ++void cmd_set_timeout(uint64_t seconds)
4855 ++{
4856 ++ command_timeout = seconds * QB_TIME_NS_IN_MSEC;
4857 ++}
4858 ++
4859 + /* ---------------------------------- */
4860 +
4861 + #ifndef HAVE_READLINE_READLINE_H
4862 +@@ -598,11 +718,6 @@ static void dummy_read_char()
4863 +
4864 + parse_input_command((c == EOF) ? NULL : input_buf);
4865 + input_buf_term = 0;
4866 +-
4867 +- if (is_tty) {
4868 +- printf("vqsim> ");
4869 +- fflush(stdout);
4870 +- }
4871 + }
4872 + #endif
4873 +
4874 +@@ -617,50 +732,26 @@ static int stdin_read_fn(int32_t fd, int32_t revents, void *data)
4875 + return 0;
4876 + }
4877 +
4878 +-static void start_kb_input(void)
4879 +-{
4880 +- wait_count_to_unblock = 0;
4881 +-
4882 +-#ifdef HAVE_READLINE_READLINE_H
4883 +- /* Readline will deal with completed lines when they arrive */
4884 +- rl_callback_handler_install("vqsim> ", parse_input_command);
4885 +-#else
4886 +- if (is_tty) {
4887 +- printf("vqsim> ");
4888 +- fflush(stdout);
4889 +- }
4890 +-#endif
4891 +-
4892 +- /* Send stdin to readline */
4893 +- if (qb_loop_poll_add(poll_loop,
4894 +- QB_LOOP_MED,
4895 +- STDIN_FILENO,
4896 +- POLLIN | POLLERR,
4897 +- NULL,
4898 +- stdin_read_fn)) {
4899 +- if (errno != EEXIST) {
4900 +- perror("qb_loop_poll_add1 returned error");
4901 +- }
4902 +- }
4903 +-}
4904 +
4905 + static void start_kb_input_timeout(void *data)
4906 + {
4907 +-// fprintf(stderr, "Waiting for nodes to report status timed out\n");
4908 +- start_kb_input();
4909 ++ resume_kb_input(1);
4910 + }
4911 +
4912 + static void usage(char *program)
4913 + {
4914 + printf("Usage:\n");
4915 + printf("\n");
4916 +- printf("%s [-f <config-file>] [-o <output-file>]\n", program);
4917 ++ printf("%s [-c <config-file>] [-o <output-file>]\n", program);
4918 + printf("\n");
4919 +- printf(" -f config file. defaults to /etc/corosync/corosync.conf\n");
4920 ++ printf(" -c config file. defaults to /etc/corosync/corosync.conf\n");
4921 + printf(" -o output file. defaults to stdout\n");
4922 + printf(" -n no synchronization (on adding a node)\n");
4923 + printf(" -h display this help text\n");
4924 + printf("\n");
4925 ++ printf("%s always takes input from STDIN, but cannot use a file.\n", program);
4926 ++ printf("If you want to script it then use\n cat | %s\n", program);
4927 ++ printf("\n");
4928 + }
4929 +
4930 + int main(int argc, char **argv)
4931 +@@ -669,16 +760,16 @@ int main(int argc, char **argv)
4932 + int ch;
4933 + char *output_file_name = NULL;
4934 +
4935 +- while ((ch = getopt (argc, argv, "f:o:nh")) != EOF) {
4936 ++ while ((ch = getopt (argc, argv, "c:o:nh")) != EOF) {
4937 + switch (ch) {
4938 +- case 'f':
4939 ++ case 'c':
4940 + strncpy(corosync_config_file, optarg, sizeof(corosync_config_file));
4941 + break;
4942 + case 'o':
4943 + output_file_name = optarg;
4944 + break;
4945 + case 'n':
4946 +- nosync = 1;
4947 ++ sync_cmds = 0;
4948 + break;
4949 + default:
4950 + usage(argv[0]);
4951 +@@ -696,9 +787,8 @@ int main(int argc, char **argv)
4952 + else {
4953 + output_file = stdout;
4954 + }
4955 +-#ifndef HAVE_READLINE_READLINE_H
4956 ++
4957 + is_tty = isatty(STDIN_FILENO);
4958 +-#endif
4959 +
4960 + qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
4961 + QB_LOG_FILTER_FUNCTION, "*", LOG_DEBUG);
4962 +@@ -717,9 +807,26 @@ int main(int argc, char **argv)
4963 + sigchld_handler,
4964 + &sigchld_qb_handle);
4965 +
4966 +- /* Create a full cluster of nodes from corosync.conf */
4967 ++
4968 ++#ifdef HAVE_READLINE_READLINE_H
4969 ++ /* Readline will deal with completed lines when they arrive */
4970 ++ /*
4971 ++ * For scripting add '#' to the start of the prompt so that
4972 ++ * parsers can ignore input lines
4973 ++ */
4974 ++ rl_already_prompted = 1;
4975 ++ if (is_tty) {
4976 ++ rl_callback_handler_install("vqsim> ", parse_input_command);
4977 ++ } else {
4978 ++ rl_callback_handler_install("#vqsim> ", parse_input_command);
4979 ++ }
4980 ++#endif
4981 ++
4982 ++
4983 ++
4984 ++/* Create a full cluster of nodes from corosync.conf */
4985 + read_corosync_conf();
4986 +- if (create_nodes_from_config() && !nosync) {
4987 ++ if (create_nodes_from_config() && sync_cmds) {
4988 + /* Delay kb input handling by 1 second when we've just
4989 + added the nodes from corosync.conf; expect that
4990 + the delay will be cancelled substantially earlier
4991 +@@ -731,8 +838,9 @@ int main(int argc, char **argv)
4992 + NULL,
4993 + start_kb_input_timeout,
4994 + &kb_timer);
4995 ++ waiting_for_sync = 1;
4996 + } else {
4997 +- start_kb_input();
4998 ++ resume_kb_input(0);
4999 + }
5000 +
5001 + qb_loop_run(poll_loop);
5002 +diff --git a/vqsim/vqsim_vq_engine.c b/vqsim/vqsim_vq_engine.c
5003 +index cbe1d47..eb35d35 100644
5004 +--- a/vqsim/vqsim_vq_engine.c
5005 ++++ b/vqsim/vqsim_vq_engine.c
5006 +@@ -191,6 +191,7 @@ static void set_local_node_pos(struct corosync_api_v1 *api)
5007 + uint32_t nodeid;
5008 + const char *iter_key;
5009 + int res;
5010 ++ int found = 0;
5011 +
5012 + iter = icmap_iter_init("nodelist.node.");
5013 + while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
5014 +@@ -205,13 +206,18 @@ static void set_local_node_pos(struct corosync_api_v1 *api)
5015 + res = icmap_get_uint32(iter_key, &nodeid);
5016 + if (res == CS_OK) {
5017 + if (nodeid == our_nodeid) {
5018 ++ found = 1;
5019 + res = icmap_set_uint32("nodelist.local_node_pos", node_pos);
5020 +- if (res != CS_OK) {
5021 +- fprintf(stderr, "Failed to find node %d in corosync.conf. Quorum calculations may not be correct:\n", our_nodeid);
5022 +- }
5023 + }
5024 + }
5025 + }
5026 ++ if (!found) {
5027 ++ /* This probably indicates a dynamically-added node
5028 ++ * set the pos to zero and use the votes of the
5029 ++ * first node in corosync.conf
5030 ++ */
5031 ++ res = icmap_set_uint32("nodelist.local_node_pos", 0);
5032 ++ }
5033 + }
5034 +
5035 + static int load_quorum_instance(struct corosync_api_v1 *api)
5036 +diff --git a/man/corosync-vqsim.8 b/man/corosync-vqsim.8
5037 +new file mode 100644
5038 +index 0000000..26a6468
5039 +--- /dev/null
5040 ++++ b/man/corosync-vqsim.8
5041 +@@ -0,0 +1,94 @@
5042 ++.\"/*
5043 ++.\" * Copyright (C) 2019 Red Hat, Inc.
5044 ++.\" *
5045 ++.\" * All rights reserved.
5046 ++.\" *
5047 ++.\" * Author: Christine Caulfield <ccaulfie@redhat.com>
5048 ++.\" *
5049 ++.\" * This software licensed under BSD license, the text of which follows:
5050 ++.\" *
5051 ++.\" * Redistribution and use in source and binary forms, with or without
5052 ++.\" * modification, are permitted provided that the following conditions are met:
5053 ++.\" *
5054 ++.\" * - Redistributions of source code must retain the above copyright notice,
5055 ++.\" * this list of conditions and the following disclaimer.
5056 ++.\" * - Redistributions in binary form must reproduce the above copyright notice,
5057 ++.\" * this list of conditions and the following disclaimer in the documentation
5058 ++.\" * and/or other materials provided with the distribution.
5059 ++.\" * - Neither the name of the MontaVista Software, Inc. nor the names of its
5060 ++.\" * contributors may be used to endorse or promote products derived from this
5061 ++.\" * software without specific prior written permission.
5062 ++.\" *
5063 ++.\" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
5064 ++.\" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5065 ++.\" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5066 ++.\" * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
5067 ++.\" * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5068 ++.\" * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5069 ++.\" * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5070 ++.\" * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5071 ++.\" * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5072 ++.\" * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
5073 ++.\" * THE POSSIBILITY OF SUCH DAMAGE.
5074 ++.\" */
5075 ++.TH COROSYNC-VQSIM 8 2019-05-10
5076 ++.SH NAME
5077 ++corosync-vqsim \- The votequorum simulator
5078 ++.SH SYNOPSIS
5079 ++.B "corosync-vqsim [\-c config_file] [\-o output file] [\-n] [\-h]"
5080 ++.SH DESCRIPTION
5081 ++.B corosync-vqsim
5082 ++simulates the quorum functions of corosync in a single program. it can simulate
5083 ++multiple nodes, network splits and a basic quorum device.
5084 ++
5085 ++By default vqsim will build a virtual cluster of all the nodes in the corosync.conf file,
5086 ++each 'node' running in a forked subprocess (and thus asynchronously). It then provides a
5087 ++command-line interface to add (up) or remove (down) nodes, and cause network splits and
5088 ++rejoins. After each event it shows the new quorum status for all nodes.
5089 ++
5090 ++Nodes in vqsim are always referred to by their nodeid (the IP address is meaningless) and
5091 ++optionally by a 'partition' which precedes the nodeid with a colon. By default all nodes
5092 ++are in partition 0. Nodes can be moved between partitions using the split and join commands.
5093 ++Multiple nodes can be split and joined at the same time.
5094 ++
5095 ++To script vqsim you must send input to it via a pipe rather than just redirecting STDIN. This
5096 ++is because it runs asynchronously to enable the virtual 'nodes' to report status when needed.
5097 ++(eg if you kill a subprocess using the 'kill(1)' command it gets removed from the cluster).
5098 ++
5099 ++By default vqsim will wait for all nodes in all partitions to reach the same
5100 ++ring sequence number before returning a prompt,
5101 ++there is a timeout associated with this in case of a 'node' failure and exceeding this timeout
5102 ++can (optionally) quit the program signalling an error.
5103 ++
5104 ++You can disable waiting using the 'sync off' command or the -n command-line option. This can easily
5105 ++cause unexpected behaviour so use it with care.
5106 ++
5107 ++The number of votes per node is read from corosync.conf. New nodes added using the 'up' command
5108 ++will copy their number of votes from the first node in corosync.conf. This may not be what you
5109 ++expect and I might fix it in future. As most clusters have only 1 vote per node (and this is
5110 ++strongly recommended) then this should rarely be a problem.
5111 ++
5112 ++Once you have the 'vqsim> ' prompt you can type 'help' and get a list of sub-commands.
5113 ++
5114 ++.SH OPTIONS
5115 ++.TP
5116 ++.B -c
5117 ++This specifies the fully qualified path to the corosync configuration file.
5118 ++
5119 ++The default is /etc/corosync/corosync.conf.
5120 ++.TP
5121 ++.B -o
5122 ++Specifies the output destination. STDOUT by default.
5123 ++.TP
5124 ++.B -n
5125 ++Don't pause after each command, come straight back to a prompt. Use with care!
5126 ++
5127 ++.TP
5128 ++.B -h
5129 ++Display a brief help message
5130 ++.SH SEE ALSO
5131 ++.BR corosync (9),
5132 ++.BR corosync.conf (5),
5133 ++.SH AUTHOR
5134 ++Christine Caulfield
5135 ++.PP
5136 diff --git a/debian/patches/vqsim-Fix-vqsim-for-corosync-3.0.patch b/debian/patches/vqsim-Fix-vqsim-for-corosync-3.0.patch
5137 new file mode 100644
5138 index 00000000..36f686c9
5139 --- /dev/null
5140 +++ b/debian/patches/vqsim-Fix-vqsim-for-corosync-3.0.patch
5141 @@ -0,0 +1,102 @@
5142 +From: Christine Caulfield <ccaulfie@redhat.com>
5143 +Date: Thu, 25 Apr 2019 14:38:52 +0100
5144 +Subject: vqsim: Fix vqsim for corosync 3.0
5145 +
5146 +A couple of small internal changes in corosync 3.0 broke vqsim.
5147 +1) The way the custom config file is specified (no long an env variable)
5148 +2) votequorum now needs to know ouZ_node_pos
5149 +
5150 +Signed-off-by: Christine Caulfield <ccaulfie@redhat.com>
5151 +Reviewed-by: Jan Friesse <jfriesse@redhat.com>
5152 +(cherry picked from commit e65d7b5d9800df96dcc8b5d6216a85800113924c)
5153 +---
5154 + vqsim/vqmain.c | 8 +-------
5155 + vqsim/vqsim_vq_engine.c | 37 +++++++++++++++++++++++++++++++++++++
5156 + 2 files changed, 38 insertions(+), 7 deletions(-)
5157 +
5158 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
5159 +index 683cc22..c3a1327 100644
5160 +--- a/vqsim/vqmain.c
5161 ++++ b/vqsim/vqmain.c
5162 +@@ -667,14 +667,12 @@ int main(int argc, char **argv)
5163 + {
5164 + qb_loop_signal_handle sigchld_qb_handle;
5165 + int ch;
5166 +- char *config_file_name = NULL;
5167 + char *output_file_name = NULL;
5168 +- char envstring[PATH_MAX];
5169 +
5170 + while ((ch = getopt (argc, argv, "f:o:nh")) != EOF) {
5171 + switch (ch) {
5172 + case 'f':
5173 +- config_file_name = optarg;
5174 ++ strncpy(corosync_config_file, optarg, sizeof(corosync_config_file));
5175 + break;
5176 + case 'o':
5177 + output_file_name = optarg;
5178 +@@ -688,10 +686,6 @@ int main(int argc, char **argv)
5179 + }
5180 + }
5181 +
5182 +- if (config_file_name) {
5183 +- sprintf(envstring, "COROSYNC_MAIN_CONFIG_FILE=%s", config_file_name);
5184 +- putenv(envstring);
5185 +- }
5186 + if (output_file_name) {
5187 + output_file = fopen(output_file_name, "w");
5188 + if (!output_file) {
5189 +diff --git a/vqsim/vqsim_vq_engine.c b/vqsim/vqsim_vq_engine.c
5190 +index 9d8b4ee..cbe1d47 100644
5191 +--- a/vqsim/vqsim_vq_engine.c
5192 ++++ b/vqsim/vqsim_vq_engine.c
5193 +@@ -178,6 +178,42 @@ char *get_run_dir()
5194 + return getcwd(cwd_buffer, PATH_MAX);
5195 + }
5196 +
5197 ++/* This is different to the one in totemconfig.c in that we already
5198 ++ * know the 'local' node ID, so we can just search for that.
5199 ++ * It needs to be here rather than at main config read time as it's
5200 ++ * (obviously) going to be different for each instance.
5201 ++ */
5202 ++static void set_local_node_pos(struct corosync_api_v1 *api)
5203 ++{
5204 ++ icmap_iter_t iter;
5205 ++ uint32_t node_pos;
5206 ++ char name_str[ICMAP_KEYNAME_MAXLEN];
5207 ++ uint32_t nodeid;
5208 ++ const char *iter_key;
5209 ++ int res;
5210 ++
5211 ++ iter = icmap_iter_init("nodelist.node.");
5212 ++ while ((iter_key = icmap_iter_next(iter, NULL, NULL)) != NULL) {
5213 ++ res = sscanf(iter_key, "nodelist.node.%u.%s", &node_pos, name_str);
5214 ++ if (res != 2) {
5215 ++ continue;
5216 ++ }
5217 ++ if (strcmp(name_str, "nodeid")) {
5218 ++ continue;
5219 ++ }
5220 ++
5221 ++ res = icmap_get_uint32(iter_key, &nodeid);
5222 ++ if (res == CS_OK) {
5223 ++ if (nodeid == our_nodeid) {
5224 ++ res = icmap_set_uint32("nodelist.local_node_pos", node_pos);
5225 ++ if (res != CS_OK) {
5226 ++ fprintf(stderr, "Failed to find node %d in corosync.conf. Quorum calculations may not be correct:\n", our_nodeid);
5227 ++ }
5228 ++ }
5229 ++ }
5230 ++ }
5231 ++}
5232 ++
5233 + static int load_quorum_instance(struct corosync_api_v1 *api)
5234 + {
5235 + const char *error_string;
5236 +@@ -417,6 +453,7 @@ int fork_new_instance(int nodeid, int *vq_sock, pid_t *childpid)
5237 + qdevice_timeout = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
5238 + }
5239 +
5240 ++ set_local_node_pos(&corosync_api);
5241 + load_quorum_instance(&corosync_api);
5242 +
5243 + qb_loop_poll_add(poll_loop,
5244 diff --git a/debian/patches/vqsim-Free-allocated-newvq-on-error.patch b/debian/patches/vqsim-Free-allocated-newvq-on-error.patch
5245 new file mode 100644
5246 index 00000000..cfa9a763
5247 --- /dev/null
5248 +++ b/debian/patches/vqsim-Free-allocated-newvq-on-error.patch
5249 @@ -0,0 +1,23 @@
5250 +From: Jan Friesse <jfriesse@redhat.com>
5251 +Date: Tue, 11 Jun 2019 14:50:03 +0200
5252 +Subject: vqsim: Free allocated newvq on error
5253 +
5254 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
5255 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
5256 +(cherry picked from commit 215d2e30b20d5167161a2d803284f2b0ecf67c29)
5257 +---
5258 + vqsim/vqmain.c | 1 +
5259 + 1 file changed, 1 insertion(+)
5260 +
5261 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
5262 +index 98729b9..d45a24d 100644
5263 +--- a/vqsim/vqmain.c
5264 ++++ b/vqsim/vqmain.c
5265 +@@ -425,6 +425,7 @@ static pid_t create_node(int nodeid, int partno)
5266 + fprintf(stderr,
5267 + "ERR: could not create vq instance nodeid %d\n",
5268 + nodeid);
5269 ++ free(newvq);
5270 + return (pid_t) -1;
5271 + }
5272 + newvq->partition = &partitions[partno];
5273 diff --git a/debian/patches/vqsim-Make-vqsim-compile.patch b/debian/patches/vqsim-Make-vqsim-compile.patch
5274 new file mode 100644
5275 index 00000000..766ab88b
5276 --- /dev/null
5277 +++ b/debian/patches/vqsim-Make-vqsim-compile.patch
5278 @@ -0,0 +1,131 @@
5279 +From: Jan Friesse <jfriesse@redhat.com>
5280 +Date: Tue, 23 Apr 2019 16:48:30 +0200
5281 +Subject: vqsim: Make vqsim compile
5282 +
5283 +Also add vqsim binary to .gitignore.
5284 +
5285 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
5286 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
5287 +(cherry picked from commit e287a7c1efd37732d2bd3309a1d7d23a303f8640)
5288 +---
5289 + vqsim/Makefile.am | 1 +
5290 + vqsim/vqmain.c | 19 ++++++++++++++++---
5291 + vqsim/vqsim_vq_engine.c | 5 +++--
5292 + vqsim/.gitignore | 1 +
5293 + 4 files changed, 21 insertions(+), 5 deletions(-)
5294 + create mode 100644 vqsim/.gitignore
5295 +
5296 +diff --git a/vqsim/Makefile.am b/vqsim/Makefile.am
5297 +index b74826b..2a76544 100644
5298 +--- a/vqsim/Makefile.am
5299 ++++ b/vqsim/Makefile.am
5300 +@@ -39,6 +39,7 @@ noinst_PROGRAMS = vqsim
5301 + vqsim_LDADD = $(top_builddir)/common_lib/libcorosync_common.la \
5302 + ../exec/corosync-votequorum.o ../exec/corosync-icmap.o ../exec/corosync-logsys.o \
5303 + ../exec/corosync-coroparse.o ../exec/corosync-logconfig.o \
5304 ++ ../exec/corosync-util.o \
5305 + $(LIBQB_LIBS)
5306 + if VQSIM_READLINE
5307 + vqsim_LDADD += -lreadline
5308 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
5309 +index e7917d7..683cc22 100644
5310 +--- a/vqsim/vqmain.c
5311 ++++ b/vqsim/vqmain.c
5312 +@@ -26,6 +26,9 @@
5313 + extern int coroparse_configparse (icmap_map_t config_map, const char **error_string);
5314 + extern int corosync_log_config_read (const char **error_string);
5315 +
5316 ++/* 'Keep the compiler happy' time */
5317 ++const char *corosync_get_config_file(void);
5318 ++
5319 + /* One of these per partition */
5320 + struct vq_partition {
5321 + TAILQ_HEAD(, vq_node) nodelist;
5322 +@@ -70,6 +73,15 @@ static size_t input_buf_term = 0;
5323 + static int is_tty;
5324 + #endif
5325 +
5326 ++/* 'Keep the compiler happy' time */
5327 ++static char corosync_config_file[PATH_MAX + 1] = COROSYSCONFDIR "/corosync.conf";
5328 ++
5329 ++const char *corosync_get_config_file(void)
5330 ++{
5331 ++
5332 ++ return (corosync_config_file);
5333 ++}
5334 ++
5335 + /* Tell all non-quorate nodes to quit */
5336 + static void force_fence(void)
5337 + {
5338 +@@ -110,7 +122,7 @@ static void print_quorum_state(struct vq_node *node)
5339 + }
5340 +
5341 + fprintf(output_file, "%d:%02d: q=%d ring=[%d/%lld] ", node->partition->num, node->nodeid, node->last_quorate,
5342 +- node->last_ring_id.rep.nodeid, node->last_ring_id.seq);
5343 ++ node->last_ring_id.nodeid, node->last_ring_id.seq);
5344 + fprintf(output_file, "nodes=[");
5345 + for (i = 0; i < node->last_view_list_entries; i++) {
5346 + if (i) {
5347 +@@ -209,6 +221,7 @@ static int read_corosync_conf(void)
5348 + log_printf (LOGSYS_LEVEL_ERROR, "Can't initialize log thread");
5349 + return -1;
5350 + }
5351 ++
5352 + return 0;
5353 + }
5354 +
5355 +@@ -287,7 +300,7 @@ static void send_partition_to_nodes(struct vq_partition *partition, int newring)
5356 + TAILQ_FOREACH(vqn, &partition->nodelist, entries) {
5357 + nodelist[nodes++] = vqn->nodeid;
5358 + if (first) {
5359 +- partition->ring_id.rep.nodeid = vqn->nodeid;
5360 ++ partition->ring_id.nodeid = vqn->nodeid;
5361 + first = 0;
5362 + }
5363 + }
5364 +@@ -303,7 +316,7 @@ static void init_partitions(void)
5365 +
5366 + for (i=0; i<MAX_PARTITIONS; i++) {
5367 + TAILQ_INIT(&partitions[i].nodelist);
5368 +- partitions[i].ring_id.rep.nodeid = 1000+i;
5369 ++ partitions[i].ring_id.nodeid = 1000+i;
5370 + partitions[i].ring_id.seq = 0;
5371 + partitions[i].num = i;
5372 + }
5373 +diff --git a/vqsim/vqsim_vq_engine.c b/vqsim/vqsim_vq_engine.c
5374 +index ee139d4..9d8b4ee 100644
5375 +--- a/vqsim/vqsim_vq_engine.c
5376 ++++ b/vqsim/vqsim_vq_engine.c
5377 +@@ -44,6 +44,7 @@ static unsigned int qdevice_timeout = VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT;
5378 +
5379 + /* 'Keep the compiler happy' time */
5380 + char *get_run_dir(void);
5381 ++
5382 + int api_timer_add_duration (
5383 + unsigned long long nanosec_duration,
5384 + void *data,
5385 +@@ -262,7 +263,7 @@ static int poll_qdevice(int onoff)
5386 + int res;
5387 +
5388 + pollmsg.cast_vote = onoff;
5389 +- pollmsg.ring_id.nodeid = current_ring_id.rep.nodeid;
5390 ++ pollmsg.ring_id.nodeid = current_ring_id.nodeid;
5391 + pollmsg.ring_id.seq = current_ring_id.seq;
5392 + strcpy(pollmsg.name, QDEVICE_NAME);
5393 +
5394 +@@ -374,7 +375,7 @@ static void initial_sync(int nodeid)
5395 + unsigned int member_list[1] = {nodeid};
5396 + struct memb_ring_id ring_id;
5397 +
5398 +- ring_id.rep.nodeid = our_nodeid;
5399 ++ ring_id.nodeid = our_nodeid;
5400 + ring_id.seq = 1;
5401 +
5402 + /* cluster with just us in it */
5403 +diff --git a/vqsim/.gitignore b/vqsim/.gitignore
5404 +new file mode 100644
5405 +index 0000000..85d30f9
5406 +--- /dev/null
5407 ++++ b/vqsim/.gitignore
5408 +@@ -0,0 +1 @@
5409 ++vqsim
5410 diff --git a/debian/patches/vqsim-Remove-unused-total_nodes.patch b/debian/patches/vqsim-Remove-unused-total_nodes.patch
5411 new file mode 100644
5412 index 00000000..a50c6d58
5413 --- /dev/null
5414 +++ b/debian/patches/vqsim-Remove-unused-total_nodes.patch
5415 @@ -0,0 +1,62 @@
5416 +From: Jan Friesse <jfriesse@redhat.com>
5417 +Date: Tue, 11 Jun 2019 15:11:13 +0200
5418 +Subject: vqsim: Remove unused total_nodes
5419 +
5420 +... and remove unused nodes_in_partition function.
5421 +
5422 +Also replace TAILQ_FOREACH with goto to while cycle.
5423 +
5424 +Signed-off-by: Jan Friesse <jfriesse@redhat.com>
5425 +Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
5426 +(cherry picked from commit ef9b931b7e2585ef87198693760df39d60e9f542)
5427 +---
5428 + vqsim/vqmain.c | 25 ++-----------------------
5429 + 1 file changed, 2 insertions(+), 23 deletions(-)
5430 +
5431 +diff --git a/vqsim/vqmain.c b/vqsim/vqmain.c
5432 +index d45a24d..16f7714 100644
5433 +--- a/vqsim/vqmain.c
5434 ++++ b/vqsim/vqmain.c
5435 +@@ -401,18 +401,6 @@ static void init_partitions(void)
5436 + }
5437 + }
5438 +
5439 +-static int nodes_in_partition(int part)
5440 +-{
5441 +- struct vq_node *vqn;
5442 +- int partnodes = 0;
5443 +-
5444 +- TAILQ_FOREACH(vqn, &partitions[part].nodelist, entries) {
5445 +- partnodes++;
5446 +- }
5447 +- return partnodes;
5448 +-}
5449 +-
5450 +-
5451 + static pid_t create_node(int nodeid, int partno)
5452 + {
5453 + struct vq_node *newvq;
5454 +@@ -634,21 +622,12 @@ void cmd_move_nodes(int partition, int num_nodes, int *nodelist)
5455 + void cmd_join_partitions(int part1, int part2)
5456 + {
5457 + struct vq_node *vqn;
5458 +- int total_nodes=0;
5459 +-
5460 +- /* Work out the number of nodes affected */
5461 +- total_nodes += nodes_in_partition(part1);
5462 +- total_nodes += nodes_in_partition(part2);
5463 +-
5464 +- /* TAILQ_FOREACH is not delete safe *sigh* */
5465 +-retry:
5466 +- TAILQ_FOREACH(vqn, &partitions[part2].nodelist, entries) {
5467 +
5468 ++ while (!TAILQ_EMPTY(&partitions[part2].nodelist)) {
5469 ++ vqn = TAILQ_FIRST(&partitions[part2].nodelist);
5470 + TAILQ_REMOVE(&vqn->partition->nodelist, vqn, entries);
5471 + TAILQ_INSERT_TAIL(&partitions[part1].nodelist, vqn, entries);
5472 + vqn->partition = &partitions[part1];
5473 +-
5474 +- goto retry;
5475 + }
5476 + }
5477 +
5478 diff --git a/debian/patches/series b/debian/patches/series
5479 index 6b552ce1..ea6e04ea 100644
5480 --- a/debian/patches/series
5481 +++ b/debian/patches/series
5482 @@ -1,8 +1,53 @@
5483 -Fix-various-typos-in-ChangeLog.patch
5484 -Enable-PrivateTmp-in-the-systemd-service-files.patch
5485 -Make-the-example-config-valid.patch
5486 +doc-Update-INSTALL-file.patch
5487 +cfgtool-Improve-link-status-display.patch
5488 corosync.conf.5-fix-grammar.patch
5489 corosync.conf.5-typography-fixes.patch
5490 -AC_PROG_SED-is-already-present.patch
5491 -Use-the-SED-variable-provided-by-configure.patch
5492 -Use-the-AWK-variable-provided-by-configure.patch
5493 +configure.ac-AC_PROG_SED-is-already-present.patch
5494 +build-Use-the-SED-variable-provided-by-configure.patch
5495 +build-Use-the-AWK-variable-provided-by-configure.patch
5496 +corosync-cfgtool-Fix-i-matching.patch
5497 +quorumtool-Fix-exit-status-codes.patch
5498 +nozzle-Add-support-for-libnozzle-devices.patch
5499 +configure-Do-not-autodetect-nozzle.patch
5500 +coroparse-Fix-compiler-warning.patch
5501 +totemsrp-Word-spelling-mistake.patch
5502 +Revert-init-Enable-StopWhenUnneeded.patch
5503 +set-totem.keyfile-and-totem.key-to-RO.patch
5504 +keygen-Reflect-change-in-knet.patch
5505 +totemconfig-Remove-support-for-3des.patch
5506 +crypto-re-introduce-secauth-parameter.patch
5507 +cpg-Add-CPG_REASON_UNDEFINED.patch
5508 +totemconfig-ipaddr_equal-check-just-addr-part.patch
5509 +vqsim-Make-vqsim-compile.patch
5510 +vqsim-Fix-vqsim-for-corosync-3.0.patch
5511 +totemconfig-Ensure-nodeid-is-specified-for-IPv6.patch
5512 +totemconfig-fix-autogen-mcastaddr-for-ipv6-4.patch
5513 +knet-Fix-a-couple-of-errors-when-adding-a-new-link.patch
5514 +vqsim-Enhance-vqsim.patch
5515 +totemconfig-Fix-minimum-limit-for-hold-timeout.patch
5516 +man-Enhance-token_retransmit-description.patch
5517 +knet-allow-corosync-to-use-knet-access-lists.patch
5518 +knet-Fix-initialising-of-knet-access-lists.patch
5519 +udpu-Drop-packets-from-unlisted-IPs.patch
5520 +knet-Use-block_unlisted_ips.patch
5521 +cfgtool-Fix-link-status-display.patch
5522 +man-Enhance-corosync.conf-mp-a-bit.patch
5523 +man-Enahnce-block_unlisted_ips-description.patch
5524 +spec-Add-support-for-user-flags-configure-option.patch
5525 +man-Add-vqsim-man-page-into-distributed-tarball.patch
5526 +configure-Fix-GDB_CFLAGS-typo.patch
5527 +totemconfig-ipaddr_equal-use-switch.patch
5528 +totemip-Use-res-in-totemip_sa_equal.patch
5529 +totemknet-create_nozzle_device-simplify-check.patch
5530 +totemknet-Ignore-icmap_get_string-result.patch
5531 +totemknet-macaddr_str-is-always-set.patch
5532 +totemknet-Initialize-return-value-in-setup_nozzle.patch
5533 +vqsim-Do-not-access-unitialized-argv-0.patch
5534 +vqsim-Check-write-result.patch
5535 +vqsim-Check-length-of-received-message.patch
5536 +vqsim-Free-allocated-newvq-on-error.patch
5537 +vqsim-Remove-unused-total_nodes.patch
5538 +vqsim-Check-result-of-icmap_set_uint32.patch
5539 +vqsim-Check-length-of-copied-optarg.patch
5540 +Fix-various-typos-in-ChangeLog.patch
5541 +Enable-PrivateTmp-in-the-systemd-service-files.patch