[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#986568: marked as done (unblock: corosync/3.1.2-1)



Your message dated Tue, 13 Apr 2021 20:59:25 +0000
with message-id <E1lWQ85-0007s5-7r@respighi.debian.org>
and subject line unblock corosync
has caused the Debian Bug report #986568,
regarding unblock: corosync/3.1.2-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
986568: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=986568
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package corosync

Dear Release Team,

First of all, sorry for not recognizing sooner that Corosync is a key
package; I should have asked you before the upload, but here we are...

The Corosync version 3.1.0-3 in testing is affected by two bugs:

#985070 corosync: fails to start in unprivileged container
#986325 corosync: crash with compression enabled

When the crash was fixed, upstream sent me the patch directly.  I
noticed that the fix for the other bug had already been shipped in the
3.1.1 maintenance release, which contained a couple of other fixes as
well and a fairly benign but somewhat verbose API extension (besides a
new unit test program and the Autoconf noise).  I considered these
useful future-proofing for bullseye and uploaded 3.1.1-1 with the
extra patch to fix both bugs above.  Then I learnt its migration is
blocked.  However, upstream decided that the crash fix warrants a new
maintenance release and shipped 3.1.2 yesterday with that single change.
After a little consideration I uploaded 3.1.2-1 as well to unstable on
the basis that it builds an identical source tree but has a somewhat
smaller debdiff against 3.1.0-3 because it doesn't introduce a new
Debian patch to the package:

diff -Nru corosync-3.1.0/ChangeLog corosync-3.1.2/ChangeLog
--- corosync-3.1.0/ChangeLog	2020-10-20 16:15:49.000000000 +0200
+++ corosync-3.1.2/ChangeLog	2021-04-06 12:03:45.000000000 +0200
@@ -1,3 +1,202 @@
+2021-04-06  Fabio M. Di Nitto  <fdinitto@redhat.com>
+
+	knet: pass correct handle to knet_handle_compress
+	totemknet_configure_compression was using knet_context
+	just to gather the knet handle / instance.
+
+	On first time config knet_contex is not initialized till
+	much later in the code, passing some random garbage pointers
+	to knet_handle_compress, that would crash later trying
+	to acquire a mutex lock.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-29  Johannes Krupp  <johannes.krupp@cispa.saarland>
+
+	totemconfig: fix integer underflow and logic bug
+	Fix integer underflow when computing `namelen` in `nodelist_byname`,
+	always use computed `namelen`.
+	Fixes #626.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-25  liangxin1300  <XLiang@suse.com>
+
+	totemconfig: change udp netmtu value as a constant
+	Insted of using "magic number" use UDP_NETMTU constant.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-18  Dan Streetman  <ddstreet@canonical.com>
+
+	totemknet: retry knet_handle_new if it fails
+	Retry knet_handle_new without privileged operations if it fails
+
+	knet_handle_new can fail with ENAMETOOLONG if its privileged operations
+	fail, which can happen if we're running as a user process or in an
+	unprivileged container.
+
+	This adds a cmap key 'allow_knet_handle_fallback' that defaults to no,
+	which is the current behavior of exiting with error if the knet_handle
+	can't be created with privileged operations. If the new cmap key is set
+	to 'yes' and the knet_handle creation fails, fallback to creating the
+	handle using unprivileged operations is tried.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-11  Dan Streetman  <ddstreet@canonical.com>
+
+	main: Check memlock rlimit
+	Don't lock all current and future memory if can't
+	increase memlock rlimit.
+
+	If we fail to increase our RLIMIT_MEMLOCK, then locking all our current
+	and future memory is extremely dangerous; once our memory use reaches
+	our RLIMIT_MEMLOCK, memory allocations will start failing, very likely
+	leading to our entire process crashing.
+
+	This can happen if we aren't a privileged process, for example if
+	running as non-root user, or inside an unprivileged container.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-09  Fabio M. Di Nitto  <fdinitto@redhat.com>
+
+	configure: drop unnecessary check and define
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+	configure: move exec_prefix sanitize
+	Move exec_prefix sanitize closer to prefix. This is not
+	functional change, just group functional tests together.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+	configure: drop dead code
+	prefix is sanitized already at the top of configure.ac to /usr,
+	hence the second instance can never hit.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+	configure: detect and init pkg-config with macro
+	this also allows to use PKG_CONFIG_* macros immediately
+	in conditional calls
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-03-04  Christine Caulfield  <ccaulfie@redhat.com>
+
+	main: Close race condition when moving to statedir
+	Found by covscan which also didn't like us 'leaking' the
+	fd to the lockfile. So close that too.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2021-01-14  Jan Friesse  <jfriesse@redhat.com>
+
+	init: Use corosync-cfgtool for shutdown
+	... to trigger cfg shutdown callbacks.
+
+	Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
+
+2021-01-14  Christine Caulfield  <ccaulfie@redhat.com>
+
+	test: Add testcfg to exercise some cfg functions
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+	cfg: Reinstate cfg tracking
+	CFG tracking was removed in 815375411e80131f31b172d7c43625769ee8b53d,
+	probably as a mistake, as part of the tidy up of cfg and the removal of
+	dynamic loading. This means that shutdown tracking (using
+	cfg_try_shutdown()) stopped working.
+
+	This patch restores the trackstart & trackstop API calls (renamed to be
+	more consistent with the exiting libraries) so that shutdown tracking
+	can be used again.
+
+	Change cfg.shutdown_timeout to be in milliseconds rather than seconds
+	nd use libqb macros for conversion.
+
+	Add --force option to corosync-cfgtool -H
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2020-11-26  Jan Friesse  <jfriesse@redhat.com>
+
+	cfg: Improve nodestatusget versioning
+	Patch tries to make nodestatusget really extendable. Following changes
+	are implemented:
+	- corosync_cfg_node_status_version_t is added with (for now) single
+	  value CFG_NODE_STATUS_V1
+	- corosync_knet_node_status renamed to corosync_cfg_node_status_v1 (it
+	  isn't really knet because it works as well for udp(u()
+	- struct res_lib_cfg_nodestatusget_version is added which holds only ipc
+	  result header and version on same position as for
+	  corosync_cfg_node_status_v1
+	- corosync_cfg_node_status_get requires version and pointer to one of
+	  corosync_cfg_node_status_v structures
+	- request is handled in case switches to make adding new version easier
+
+	Also fix following bugs:
+	- totempg_nodestatus_get error was retyped to cs_error_t without any
+	  meaning.
+	- header.error was not checked at all in the library
+
+	Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
+
+2020-11-26  Christine Caulfield  <ccaulfie@redhat.com>
+
+	cfg: New API to get extended node/link infomation
+	Current we horribly over-use totempg_ifaces_get() to
+	retrieve information about knet interfaces. This is an attempt to
+	improve on that.
+
+	All transports are supported (so not only Knet but also UDP(U)).
+
+	This patch builds best against the "onwire-upgrade" branch of knet
+	as that's what sparked my interest in getting more information out.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2020-11-12  Jan Friesse  <jfriesse@redhat.com>
+
+	totemknet: Check both cipher and hash for crypto
+	Previously only crypto cipher was used as a way to find out if crypto is
+	enabled or disabled.
+
+	This usually works ok until cipher is set to none and hash to some other
+	value (like sha1). Such config is perfectly valid and it was not
+	supported correctly.
+
+	As a solution, check both cipher and hash.
+
+	Reviewed-by: Fabio M. Di Nitto <fdinitto@redhat.com>
+	Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
+
+2020-11-10  Ferenc Wágner  <wferi@debian.org>
+
+	The ring id file needn't be executable
+	At the same time simplify the overwrite logic and stop clearing the
+	umask (which is unexpected and quite pointless here, as applications
+	can't really protect the users from their own pathological settings).
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2020-11-06  Fabio M. Di Nitto  <fdinitto@redhat.com>
+
+	pkgconfig: export LOGDIR in corosync.pc
+	logdir is configurable at build time and can change
+	from distro to distro. Export the path for pcs to use.
+
+	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
+
+2020-11-02  Jan Friesse  <jfriesse@redhat.com>
+
+	spec: Add isa version of corosync-devel provides
+	Also add release to version to match autogenerated corosynclib-devel
+	provides.
+
+	Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
+
 2020-10-19  liangxin1300  <XLiang@suse.com>
 
 	totemconfig: remove redundant nodeid error log
diff -Nru corosync-3.1.0/common_lib/Makefile.in corosync-3.1.2/common_lib/Makefile.in
--- corosync-3.1.0/common_lib/Makefile.in	2020-10-20 16:15:26.000000000 +0200
+++ corosync-3.1.2/common_lib/Makefile.in	2021-04-06 12:03:23.000000000 +0200
@@ -303,7 +303,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/conf/logrotate/Makefile.in corosync-3.1.2/conf/logrotate/Makefile.in
--- corosync-3.1.0/conf/logrotate/Makefile.in	2020-10-20 16:15:26.000000000 +0200
+++ corosync-3.1.2/conf/logrotate/Makefile.in	2021-04-06 12:03:23.000000000 +0200
@@ -252,7 +252,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/conf/Makefile.in corosync-3.1.2/conf/Makefile.in
--- corosync-3.1.0/conf/Makefile.in	2020-10-20 16:15:26.000000000 +0200
+++ corosync-3.1.2/conf/Makefile.in	2021-04-06 12:03:23.000000000 +0200
@@ -315,7 +315,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/configure corosync-3.1.2/configure
--- corosync-3.1.0/configure	2020-10-20 16:15:24.000000000 +0200
+++ corosync-3.1.2/configure	2021-04-06 12:03:21.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for corosync 3.1.0.
+# Generated by GNU Autoconf 2.69 for corosync 3.1.2.
 #
 # Report bugs to <users@clusterlabs.org>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='corosync'
 PACKAGE_TARNAME='corosync'
-PACKAGE_VERSION='3.1.0'
-PACKAGE_STRING='corosync 3.1.0'
+PACKAGE_VERSION='3.1.2'
+PACKAGE_STRING='corosync 3.1.2'
 PACKAGE_BUGREPORT='users@clusterlabs.org'
 PACKAGE_URL=''
 
@@ -700,15 +700,14 @@
 HAVE_QB_LOG_FILE_REOPEN_TRUE
 LIBQB_LIBS
 LIBQB_CFLAGS
-PKG_CONFIG_LIBDIR
-PKG_CONFIG_PATH
-PKG_CONFIG
 BASHPATH
 DOXYGEN
 DOT
 AUGTOOL
-PKGCONFIG
 GROFF
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
 WITH_LIST
 OTOOL64
 OTOOL
@@ -1424,7 +1423,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures corosync 3.1.0 to adapt to many kinds of systems.
+\`configure' configures corosync 3.1.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1494,7 +1493,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of corosync 3.1.0:";;
+     short | recursive ) echo "Configuration of corosync 3.1.2:";;
    esac
   cat <<\_ACEOF
 
@@ -1654,7 +1653,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-corosync configure 3.1.0
+corosync configure 3.1.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2264,7 +2263,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by corosync $as_me 3.1.0, which was
+It was created by corosync $as_me 3.1.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4443,7 +4442,7 @@
 
 # Define the identity of the package.
  PACKAGE='corosync'
- VERSION='3.1.0'
+ VERSION='3.1.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -11912,16 +11911,12 @@
 	fi
 fi
 
-if test "$srcdir" = "."; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: building in place srcdir:$srcdir" >&5
-$as_echo "$as_me: building in place srcdir:$srcdir" >&6;}
-
-$as_echo "#define BUILDING_IN_PLACE 1" >>confdefs.h
-
-else
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: building out of tree srcdir:$srcdir" >&5
-$as_echo "$as_me: building out of tree srcdir:$srcdir" >&6;}
-fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: Sanitizing exec_prefix: ${exec_prefix}" >&5
+$as_echo "$as_me: Sanitizing exec_prefix: ${exec_prefix}" >&6;}
+case $exec_prefix in
+    NONE)   exec_prefix=$prefix;;
+  prefix) exec_prefix=$prefix;;
+esac
 
 # Checks for programs.
 
@@ -12764,26 +12759,34 @@
   rm -f conftest.sed
 
 
-for ac_prog in groff
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_GROFF+:} false; then :
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$GROFF"; then
-  ac_cv_prog_GROFF="$GROFF" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_GROFF="$ac_prog"
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -12791,32 +12794,102 @@
   done
 IFS=$as_save_IFS
 
+  ;;
+esac
 fi
-fi
-GROFF=$ac_cv_prog_GROFF
-if test -n "$GROFF"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5
-$as_echo "$GROFF" >&6; }
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
-  test -n "$GROFF" && break
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
 done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.9.0
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+fi
 
-for ac_prog in pkg-config
+for ac_prog in groff
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_PKGCONFIG+:} false; then :
+if ${ac_cv_prog_GROFF+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  if test -n "$PKGCONFIG"; then
-  ac_cv_prog_PKGCONFIG="$PKGCONFIG" # Let the user override the test.
+  if test -n "$GROFF"; then
+  ac_cv_prog_GROFF="$GROFF" # Let the user override the test.
 else
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
 for as_dir in $PATH
@@ -12825,7 +12898,7 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_PKGCONFIG="$ac_prog"
+    ac_cv_prog_GROFF="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -12835,17 +12908,17 @@
 
 fi
 fi
-PKGCONFIG=$ac_cv_prog_PKGCONFIG
-if test -n "$PKGCONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
-$as_echo "$PKGCONFIG" >&6; }
+GROFF=$ac_cv_prog_GROFF
+if test -n "$GROFF"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5
+$as_echo "$GROFF" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
 
 
-  test -n "$PKGCONFIG" && break
+  test -n "$GROFF" && break
 done
 
 for ac_prog in augtool
@@ -13815,126 +13888,6 @@
 SAVE_CPPFLAGS="$CPPFLAGS"
 SAVE_LIBS="$LIBS"
 
-
-
-
-
-
-
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
-	if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
-set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PKG_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $PKG_CONFIG in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
-if test -n "$PKG_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
-$as_echo "$PKG_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_path_PKG_CONFIG"; then
-  ac_pt_PKG_CONFIG=$PKG_CONFIG
-  # Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  case $ac_pt_PKG_CONFIG in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
-if test -n "$ac_pt_PKG_CONFIG"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
-$as_echo "$ac_pt_PKG_CONFIG" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_pt_PKG_CONFIG" = x; then
-    PKG_CONFIG=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    PKG_CONFIG=$ac_pt_PKG_CONFIG
-  fi
-else
-  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
-fi
-
-fi
-if test -n "$PKG_CONFIG"; then
-	_pkg_min_version=0.9.0
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
-$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
-	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-	else
-		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-		PKG_CONFIG=""
-	fi
-fi
-
 pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBQB" >&5
 $as_echo_n "checking for LIBQB... " >&6; }
@@ -14561,6 +14514,50 @@
 
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for knet_handle_get_onwire_ver in -lknet" >&5
+$as_echo_n "checking for knet_handle_get_onwire_ver in -lknet... " >&6; }
+if ${ac_cv_lib_knet_knet_handle_get_onwire_ver+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lknet  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char knet_handle_get_onwire_ver ();
+int
+main ()
+{
+return knet_handle_get_onwire_ver ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_knet_knet_handle_get_onwire_ver=yes
+else
+  ac_cv_lib_knet_knet_handle_get_onwire_ver=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_knet_knet_handle_get_onwire_ver" >&5
+$as_echo "$ac_cv_lib_knet_knet_handle_get_onwire_ver" >&6; }
+if test "x$ac_cv_lib_knet_knet_handle_get_onwire_ver" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_KNET_ONWIRE_VER 1
+_ACEOF
+
+fi
+
 LIBS="$OLDLIBS"
 
 # Checks for library functions.
@@ -15630,20 +15627,6 @@
 	return $RC
 }
 
-## cleanup
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Sanitizing prefix: ${prefix}" >&5
-$as_echo "$as_me: Sanitizing prefix: ${prefix}" >&6;}
-case $prefix in
-  NONE) prefix=/usr/local;;
-esac
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Sanitizing exec_prefix: ${exec_prefix}" >&5
-$as_echo "$as_me: Sanitizing exec_prefix: ${exec_prefix}" >&6;}
-case $exec_prefix in
-    NONE)   exec_prefix=$prefix;;
-  prefix) exec_prefix=$prefix;;
-esac
-
 ## local defines
 PACKAGE_FEATURES=""
 
@@ -15657,7 +15640,7 @@
 SONAME="${SOMAJOR}.${SOMINOR}.${SOMICRO}"
 
 # specific libraries SONAME
-CFG_SONAME="7.1.0"
+CFG_SONAME="7.3.0"
 CPG_SONAME="4.1.0"
 QUORUM_SONAME="5.1.0"
 SAM_SONAME="4.4.0"
@@ -17671,7 +17654,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by corosync $as_me 3.1.0, which was
+This file was extended by corosync $as_me 3.1.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -17737,7 +17720,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-corosync config.status 3.1.0
+corosync config.status 3.1.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -Nru corosync-3.1.0/configure.ac corosync-3.1.2/configure.ac
--- corosync-3.1.0/configure.ac	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/configure.ac	2021-03-29 14:07:44.000000000 +0200
@@ -69,12 +69,12 @@
 	fi
 fi
 
-if test "$srcdir" = "."; then
-	AC_MSG_NOTICE([building in place srcdir:$srcdir])
-	AC_DEFINE([BUILDING_IN_PLACE], 1, [building in place])
-else
-	AC_MSG_NOTICE([building out of tree srcdir:$srcdir])
-fi
+AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
+case $exec_prefix in
+  dnl For consistency with Corosync, map NONE->$prefix
+  NONE)   exec_prefix=$prefix;;
+  prefix) exec_prefix=$prefix;;
+esac
 
 # Checks for programs.
 
@@ -94,9 +94,9 @@
 AC_PROG_LN_S
 AC_PROG_MAKE_SET
 AC_PROG_SED
+PKG_PROG_PKG_CONFIG
 
 AC_CHECK_PROGS([GROFF], [groff])
-AC_CHECK_PROGS([PKGCONFIG], [pkg-config])
 AC_CHECK_PROGS([AUGTOOL], [augtool])
 AC_CHECK_PROGS([DOT], [dot])
 AC_CHECK_PROGS([DOXYGEN], [doxygen])
@@ -194,6 +194,8 @@
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_ACCESS_LIST], 1, [have knet access list])])
 AC_CHECK_LIB([knet],[knet_handle_crypto_set_config],
 	     [AC_DEFINE_UNQUOTED([HAVE_KNET_CRYPTO_RECONF], 1, [have knet crypto reconfig support])])
+AC_CHECK_LIB([knet],[knet_handle_get_onwire_ver],
+	     [AC_DEFINE_UNQUOTED([HAVE_KNET_ONWIRE_VER], 1, [have knet onwire versioning])])
 LIBS="$OLDLIBS"
 
 # Checks for library functions.
@@ -286,19 +288,6 @@
 	return $RC
 }
 
-## cleanup
-AC_MSG_NOTICE(Sanitizing prefix: ${prefix})
-case $prefix in
-  NONE) prefix=/usr/local;;
-esac
-
-AC_MSG_NOTICE(Sanitizing exec_prefix: ${exec_prefix})
-case $exec_prefix in
-  dnl For consistency with Corosync, map NONE->$prefix
-  NONE)   exec_prefix=$prefix;;
-  prefix) exec_prefix=$prefix;;
-esac
-
 ## local defines
 PACKAGE_FEATURES=""
 
diff -Nru corosync-3.1.0/corosync.spec.in corosync-3.1.2/corosync.spec.in
--- corosync-3.1.0/corosync.spec.in	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/corosync.spec.in	2021-03-11 14:42:58.000000000 +0100
@@ -248,7 +248,8 @@
 Summary: The Corosync Cluster Engine Development Kit
 Requires: corosynclib%{?_isa} = %{version}-%{release}
 Requires: pkgconfig
-Provides: corosync-devel = %{version}
+Provides: corosync-devel = %{version}-%{release}
+Provides: corosync-devel%{?_isa} = %{version}-%{release}
 
 %description -n corosynclib-devel
 This package contains include files and man pages used to develop using
diff -Nru corosync-3.1.0/debian/changelog corosync-3.1.2/debian/changelog
--- corosync-3.1.0/debian/changelog	2021-02-28 10:06:39.000000000 +0100
+++ corosync-3.1.2/debian/changelog	2021-04-07 14:19:13.000000000 +0200
@@ -1,3 +1,22 @@
+corosync (3.1.2-1) unstable; urgency=medium
+
+  * [2c66d6d] New upstream release (3.1.2)
+  * [158e261] Drop upstreamed patch, refresh the rest
+
+ -- Ferenc Wágner <wferi@debian.org>  Wed, 07 Apr 2021 14:19:13 +0200
+
+corosync (3.1.1-1) unstable; urgency=medium
+
+  * [d0fe5b2] New upstream release (3.1.1) (Closes: #985070)
+  * [e867d55] Refresh our patches
+  * [9d9b3d5] Acknowledge new symbols
+  * [069e608] Adapt autopkgtest to the new cfgtool output format
+  * [a447ac3] New patch: totemknet: pass correct handle to knet_handle_compress.
+    Thanks to Fabio M. Di Nitto (Closes: #986325)
+  * [dc2b18f] New patch: man: corosync-cfgtool.8: use proper single quotes
+
+ -- Ferenc Wágner <wferi@debian.org>  Sat, 03 Apr 2021 17:27:29 +0200
+
 corosync (3.1.0-3) unstable; urgency=medium
 
   [ Helmut Grohne ]
diff -Nru corosync-3.1.0/debian/libcfg7.symbols corosync-3.1.2/debian/libcfg7.symbols
--- corosync-3.1.0/debian/libcfg7.symbols	2020-12-26 17:43:38.000000000 +0100
+++ corosync-3.1.2/debian/libcfg7.symbols	2021-04-03 13:29:49.000000000 +0200
@@ -8,8 +8,11 @@
  corosync_cfg_initialize@COROSYNC_CFG_0.82 2.99.5
  corosync_cfg_kill_node@Base 2.99.5
  corosync_cfg_local_get@Base 2.99.5
+ corosync_cfg_node_status_get@COROSYNC_CFG_0.82 3.1.1
  corosync_cfg_reload_config@Base 2.99.5
  corosync_cfg_reopen_log_files@Base 2.99.5
  corosync_cfg_replyto_shutdown@Base 2.99.5
  corosync_cfg_ring_status_get@COROSYNC_CFG_0.82 2.99.5
+ corosync_cfg_trackstart@COROSYNC_CFG_0.82 3.1.1
+ corosync_cfg_trackstop@COROSYNC_CFG_0.82 3.1.1
  corosync_cfg_try_shutdown@Base 2.99.5
diff -Nru corosync-3.1.0/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch corosync-3.1.2/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch
--- corosync-3.1.0/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch	2020-12-26 17:42:01.000000000 +0100
+++ corosync-3.1.2/debian/patches/Enable-PrivateTmp-in-the-systemd-service-files.patch	2021-04-07 14:18:49.000000000 +0200
@@ -20,10 +20,10 @@
  [Install]
  WantedBy=multi-user.target
 diff --git a/init/corosync.service.in b/init/corosync.service.in
-index 654e41f..0c74306 100644
+index bd2a48a..f59bddb 100644
 --- a/init/corosync.service.in
 +++ b/init/corosync.service.in
-@@ -28,6 +28,7 @@ StandardError=null
+@@ -29,6 +29,7 @@ StandardError=null
  #RestartSec=70
  #  rewrite according to environment.
  #ExecStartPre=/sbin/modprobe softdog
diff -Nru corosync-3.1.0/debian/patches/Fix-various-typos-in-ChangeLog.patch corosync-3.1.2/debian/patches/Fix-various-typos-in-ChangeLog.patch
--- corosync-3.1.0/debian/patches/Fix-various-typos-in-ChangeLog.patch	2020-12-26 17:42:01.000000000 +0100
+++ corosync-3.1.2/debian/patches/Fix-various-typos-in-ChangeLog.patch	2021-04-07 14:18:49.000000000 +0200
@@ -10,10 +10,10 @@
  1 file changed, 8 insertions(+), 8 deletions(-)
 
 diff --git a/ChangeLog b/ChangeLog
-index 700a9c0..6444ea7 100644
+index dc9d199..2e87a72 100644
 --- a/ChangeLog
 +++ b/ChangeLog
-@@ -9188,7 +9188,7 @@
+@@ -9387,7 +9387,7 @@
  
  2012-02-07  Fabio M. Di Nitto  <fdinitto@redhat.com>
  
@@ -22,7 +22,7 @@
  	Reviewed-by: Christine Caulfield <ccaulfie@redhat.com>
  
  2012-02-07  Angus Salkeld  <asalkeld@redhat.com>
-@@ -9373,7 +9373,7 @@
+@@ -9572,7 +9572,7 @@
  
  	Honor exec_init_fn call
  	exec_init_fn now either returns NULL (success) or a string which indicates
@@ -31,7 +31,7 @@
  	occurs, corosync will exit.  This patch adds ykd and makes other suggestions
  	from Fabio Di Nitto.
  
-@@ -10737,7 +10737,7 @@
+@@ -10936,7 +10936,7 @@
  
  	start 5 nodes randomly at about same time, start 5 nodes randomly at about
  	same time, wait 10 seconds and attempt to send a message.  If message blocks
@@ -40,7 +40,7 @@
  	cyclng the nodes and see if the TRY_AGAIN state becomes unblocked.
  
  	If it doesn't the test case has failed
-@@ -11128,7 +11128,7 @@
+@@ -11327,7 +11327,7 @@
  	is these last messages should be delivered after a transitional
  	configuration to maintain SAFE agreement.  We don't have support for
  	SAFE atm, so it is probably safe just to throw these messages away.  Without
@@ -49,7 +49,7 @@
  
  	Tested-by: Tim Beale <tlbeale@gmail.com>
  	Reviewed-by: Jan Friesse <jfriesse@redhat.com>
-@@ -18876,7 +18876,7 @@
+@@ -19075,7 +19075,7 @@
  
  2007-08-11  Steven Dake  <sdake@redhat.com>
  
@@ -58,7 +58,7 @@
  	git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1420 fd59a12c-fef9-0310-b244-a6a79926bd2f
  
  	Allow make doxygen to work properly
-@@ -19219,7 +19219,7 @@
+@@ -19418,7 +19418,7 @@
  
  2006-11-10  Steven Dake  <sdake@redhat.com>
  
@@ -67,7 +67,7 @@
  	git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1299 fd59a12c-fef9-0310-b244-a6a79926bd2f
  
  	Recovery algorithms described in this document.
-@@ -25393,13 +25393,13 @@
+@@ -25592,13 +25592,13 @@
  
  2004-07-12  Steven Dake  <sdake@broked.org>
  
diff -Nru corosync-3.1.0/debian/patches/man-corosync-cfgtool.8-use-proper-single-quotes.patch corosync-3.1.2/debian/patches/man-corosync-cfgtool.8-use-proper-single-quotes.patch
--- corosync-3.1.0/debian/patches/man-corosync-cfgtool.8-use-proper-single-quotes.patch	1970-01-01 01:00:00.000000000 +0100
+++ corosync-3.1.2/debian/patches/man-corosync-cfgtool.8-use-proper-single-quotes.patch	2021-04-07 14:18:49.000000000 +0200
@@ -0,0 +1,28 @@
+From: =?utf-8?q?Ferenc_W=C3=A1gner?= <wferi@debian.org>
+Date: Sat, 3 Apr 2021 13:14:28 +0200
+Subject: man: corosync-cfgtool.8: use proper single quotes
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+Apostrophe as the first character of the input line indicates a
+request, so groff complained: macro 'onwire'' not defined.
+
+Signed-off-by: Ferenc Wágner <wferi@debian.org>
+---
+ man/corosync-cfgtool.8 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/man/corosync-cfgtool.8 b/man/corosync-cfgtool.8
+index 1198213..b83f899 100644
+--- a/man/corosync-cfgtool.8
++++ b/man/corosync-cfgtool.8
+@@ -88,7 +88,7 @@ nodeid: 2 reachable   onwire (min/max/cur): 0, 1, 1
+ .P
+ Only reachable nodes are displayed so "reachable" should always be there.
+ .br
+-'onwire' versions are the knet on-wire versions that are supported/in use (where appropriate).
++\(oqonwire\(cq versions are the knet on-wire versions that are supported/in use (where appropriate).
+ .br
+ IP addresses are the local and remote IP addresses (for UDP[U] only the local IP address is shown)
+ .br
diff -Nru corosync-3.1.0/debian/patches/series corosync-3.1.2/debian/patches/series
--- corosync-3.1.0/debian/patches/series	2020-12-26 17:42:01.000000000 +0100
+++ corosync-3.1.2/debian/patches/series	2021-04-07 14:18:49.000000000 +0200
@@ -1,3 +1,4 @@
 Fix-various-typos-in-ChangeLog.patch
 Enable-PrivateTmp-in-the-systemd-service-files.patch
 Make-the-example-config-valid.patch
+man-corosync-cfgtool.8-use-proper-single-quotes.patch
diff -Nru corosync-3.1.0/debian/tests/cfgtool corosync-3.1.2/debian/tests/cfgtool
--- corosync-3.1.0/debian/tests/cfgtool	2020-12-26 17:42:01.000000000 +0100
+++ corosync-3.1.2/debian/tests/cfgtool	2021-04-07 14:14:49.000000000 +0200
@@ -6,4 +6,4 @@
 
 corosync-cfgtool -s >"$OUTPUT"
 cat "$OUTPUT"
-grep -q '^		nodeid  1:	localhost$' "$OUTPUT"
+grep -q '^[[:blank:]]*nodeid:[[:blank:]]*1:[[:blank:]]*localhost$' "$OUTPUT"
diff -Nru corosync-3.1.0/exec/cfg.c corosync-3.1.2/exec/cfg.c
--- corosync-3.1.0/exec/cfg.c	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/exec/cfg.c	2021-03-29 14:07:44.000000000 +0200
@@ -55,6 +55,7 @@
 #include <qb/qbipc_common.h>
 #include <corosync/cfg.h>
 #include <qb/qblist.h>
+#include <qb/qbutil.h>
 #include <corosync/mar_gen.h>
 #include <corosync/totem/totemip.h>
 #include <corosync/totem/totem.h>
@@ -65,6 +66,7 @@
 #include <corosync/corodefs.h>
 
 #include "totemconfig.h"
+#include "totemknet.h"
 #include "service.h"
 #include "main.h"
 
@@ -78,7 +80,8 @@
 	MESSAGE_REQ_EXEC_CFG_CRYPTO_RECONFIG = 4
 };
 
-#define DEFAULT_SHUTDOWN_TIMEOUT 5
+/* in milliseconds */
+#define DEFAULT_SHUTDOWN_TIMEOUT 5000
 
 static struct qb_list_head trackers_list;
 
@@ -141,6 +144,10 @@
 	void *conn,
 	const void *msg);
 
+static void message_handler_req_lib_cfg_nodestatusget (
+	void *conn,
+	const void *msg);
+
 static void message_handler_req_lib_cfg_ringreenable (
 	void *conn,
 	const void *msg);
@@ -157,6 +164,14 @@
 	void *conn,
 	const void *msg);
 
+static void message_handler_req_lib_cfg_trackstart (
+	void *conn,
+	const void *msg);
+
+static void message_handler_req_lib_cfg_trackstop (
+	void *conn,
+	const void *msg);
+
 static void message_handler_req_lib_cfg_get_node_addrs (
 	void *conn,
 	const void *msg);
@@ -213,7 +228,20 @@
 	{ /* 8 */
 		.lib_handler_fn		= message_handler_req_lib_cfg_reopen_log_files,
 		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
-	}
+	},
+	{ /* 9 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_nodestatusget,
+		.flow_control		= CS_LIB_FLOW_CONTROL_NOT_REQUIRED
+	},
+	{ /* 10 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_trackstart,
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
+	},
+	{ /* 11 */
+		.lib_handler_fn		= message_handler_req_lib_cfg_trackstop,
+		.flow_control		= CS_LIB_FLOW_CONTROL_REQUIRED
+	},
+
 };
 
 static struct corosync_exec_handler cfg_exec_engine[] =
@@ -612,6 +640,7 @@
 	delete_and_notify_if_changed(temp_map, "totem.cluster_name");
 	delete_and_notify_if_changed(temp_map, "quorum.provider");
 	delete_and_notify_if_changed(temp_map, "system.move_to_root_cgroup");
+	delete_and_notify_if_changed(temp_map, "system.allow_knet_handle_fallback");
 	delete_and_notify_if_changed(temp_map, "system.sched_rr");
 	delete_and_notify_if_changed(temp_map, "system.priority");
 	delete_and_notify_if_changed(temp_map, "system.qb_ipc_type");
@@ -957,6 +986,132 @@
 	LEAVE();
 }
 
+
+static void message_handler_req_lib_cfg_nodestatusget (
+	void *conn,
+	const void *msg)
+{
+	struct res_lib_cfg_nodestatusget_version res_lib_cfg_nodestatusget_version;
+	struct res_lib_cfg_nodestatusget_v1 res_lib_cfg_nodestatusget_v1;
+	void *res_lib_cfg_nodestatusget_ptr = NULL;
+	size_t res_lib_cfg_nodestatusget_size;
+	struct req_lib_cfg_nodestatusget *req_lib_cfg_nodestatusget = (struct req_lib_cfg_nodestatusget *)msg;
+	struct totem_node_status node_status;
+	int i;
+
+	ENTER();
+
+	memset(&node_status, 0, sizeof(node_status));
+	if (totempg_nodestatus_get(req_lib_cfg_nodestatusget->nodeid, &node_status) != 0) {
+		res_lib_cfg_nodestatusget_ptr = &res_lib_cfg_nodestatusget_version;
+		res_lib_cfg_nodestatusget_size = sizeof(res_lib_cfg_nodestatusget_version);
+
+		res_lib_cfg_nodestatusget_version.header.error = CS_ERR_FAILED_OPERATION;
+		res_lib_cfg_nodestatusget_version.header.id = MESSAGE_RES_CFG_NODESTATUSGET;
+		res_lib_cfg_nodestatusget_version.header.size = res_lib_cfg_nodestatusget_size;
+
+		goto ipc_response_send;
+	}
+
+	/* Currently only one structure version supported */
+	switch (req_lib_cfg_nodestatusget->version) {
+	case CFG_NODE_STATUS_V1:
+		res_lib_cfg_nodestatusget_ptr = &res_lib_cfg_nodestatusget_v1;
+		res_lib_cfg_nodestatusget_size = sizeof(res_lib_cfg_nodestatusget_v1);
+
+		res_lib_cfg_nodestatusget_v1.header.error = CS_OK;
+		res_lib_cfg_nodestatusget_v1.header.id = MESSAGE_RES_CFG_NODESTATUSGET;
+		res_lib_cfg_nodestatusget_v1.header.size = res_lib_cfg_nodestatusget_size;
+
+		res_lib_cfg_nodestatusget_v1.node_status.version = CFG_NODE_STATUS_V1;
+		res_lib_cfg_nodestatusget_v1.node_status.nodeid = req_lib_cfg_nodestatusget->nodeid;
+		res_lib_cfg_nodestatusget_v1.node_status.reachable = node_status.reachable;
+		res_lib_cfg_nodestatusget_v1.node_status.remote = node_status.remote;
+		res_lib_cfg_nodestatusget_v1.node_status.external = node_status.external;
+		res_lib_cfg_nodestatusget_v1.node_status.onwire_min = node_status.onwire_min;
+		res_lib_cfg_nodestatusget_v1.node_status.onwire_max = node_status.onwire_max;
+		res_lib_cfg_nodestatusget_v1.node_status.onwire_ver = node_status.onwire_ver;
+
+		for (i=0; i < KNET_MAX_LINK; i++) {
+			res_lib_cfg_nodestatusget_v1.node_status.link_status[i].enabled = node_status.link_status[i].enabled;
+			res_lib_cfg_nodestatusget_v1.node_status.link_status[i].connected = node_status.link_status[i].connected;
+			res_lib_cfg_nodestatusget_v1.node_status.link_status[i].dynconnected = node_status.link_status[i].dynconnected;
+			res_lib_cfg_nodestatusget_v1.node_status.link_status[i].mtu = node_status.link_status[i].mtu;
+			memcpy(res_lib_cfg_nodestatusget_v1.node_status.link_status[i].src_ipaddr,
+			       node_status.link_status[i].src_ipaddr, CFG_MAX_HOST_LEN);
+			memcpy(res_lib_cfg_nodestatusget_v1.node_status.link_status[i].dst_ipaddr,
+			       node_status.link_status[i].dst_ipaddr, CFG_MAX_HOST_LEN);
+		}
+		break;
+	default:
+		/*
+		 * Unsupported version requested
+		 */
+		res_lib_cfg_nodestatusget_ptr = &res_lib_cfg_nodestatusget_version;
+		res_lib_cfg_nodestatusget_size = sizeof(res_lib_cfg_nodestatusget_version);
+
+		res_lib_cfg_nodestatusget_version.header.error = CS_ERR_NOT_SUPPORTED;
+		res_lib_cfg_nodestatusget_version.header.id = MESSAGE_RES_CFG_NODESTATUSGET;
+		res_lib_cfg_nodestatusget_version.header.size = res_lib_cfg_nodestatusget_size;
+		break;
+	}
+
+ipc_response_send:
+	api->ipc_response_send (
+		conn,
+		res_lib_cfg_nodestatusget_ptr,
+		res_lib_cfg_nodestatusget_size);
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_cfg_trackstart (
+	void *conn,
+	const void *msg)
+{
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+	struct res_lib_cfg_trackstart res_lib_cfg_trackstart;
+
+	ENTER();
+
+	/*
+	 * We only do shutdown tracking at the moment
+	 */
+	if (qb_list_empty(&ci->list)) {
+		qb_list_add(&ci->list, &trackers_list);
+		ci->tracker_conn = conn;
+
+		if (shutdown_con) {
+			/*
+			 * Shutdown already in progress, ask the newcomer's opinion
+			 */
+			ci->shutdown_reply = SHUTDOWN_REPLY_UNKNOWN;
+			shutdown_expected++;
+			send_test_shutdown(conn, NULL, CS_OK);
+		}
+	}
+
+	res_lib_cfg_trackstart.header.size = sizeof(struct res_lib_cfg_trackstart);
+	res_lib_cfg_trackstart.header.id = MESSAGE_RES_CFG_STATETRACKSTART;
+	res_lib_cfg_trackstart.header.error = CS_OK;
+
+	api->ipc_response_send(conn, &res_lib_cfg_trackstart,
+				    sizeof(res_lib_cfg_trackstart));
+
+	LEAVE();
+}
+
+static void message_handler_req_lib_cfg_trackstop (
+	void *conn,
+	const void *msg)
+{
+	struct cfg_info *ci = (struct cfg_info *)api->ipc_private_data_get (conn);
+
+	ENTER();
+	remove_ci_from_shutdown(ci);
+	LEAVE();
+}
+
 static void message_handler_req_lib_cfg_ringreenable (
 	void *conn,
 	const void *msg)
@@ -1151,7 +1306,7 @@
 		 * Start the timer. If we don't get a full set of replies before this goes
 		 * off we'll cancel the shutdown
 		 */
-		api->timer_add_duration((unsigned long long)shutdown_timeout*1000000000, NULL,
+		api->timer_add_duration((unsigned long long)shutdown_timeout*QB_TIME_NS_IN_MSEC, NULL,
 					shutdown_timer_fn, &shutdown_timer);
 
 		/*
diff -Nru corosync-3.1.0/exec/coroparse.c corosync-3.1.2/exec/coroparse.c
--- corosync-3.1.0/exec/coroparse.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/coroparse.c	2021-03-29 14:07:44.000000000 +0200
@@ -808,6 +808,14 @@
 					return (0);
 				}
 			}
+			if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
+				if ((strcmp(value, "yes") != 0) &&
+				    (strcmp(value, "no") != 0)) {
+					*error_string = "Invalid system.allow_knet_handle_fallback";
+
+					return (0);
+				}
+			}
 			break;
 
 		case MAIN_CP_CB_DATA_STATE_INTERFACE:
diff -Nru corosync-3.1.0/exec/main.c corosync-3.1.2/exec/main.c
--- corosync-3.1.0/exec/main.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/main.c	2021-03-29 14:07:44.000000000 +0200
@@ -167,6 +167,8 @@
 
 static char corosync_config_file[PATH_MAX + 1] = COROSYSCONFDIR "/corosync.conf";
 
+static int lockfile_fd = -1;
+
 qb_loop_t *cs_poll_handle_get (void)
 {
 	return (corosync_poll_handle);
@@ -473,7 +475,12 @@
 #define RLIMIT_MEMLOCK RLIMIT_VMEM
 #endif
 
-	setrlimit (RLIMIT_MEMLOCK, &rlimit);
+	res = setrlimit (RLIMIT_MEMLOCK, &rlimit);
+	if (res == -1) {
+		LOGSYS_PERROR (errno, LOGSYS_LEVEL_WARNING,
+			"Could not increase RLIMIT_MEMLOCK, not locking memory");
+		return;
+	}
 
 	res = mlockall (MCL_CURRENT | MCL_FUTURE);
 	if (res == -1) {
@@ -640,7 +647,7 @@
 
 	snprintf (filename, sizeof(filename), "%s/ringid_%u",
 		get_state_dir(), nodeid);
-	fd = open (filename, O_RDONLY, 0700);
+	fd = open (filename, O_RDONLY);
 	/*
 	 * If file can be opened and read, read the ring id
 	 */
@@ -653,8 +660,7 @@
 	 */
 	if ((fd == -1) || (res != sizeof (uint64_t))) {
 		memb_ring_id->seq = 0;
-		umask(0);
-		fd = open (filename, O_CREAT|O_RDWR, 0700);
+		fd = creat (filename, 0600);
 		if (fd != -1) {
 			res = write (fd, &memb_ring_id->seq, sizeof (uint64_t));
 			close (fd);
@@ -686,10 +692,7 @@
 	snprintf (filename, sizeof(filename), "%s/ringid_%u",
 		get_state_dir(), nodeid);
 
-	fd = open (filename, O_WRONLY, 0700);
-	if (fd == -1) {
-		fd = open (filename, O_CREAT|O_RDWR, 0700);
-	}
+	fd = creat (filename, 0600);
 	if (fd == -1) {
 		LOGSYS_PERROR(errno, LOGSYS_LEVEL_ERROR,
 			"Couldn't store new ring id " CS_PRI_RING_ID_SEQ " to stable storage",
@@ -1086,12 +1089,11 @@
 	enum e_corosync_done err;
 	char pid_s[17];
 	int fd_flag;
-	int lf;
 
 	err = COROSYNC_DONE_EXIT;
 
-	lf = open (lockfile, O_WRONLY | O_CREAT, 0640);
-	if (lf == -1) {
+	lockfile_fd = open (lockfile, O_WRONLY | O_CREAT, 0640);
+	if (lockfile_fd == -1) {
 		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't create lock file.");
 		return (COROSYNC_DONE_ACQUIRE_LOCK);
 	}
@@ -1101,7 +1103,7 @@
 	lock.l_start = 0;
 	lock.l_whence = SEEK_SET;
 	lock.l_len = 0;
-	if (fcntl (lf, F_SETLK, &lock) == -1) {
+	if (fcntl (lockfile_fd, F_SETLK, &lock) == -1) {
 		switch (errno) {
 		case EINTR:
 			goto retry_fcntl;
@@ -1121,7 +1123,7 @@
 		}
 	}
 
-	if (ftruncate (lf, 0) == -1) {
+	if (ftruncate (lockfile_fd, 0) == -1) {
 		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't truncate lock file. Error was %s",
 		    strerror (errno));
 		err = COROSYNC_DONE_ACQUIRE_LOCK;
@@ -1132,7 +1134,7 @@
 	snprintf (pid_s, sizeof (pid_s) - 1, "%u\n", pid);
 
 retry_write:
-	if (write (lf, pid_s, strlen (pid_s)) != strlen (pid_s)) {
+	if (write (lockfile_fd, pid_s, strlen (pid_s)) != strlen (pid_s)) {
 		if (errno == EINTR) {
 			goto retry_write;
 		} else {
@@ -1143,14 +1145,14 @@
 		}
 	}
 
-	if ((fd_flag = fcntl (lf, F_GETFD, 0)) == -1) {
+	if ((fd_flag = fcntl (lockfile_fd, F_GETFD, 0)) == -1) {
 		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't get close-on-exec flag from lock file. "
 			"Error was %s", strerror (errno));
 		err = COROSYNC_DONE_ACQUIRE_LOCK;
 		goto error_close_unlink;
 	}
 	fd_flag |= FD_CLOEXEC;
-	if (fcntl (lf, F_SETFD, fd_flag) == -1) {
+	if (fcntl (lockfile_fd, F_SETFD, fd_flag) == -1) {
 		log_printf (LOGSYS_LEVEL_ERROR, "Corosync Executive couldn't set close-on-exec flag to lock file. "
 			"Error was %s", strerror (errno));
 		err = COROSYNC_DONE_ACQUIRE_LOCK;
@@ -1162,7 +1164,7 @@
 error_close_unlink:
 	unlink (lockfile);
 error_close:
-	close (lf);
+	close (lockfile_fd);
 
 	return (err);
 }
@@ -1219,7 +1221,6 @@
 	struct totem_config totem_config;
 	int res, ch;
 	int background, sched_rr, prio, testonly, move_to_root_cgroup;
-	struct stat stat_out;
 	enum e_corosync_done flock_err;
 	uint64_t totem_config_warnings;
 	struct scheduler_pause_timeout_data scheduler_pause_timeout_data;
@@ -1337,19 +1338,9 @@
 			"totemip.c,totemconfig.c,totemcrypto.c,totemsrp.c,"
 			"totempg.c,totemudp.c,totemudpu.c,totemnet.c,totemknet.c");
 
-	/*
-	 * Make sure required directory is present
-	 */
-	res = stat (get_state_dir(), &stat_out);
-	if ((res == -1) || (res == 0 && !S_ISDIR(stat_out.st_mode))) {
-		log_printf (LOGSYS_LEVEL_ERROR, "State directory %s not present.  Please create it.", get_state_dir());
-		corosync_exit_error (COROSYNC_DONE_DIR_NOT_PRESENT);
-	}
-
 	res = chdir(get_state_dir());
 	if (res == -1) {
-		log_printf (LOGSYS_LEVEL_ERROR, "Cannot chdir to state directory %s.  "
-		    "Please make sure it has correct context and rights.", get_state_dir());
+		log_printf (LOGSYS_LEVEL_ERROR, "Cannot chdir to state directory %s. %s", get_state_dir(), strerror(errno));
 		corosync_exit_error (COROSYNC_DONE_DIR_NOT_PRESENT);
 	}
 
@@ -1580,6 +1571,7 @@
 	/*
 	 * Remove pid lock file
 	 */
+	close (lockfile_fd);
 	unlink (corosync_lock_file);
 
 	corosync_exit_error (COROSYNC_DONE_EXIT);
diff -Nru corosync-3.1.0/exec/Makefile.in corosync-3.1.2/exec/Makefile.in
--- corosync-3.1.0/exec/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/exec/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -303,7 +303,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/exec/totemconfig.c corosync-3.1.2/exec/totemconfig.c
--- corosync-3.1.0/exec/totemconfig.c	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/exec/totemconfig.c	2021-03-29 14:07:44.000000000 +0200
@@ -81,6 +81,8 @@
 #define MAX_MESSAGES				17
 #define MISS_COUNT_CONST			5
 #define BLOCK_UNLISTED_IPS			1
+/* This constant is not used for knet */
+#define UDP_NETMTU                              1500
 
 /* Currently all but PONG_COUNT match the defaults in libknet.h */
 #define KNET_PING_INTERVAL                      1000
@@ -649,11 +651,11 @@
 			char *dot;
 			dot = strchr(name, '.');
 			if (dot) {
-				namelen = name - dot - 1;
+				namelen = dot - name;
 			}
 		}
 		if (strncmp(find_name, name, namelen) == 0 &&
-		    strlen(find_name) == strlen(name)) {
+		    strlen(find_name) == namelen) {
 			icmap_iter_finalize(iter);
 			return node_pos;
 		}
@@ -2099,7 +2101,7 @@
 			totem_config->net_mtu = KNET_MAX_PACKET_SIZE;
 		}
 		else {
-			totem_config->net_mtu = 1500;
+			totem_config->net_mtu = UDP_NETMTU;
 		}
 	}
 
diff -Nru corosync-3.1.0/exec/totemknet.c corosync-3.1.2/exec/totemknet.c
--- corosync-3.1.0/exec/totemknet.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemknet.c	2021-04-06 11:09:02.000000000 +0200
@@ -197,7 +197,7 @@
 
 
 static int totemknet_configure_compression (
-	void *knet_context,
+	struct totemknet_instance *instance,
 	struct totem_config *totem_config);
 
 static void totemknet_start_merge_detect_timeout(
@@ -488,6 +488,83 @@
 #define OWN_INDEX_NONE -1
 #endif
 
+int totemknet_nodestatus_get (
+	void *knet_context,
+	unsigned int nodeid,
+	struct totem_node_status *node_status)
+{
+	int i;
+	int res = 0;
+	struct knet_link_status link_status;
+	struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
+	struct knet_host_status knet_host_status;
+	uint8_t link_list[KNET_MAX_LINK];
+	size_t num_links;
+
+	if (!instance->knet_handle) {
+		return CS_ERR_NOT_EXIST; /* Not using knet */
+	}
+
+	if (!node_status) {
+		return CS_ERR_INVALID_PARAM;
+	}
+
+	res = knet_host_get_status(instance->knet_handle,
+				   nodeid,
+				   &knet_host_status);
+	if (res) {
+		knet_log_printf (LOGSYS_LEVEL_WARNING, "knet_handle_get_host_status(%d) failed: %d", nodeid, res);
+		return (-1);
+	}
+	node_status->nodeid = nodeid;
+	node_status->reachable = knet_host_status.reachable;
+	node_status->remote = knet_host_status.remote;
+	node_status->external = knet_host_status.external;
+
+#ifdef HAVE_KNET_ONWIRE_VER
+	res = knet_handle_get_onwire_ver(instance->knet_handle,
+					 nodeid,
+					 &node_status->onwire_min,
+					 &node_status->onwire_max,
+					 &node_status->onwire_ver);
+	if (res) {
+		knet_log_printf (LOGSYS_LEVEL_WARNING, "knet_handle_get_onwire_ver(%d) failed: %d", nodeid, res);
+		return (-1);
+	}
+#endif
+	/* Get link info */
+	res = knet_link_get_link_list(instance->knet_handle,
+				      nodeid, link_list, &num_links);
+	if (res) {
+		knet_log_printf (LOGSYS_LEVEL_WARNING, "knet_link_get_link_list(%d) failed: %d", nodeid, res);
+		return (-1);
+	}
+
+	for (i=0; i < num_links; i++) {
+		if (!instance->totem_config->interfaces[link_list[i]].configured) {
+			continue;
+		}
+		res = knet_link_get_status(instance->knet_handle,
+					   nodeid,
+					   link_list[i],
+					   &link_status,
+					   sizeof(link_status));
+		if (res == 0) {
+			node_status->link_status[i].enabled = link_status.enabled;
+			node_status->link_status[i].connected = link_status.connected;
+			node_status->link_status[i].dynconnected = link_status.dynconnected;
+			node_status->link_status[i].mtu = link_status.mtu;
+			memcpy(node_status->link_status[i].src_ipaddr, link_status.src_ipaddr, KNET_MAX_HOST_LEN);
+			memcpy(node_status->link_status[i].dst_ipaddr, link_status.dst_ipaddr, KNET_MAX_HOST_LEN);
+		} else {
+			knet_log_printf (LOGSYS_LEVEL_WARNING, "knet_link_get_link_status(%d, %d) failed: %d", nodeid, link_list[i], res);
+		}
+	}
+	return res;
+}
+
+
+
 int totemknet_ifaces_get (void *knet_context,
 	char ***status,
 	unsigned int *iface_count)
@@ -905,6 +982,14 @@
 	LEAVE();
 }
 
+static int totemknet_is_crypto_enabled(const struct totemknet_instance *instance)
+{
+
+	return (!(strcmp(instance->totem_config->crypto_cipher_type, "none") == 0 &&
+	    strcmp(instance->totem_config->crypto_hash_type, "none") == 0));
+
+}
+
 static int totemknet_set_knet_crypto(struct totemknet_instance *instance)
 {
 	struct knet_handle_crypto_cfg crypto_cfg;
@@ -927,7 +1012,7 @@
 		);
 
 	/* If crypto is being disabled we need to explicitly allow cleartext traffic in knet */
-	if (strcmp(instance->totem_config->crypto_cipher_type, "none") == 0) {
+	if (!totemknet_is_crypto_enabled(instance)) {
 		res = knet_handle_crypto_rx_clear_traffic(instance->knet_handle, KNET_CRYPTO_RX_ALLOW_CLEAR_TRAFFIC);
 		if (res) {
 			knet_log_printf(LOGSYS_LEVEL_ERROR, "knet_handle_crypto_rx_clear_traffic(ALLOW) failed %s", strerror(errno));
@@ -996,7 +1081,9 @@
 		void *context))
 {
 	struct totemknet_instance *instance;
+	char *tmp_str;
 	int8_t channel=0;
+	int allow_knet_handle_fallback=0;
 	int res;
 	int i;
 
@@ -1061,13 +1148,27 @@
 		goto exit_error;
 	}
 
+	if (icmap_get_string("system.allow_knet_handle_fallback", &tmp_str) == CS_OK) {
+		if (strcmp(tmp_str, "yes") == 0) {
+			allow_knet_handle_fallback = 1;
+		}
+		free(tmp_str);
+	}
 
-#if !defined(KNET_API_VER) || (KNET_API_VER == 1)
+#if defined(KNET_API_VER) && (KNET_API_VER == 2)
+	instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG, KNET_HANDLE_FLAG_PRIVILEGED);
+#else
 	instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG);
 #endif
-#if KNET_API_VER == 2
-	instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG, KNET_HANDLE_FLAG_PRIVILEGED);
+
+	if (allow_knet_handle_fallback && !instance->knet_handle && errno == ENAMETOOLONG) {
+		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_WARNING, "knet_handle_new failed, trying unprivileged");
+#if defined(KNET_API_VER) && (KNET_API_VER == 2)
+		instance->knet_handle = knet_handle_new(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG, 0);
+#else
+		instance->knet_handle = knet_handle_new_ex(instance->totem_config->node_id, instance->logpipes[1], KNET_LOG_DEBUG, 0);
 #endif
+	}
 
 	if (!instance->knet_handle) {
 		KNET_LOGSYS_PERROR(errno, LOGSYS_LEVEL_CRIT, "knet_handle_new failed");
@@ -1108,7 +1209,7 @@
 
 	/* Enable crypto if requested */
 #ifdef HAVE_KNET_CRYPTO_RECONF
-	if (strcmp(instance->totem_config->crypto_cipher_type, "none") != 0) {
+	if (totemknet_is_crypto_enabled(instance)) {
 	        res = totemknet_set_knet_crypto(instance);
 		if (res == 0) {
 			res = knet_handle_crypto_use_config(instance->knet_handle, totem_config->crypto_index);
@@ -1134,7 +1235,7 @@
 		}
 	}
 #else
-	if (strcmp(instance->totem_config->crypto_cipher_type, "none") != 0) {
+	if (totemknet_is_crypto_enabled(instance)) {
 		res = totemknet_set_knet_crypto(instance);
 		if (res) {
 			knet_log_printf(LOG_DEBUG, "Failed to set up knet crypto");
@@ -1146,7 +1247,7 @@
 	/* Set up compression */
 	if (strcmp(totem_config->knet_compression_model, "none") != 0) {
 		/* Not fatal, but will log */
-		(void)totemknet_configure_compression(knet_context, totem_config);
+		(void)totemknet_configure_compression(instance, totem_config);
 	}
 
 	knet_handle_setfwd(instance->knet_handle, 1);
@@ -1549,10 +1650,9 @@
 
 
 static int totemknet_configure_compression (
-	void *knet_context,
+	struct totemknet_instance *instance,
 	struct totem_config *totem_config)
 {
-	struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
 	struct knet_handle_compress_cfg compress_cfg;
 	int res = 0;
 
@@ -1576,7 +1676,7 @@
 	struct totemknet_instance *instance = (struct totemknet_instance *)knet_context;
 	int res = 0;
 
-	(void)totemknet_configure_compression(knet_context, totem_config);
+	(void)totemknet_configure_compression(instance, totem_config);
 
 #ifdef HAVE_LIBNOZZLE
 	/* Set up nozzle device(s). Return code is ignored, because inability
@@ -1616,7 +1716,7 @@
 	switch (phase) {
 		case CRYPTO_RECONFIG_PHASE_ACTIVATE:
 			config_to_use = totem_config->crypto_index;
-			if (strcmp(instance->totem_config->crypto_cipher_type, "none") == 0) {
+			if (!totemknet_is_crypto_enabled(instance)) {
 				config_to_use = 0; /* we are clearing it */
 			}
 
@@ -1647,7 +1747,7 @@
 			}
 
 			/* If crypto is enabled then disable all cleartext reception */
-			if (strcmp(instance->totem_config->crypto_cipher_type, "none") != 0) {
+			if (totemknet_is_crypto_enabled(instance)) {
 				res = knet_handle_crypto_rx_clear_traffic(instance->knet_handle, KNET_CRYPTO_RX_DISALLOW_CLEAR_TRAFFIC);
 				if (res) {
 					knet_log_printf(LOGSYS_LEVEL_ERROR, "knet_handle_crypto_rx_clear_traffic(DISALLOW) failed %s", strerror(errno));
diff -Nru corosync-3.1.0/exec/totemknet.h corosync-3.1.2/exec/totemknet.h
--- corosync-3.1.0/exec/totemknet.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemknet.h	2021-03-29 14:07:44.000000000 +0200
@@ -102,6 +102,9 @@
 
 extern void totemknet_net_mtu_adjust (void *knet_context, struct totem_config *totem_config);
 
+extern int totemknet_nodestatus_get (void *knet_context, unsigned int nodeid,
+				     struct totem_node_status *node_status);
+
 extern int totemknet_ifaces_get (void *net_context,
 	char ***status,
 	unsigned int *iface_count);
diff -Nru corosync-3.1.0/exec/totemnet.c corosync-3.1.2/exec/totemnet.c
--- corosync-3.1.0/exec/totemnet.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemnet.c	2021-03-29 14:07:44.000000000 +0200
@@ -115,6 +115,11 @@
 		char ***status,
 		unsigned int *iface_count);
 
+	int (*nodestatus_get) (
+		void *transport_context,
+		unsigned int nodeid,
+		struct totem_node_status *node_status);
+
 	int (*token_target_set) (
 		void *transport_context,
 		unsigned int nodeid);
@@ -179,6 +184,7 @@
 		.finalize = totemudp_finalize,
 		.net_mtu_adjust = totemudp_net_mtu_adjust,
 		.ifaces_get = totemudp_ifaces_get,
+		.nodestatus_get = totemudp_nodestatus_get,
 		.token_target_set = totemudp_token_target_set,
 		.crypto_set = totemudp_crypto_set,
 		.recv_mcast_empty = totemudp_recv_mcast_empty,
@@ -203,6 +209,7 @@
 		.finalize = totemudpu_finalize,
 		.net_mtu_adjust = totemudpu_net_mtu_adjust,
 		.ifaces_get = totemudpu_ifaces_get,
+		.nodestatus_get = totemudpu_nodestatus_get,
 		.token_target_set = totemudpu_token_target_set,
 		.crypto_set = totemudpu_crypto_set,
 		.recv_mcast_empty = totemudpu_recv_mcast_empty,
@@ -227,6 +234,7 @@
 		.finalize = totemknet_finalize,
 		.net_mtu_adjust = totemknet_net_mtu_adjust,
 		.ifaces_get = totemknet_ifaces_get,
+		.nodestatus_get = totemknet_nodestatus_get,
 		.token_target_set = totemknet_token_target_set,
 		.crypto_set = totemknet_crypto_set,
 		.recv_mcast_empty = totemknet_recv_mcast_empty,
@@ -472,6 +480,19 @@
 
 	return (res);
 }
+
+extern int totemnet_nodestatus_get (
+	void *net_context,
+	unsigned int nodeid,
+	struct totem_node_status *node_status)
+{
+	struct totemnet_instance *instance = (struct totemnet_instance *)net_context;
+	unsigned int res;
+
+	res = instance->transport->nodestatus_get (instance->transport_context, nodeid, node_status);
+
+	return (res);
+}
 
 int totemnet_ifaces_get (
 	void *net_context,
diff -Nru corosync-3.1.0/exec/totemnet.h corosync-3.1.2/exec/totemnet.h
--- corosync-3.1.0/exec/totemnet.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemnet.h	2021-03-29 14:07:44.000000000 +0200
@@ -125,6 +125,11 @@
 
 extern const char *totemnet_iface_print (void *net_context);
 
+extern int totemnet_nodestatus_get (
+	void *net_context,
+	unsigned int nodeid,
+	struct totem_node_status *node_status);
+
 extern int totemnet_ifaces_get (
 	void *net_context,
 	char ***status,
diff -Nru corosync-3.1.0/exec/totempg.c corosync-3.1.2/exec/totempg.c
--- corosync-3.1.0/exec/totempg.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totempg.c	2021-03-29 14:07:44.000000000 +0200
@@ -1447,6 +1447,13 @@
 	return (res);
 }
 
+int totempg_nodestatus_get (unsigned int nodeid,
+			    struct totem_node_status *node_status)
+{
+	memset(node_status, 0, sizeof(struct totem_node_status));
+	return totemsrp_nodestatus_get (totemsrp_context, nodeid, node_status);
+}
+
 int totempg_ifaces_get (
 	unsigned int nodeid,
 	unsigned int *interface_id,
diff -Nru corosync-3.1.0/exec/totemsrp.c corosync-3.1.2/exec/totemsrp.c
--- corosync-3.1.0/exec/totemsrp.c	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/exec/totemsrp.c	2021-03-29 14:07:44.000000000 +0200
@@ -1039,6 +1039,27 @@
 	free (instance);
 }
 
+int totemsrp_nodestatus_get (
+	void *srp_context,
+	unsigned int nodeid,
+	struct totem_node_status *node_status)
+{
+	struct totemsrp_instance *instance = (struct totemsrp_instance *)srp_context;
+	int i;
+
+	node_status->version = TOTEM_NODE_STATUS_STRUCTURE_VERSION;
+
+	/* Fill in 'reachable' here as the lower level UDP[u] layers don't know */
+	for (i = 0; i < instance->my_proc_list_entries; i++) {
+		if (instance->my_proc_list[i].nodeid == nodeid) {
+			node_status->reachable = 1;
+		}
+	}
+
+	return totemnet_nodestatus_get(instance->totemnet_context, nodeid, node_status);
+}
+
+
 /*
  * Return configured interfaces. interfaces is array of totem_ip addresses allocated by caller,
  * with interaces_size number of items. iface_count is final number of interfaces filled by this
diff -Nru corosync-3.1.0/exec/totemsrp.h corosync-3.1.2/exec/totemsrp.h
--- corosync-3.1.0/exec/totemsrp.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemsrp.h	2021-03-29 14:07:44.000000000 +0200
@@ -101,6 +101,9 @@
 
 extern void totemsrp_net_mtu_adjust (struct totem_config *totem_config);
 
+extern int totemsrp_nodestatus_get (void *srp_context, unsigned int nodeid,
+				    struct totem_node_status *node_status);
+
 extern int totemsrp_ifaces_get (
 	void *srp_context,
 	unsigned int nodeid,
diff -Nru corosync-3.1.0/exec/totemudp.c corosync-3.1.2/exec/totemudp.c
--- corosync-3.1.0/exec/totemudp.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemudp.c	2021-03-29 14:07:44.000000000 +0200
@@ -1334,6 +1334,35 @@
 	return (res);
 }
 
+int totemudp_nodestatus_get (void *udp_context, unsigned int nodeid,
+			     struct totem_node_status *node_status)
+{
+	struct totemudp_instance *instance = (struct totemudp_instance *)udp_context;
+	struct qb_list_head *list;
+	struct totemudp_member *member;
+
+	qb_list_for_each(list, &(instance->member_list)) {
+		member = qb_list_entry (list,
+			struct totemudp_member,
+			list);
+
+		if (member->member.nodeid == nodeid) {
+			node_status->nodeid = nodeid;
+			/* reachable is filled in by totemsrp */
+			node_status->link_status[0].enabled = 1;
+			if (instance->netif_bind_state == BIND_STATE_REGULAR) {
+				node_status->link_status[0].enabled = 1;
+			} else {
+				node_status->link_status[0].enabled = 0;
+			}
+			node_status->link_status[0].connected = node_status->reachable;
+			node_status->link_status[0].mtu = instance->totem_config->net_mtu;
+			strncpy(node_status->link_status[0].src_ipaddr, totemip_print(&member->member), KNET_MAX_HOST_LEN-1);
+		}
+	}
+	return (0);
+}
+
 int totemudp_ifaces_get (
 	void *net_context,
 	char ***status,
diff -Nru corosync-3.1.0/exec/totemudp.h corosync-3.1.2/exec/totemudp.h
--- corosync-3.1.0/exec/totemudp.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemudp.h	2021-03-29 14:07:44.000000000 +0200
@@ -92,6 +92,9 @@
 	const void *msg,
 	unsigned int msg_len);
 
+extern int totemudp_nodestatus_get (void *net_context, unsigned int nodeid,
+				    struct totem_node_status *node_status);
+
 extern int totemudp_ifaces_get (void *net_context,
 	char ***status,
 	unsigned int *iface_count);
diff -Nru corosync-3.1.0/exec/totemudpu.c corosync-3.1.2/exec/totemudpu.c
--- corosync-3.1.0/exec/totemudpu.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemudpu.c	2021-03-29 14:07:44.000000000 +0200
@@ -793,6 +793,34 @@
 	return 0;
 }
 
+int totemudpu_nodestatus_get (void *udpu_context, unsigned int nodeid,
+			      struct totem_node_status *node_status)
+{
+	struct totemudpu_instance *instance = (struct totemudpu_instance *)udpu_context;
+	struct qb_list_head *list;
+	struct totemudpu_member *member;
+
+	qb_list_for_each(list, &(instance->member_list)) {
+		member = qb_list_entry (list,
+			struct totemudpu_member,
+			list);
+
+		if (member->member.nodeid == nodeid) {
+			node_status->nodeid = nodeid;
+			/* reachable is filled in by totemsrp */
+			if (instance->netif_bind_state == BIND_STATE_REGULAR) {
+				node_status->link_status[0].enabled = 1;
+			} else {
+				node_status->link_status[0].enabled = 0;
+			}
+			node_status->link_status[0].connected = node_status->reachable;
+			node_status->link_status[0].mtu = instance->totem_config->net_mtu;
+			strncpy(node_status->link_status[0].src_ipaddr, totemip_print(&member->member), KNET_MAX_HOST_LEN-1);
+		}
+	}
+	return (0);
+}
+
 int totemudpu_ifaces_get (
 	void *net_context,
 	char ***status,
diff -Nru corosync-3.1.0/exec/totemudpu.h corosync-3.1.2/exec/totemudpu.h
--- corosync-3.1.0/exec/totemudpu.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/exec/totemudpu.h	2021-03-29 14:07:44.000000000 +0200
@@ -92,6 +92,9 @@
 	const void *msg,
 	unsigned int msg_len);
 
+extern int totemudpu_nodestatus_get (void *net_context, unsigned int nodeid,
+				    struct totem_node_status *node_status);
+
 extern int totemudpu_ifaces_get (void *net_context,
 	char ***status,
 	unsigned int *iface_count);
diff -Nru corosync-3.1.0/include/corosync/cfg.h corosync-3.1.2/include/corosync/cfg.h
--- corosync-3.1.0/include/corosync/cfg.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/include/corosync/cfg.h	2021-03-29 14:07:44.000000000 +0200
@@ -162,6 +162,48 @@
 	char ***status,
 	unsigned int *interface_count);
 
+typedef enum {
+	CFG_NODE_STATUS_V1 = 1,
+} corosync_cfg_node_status_version_t;
+
+#define CFG_MAX_HOST_LEN 256
+#define CFG_MAX_LINKS 8
+
+struct corosync_knet_link_status_v1 {
+	uint8_t enabled;	        /* link is configured and admin enabled for traffic */
+	uint8_t connected;              /* link is connected for data (local view) */
+	uint8_t dynconnected;	        /* link has been activated by remote dynip */
+	unsigned int mtu;		/* current detected MTU on this link */
+	char src_ipaddr[CFG_MAX_HOST_LEN];
+	char dst_ipaddr[CFG_MAX_HOST_LEN];
+};
+
+struct corosync_cfg_node_status_v1 {
+	corosync_cfg_node_status_version_t version;
+	unsigned int nodeid;
+	uint8_t reachable;
+	uint8_t remote;
+	uint8_t external;
+	uint8_t onwire_min;
+	uint8_t onwire_max;
+	uint8_t onwire_ver;
+	struct corosync_knet_link_status_v1 link_status[CFG_MAX_LINKS];
+};
+
+/**
+ * @brief corosync_cfg_node_status_get
+ * @param cfg_handle
+ * @param nodeid
+ * @param node_status
+ * @return
+ */
+cs_error_t
+corosync_cfg_node_status_get (
+	corosync_cfg_handle_t cfg_handle,
+	unsigned int nodeid,
+	corosync_cfg_node_status_version_t version,
+	void *node_status);
+
 /**
  * @brief corosync_cfg_kill_node
  * @param cfg_handle
@@ -176,6 +218,30 @@
 	const char *reason);
 
 /**
+ * @brief corosync_cfg_trackstart
+ * Track CFG for shutdown requests
+ * @param cfg_handle
+ * @param track_flags (none currently supported)
+ * @param reason
+ * @return
+ */
+cs_error_t
+corosync_cfg_trackstart (
+        corosync_cfg_handle_t cfg_handle,
+        uint8_t track_flags);
+
+/**
+ * @brief corosync_cfg_trackstop
+ * Stop tracking CFG for shutdown requests
+ * @param cfg_handle
+ * @param reason
+ * @return
+ */
+cs_error_t
+corosync_cfg_trackstop (
+        corosync_cfg_handle_t cfg_handle);
+
+/**
  * @brief corosync_cfg_try_shutdown
  * @param cfg_handle
  * @param flags
diff -Nru corosync-3.1.0/include/corosync/config.h.in corosync-3.1.2/include/corosync/config.h.in
--- corosync-3.1.0/include/corosync/config.h.in	2020-10-20 16:15:25.000000000 +0200
+++ corosync-3.1.2/include/corosync/config.h.in	2021-04-06 12:03:22.000000000 +0200
@@ -1,8 +1,5 @@
 /* include/corosync/config.h.in.  Generated from configure.ac by autoheader.  */
 
-/* building in place */
-#undef BUILDING_IN_PLACE
-
 /* Define to 1 if the `closedir' function returns void instead of `int'. */
 #undef CLOSEDIR_VOID
 
@@ -124,6 +121,9 @@
 /* have knet crypto reconfig support */
 #undef HAVE_KNET_CRYPTO_RECONF
 
+/* have knet onwire versioning */
+#undef HAVE_KNET_ONWIRE_VER
+
 /* Define to 1 if you have the `asan' library (-lasan). */
 #undef HAVE_LIBASAN
 
diff -Nru corosync-3.1.0/include/corosync/ipc_cfg.h corosync-3.1.2/include/corosync/ipc_cfg.h
--- corosync-3.1.0/include/corosync/ipc_cfg.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/include/corosync/ipc_cfg.h	2021-03-29 14:07:44.000000000 +0200
@@ -59,7 +59,10 @@
 	MESSAGE_REQ_CFG_GET_NODE_ADDRS = 5,
 	MESSAGE_REQ_CFG_LOCAL_GET = 6,
 	MESSAGE_REQ_CFG_RELOAD_CONFIG = 7,
-	MESSAGE_REQ_CFG_REOPEN_LOG_FILES = 8
+	MESSAGE_REQ_CFG_REOPEN_LOG_FILES = 8,
+	MESSAGE_REQ_CFG_NODESTATUSGET = 9,
+	MESSAGE_REQ_CFG_TRACKSTART = 10,
+	MESSAGE_REQ_CFG_TRACKSTOP = 11
 };
 
 /**
@@ -81,7 +84,8 @@
 	MESSAGE_RES_CFG_LOCAL_GET = 12,
 	MESSAGE_RES_CFG_REPLYTOSHUTDOWN = 13,
 	MESSAGE_RES_CFG_RELOAD_CONFIG = 14,
-	MESSAGE_RES_CFG_REOPEN_LOG_FILES = 15
+	MESSAGE_RES_CFG_REOPEN_LOG_FILES = 15,
+	MESSAGE_RES_CFG_NODESTATUSGET = 16
 };
 
 /**
@@ -102,6 +106,28 @@
 };
 
 /**
+ * @brief The req_lib_cfg_nodestatusget struct
+ */
+struct req_lib_cfg_nodestatusget {
+	struct qb_ipc_request_header header __attribute__((aligned(8)));
+	unsigned int nodeid __attribute__((aligned(8)));
+	mar_uint32_t version __attribute__((aligned(8)));
+};
+
+struct res_lib_cfg_nodestatusget_version {
+	struct qb_ipc_response_header header __attribute__((aligned(8)));
+	corosync_cfg_node_status_version_t version __attribute__((aligned(8)));
+};
+
+/**
+ * @brief The res_lib_cfg_nodestatusget struct
+ */
+struct res_lib_cfg_nodestatusget_v1 {
+	struct qb_ipc_response_header header __attribute__((aligned(8)));
+	struct corosync_cfg_node_status_v1 node_status __attribute__((aligned(8)));
+};
+
+/**
  * @brief The req_lib_cfg_ringreenable struct
  */
 struct req_lib_cfg_ringreenable {
@@ -231,6 +257,24 @@
 	struct qb_ipc_response_header header __attribute__((aligned(8)));
 };
 
+struct req_lib_cfg_trackstart {
+	struct qb_ipc_request_header header;
+	uint8_t track_flags;
+};
+
+struct res_lib_cfg_trackstart {
+	struct qb_ipc_response_header header;
+};
+
+struct req_lib_cfg_trackstop {
+	struct qb_ipc_request_header header;
+};
+
+struct res_lib_cfg_trackstop {
+	struct qb_ipc_response_header header;
+};
+
+
 /**
  * @brief corosync_administrative_target_t enum
  */
diff -Nru corosync-3.1.0/include/corosync/totem/totem.h corosync-3.1.2/include/corosync/totem/totem.h
--- corosync-3.1.0/include/corosync/totem/totem.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/include/corosync/totem/totem.h	2021-03-29 14:07:44.000000000 +0200
@@ -253,6 +253,25 @@
 	    unsigned int nodeid);
 };
 
+/*
+ * Node status returned from the API
+ * Usually the same as the cfg version (except for
+ * link_status)
+ */
+#define TOTEM_NODE_STATUS_STRUCTURE_VERSION 1
+struct totem_node_status {
+	uint32_t version; /* Structure version */
+	unsigned int nodeid;
+	uint8_t reachable;
+	uint8_t remote;
+	uint8_t external;
+	uint8_t onwire_min;
+	uint8_t onwire_max;
+	uint8_t onwire_ver;
+	struct knet_link_status link_status[KNET_MAX_LINK];
+};
+
+
 #define TOTEM_CONFIGURATION_TYPE
 enum totem_configuration_type {
 	TOTEM_CONFIGURATION_REGULAR,
diff -Nru corosync-3.1.0/include/corosync/totem/totempg.h corosync-3.1.2/include/corosync/totem/totempg.h
--- corosync-3.1.0/include/corosync/totem/totempg.h	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/include/corosync/totem/totempg.h	2021-03-29 14:07:44.000000000 +0200
@@ -146,6 +146,9 @@
 	char ***status,
         unsigned int *iface_count);
 
+extern int totempg_nodestatus_get (unsigned int nodeid,
+				   struct totem_node_status *node_status);
+
 extern void* totempg_get_stats (void);
 
 void totempg_event_signal (enum totem_event_type type, int value);
diff -Nru corosync-3.1.0/include/Makefile.in corosync-3.1.2/include/Makefile.in
--- corosync-3.1.0/include/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/include/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -270,7 +270,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/init/corosync.in corosync-3.1.2/init/corosync.in
--- corosync-3.1.0/init/corosync.in	2019-08-27 07:48:40.000000000 +0200
+++ corosync-3.1.2/init/corosync.in	2021-03-29 14:07:44.000000000 +0200
@@ -176,6 +176,9 @@
 	! status -p "$prog_pid_file" "$prog" > /dev/null 2>&1 && return
 
 	echo -n "Signaling $desc ($prog) to terminate: "
+	# Call cfgtool to trigger shutdown callbacks
+	corosync-cfgtool -H --force > /dev/null 2>&1
+	# Send TERM signal (if cfgtool -H failed)
 	kill -TERM "$(pid_var_run $prog_pid_file)" > /dev/null 2>&1
 	success
 	echo
diff -Nru corosync-3.1.0/init/corosync.service.in corosync-3.1.2/init/corosync.service.in
--- corosync-3.1.0/init/corosync.service.in	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/init/corosync.service.in	2021-03-29 14:07:44.000000000 +0200
@@ -8,6 +8,7 @@
 [Service]
 EnvironmentFile=-@INITCONFIGDIR@/corosync
 ExecStart=@SBINDIR@/corosync -f $COROSYNC_OPTIONS
+ExecStop=@SBINDIR@/corosync-cfgtool -H --force
 Type=notify
 
 # In typical systemd deployments, both standard outputs are forwarded to
diff -Nru corosync-3.1.0/init/Makefile.in corosync-3.1.2/init/Makefile.in
--- corosync-3.1.0/init/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/init/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -257,7 +257,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/lib/cfg.c corosync-3.1.2/lib/cfg.c
--- corosync-3.1.0/lib/cfg.c	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/lib/cfg.c	2021-03-29 14:07:44.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002-2005 MontaVista Software, Inc.
- * Copyright (c) 2006-2018 Red Hat, Inc.
+ * Copyright (c) 2006-2020 Red Hat, Inc.
  *
  * All rights reserved.
  *
@@ -368,6 +368,155 @@
 }
 
 cs_error_t
+corosync_cfg_node_status_get (
+	corosync_cfg_handle_t cfg_handle,
+	unsigned int nodeid,
+	corosync_cfg_node_status_version_t version,
+	void *node_status)
+{
+	struct cfg_inst *cfg_inst;
+	struct req_lib_cfg_nodestatusget req_lib_cfg_nodestatusget;
+	cs_error_t error;
+	struct iovec iov;
+	size_t cfg_node_status_size;
+	void *res_lib_cfg_nodestatuget_ptr;
+	struct res_lib_cfg_nodestatusget_v1 res_lib_cfg_nodestatusget_v1;
+	struct res_lib_cfg_nodestatusget_version *res_lib_cfg_nodestatusget_version;
+
+	if (!node_status) {
+		return (CS_ERR_INVALID_PARAM);
+	}
+
+	switch (version) {
+	case CFG_NODE_STATUS_V1:
+		cfg_node_status_size = sizeof(struct res_lib_cfg_nodestatusget_v1);
+		res_lib_cfg_nodestatuget_ptr = &res_lib_cfg_nodestatusget_v1;
+
+		break;
+	default:
+		return (CS_ERR_INVALID_PARAM);
+		break;
+	}
+
+	error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle, (void *)&cfg_inst));
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_nodestatusget.header.size = sizeof (struct req_lib_cfg_nodestatusget);
+	req_lib_cfg_nodestatusget.header.id = MESSAGE_REQ_CFG_NODESTATUSGET;
+	req_lib_cfg_nodestatusget.nodeid = nodeid;
+	req_lib_cfg_nodestatusget.version = version;
+
+	iov.iov_base = (void *)&req_lib_cfg_nodestatusget,
+	iov.iov_len = sizeof (struct req_lib_cfg_nodestatusget),
+
+	error = qb_to_cs_error (qb_ipcc_sendv_recv(cfg_inst->c,
+		&iov,
+		1,
+		res_lib_cfg_nodestatuget_ptr,
+		cfg_node_status_size, CS_IPC_TIMEOUT_MS));
+	if (error != CS_OK) {
+		goto error_put;
+	}
+
+	res_lib_cfg_nodestatusget_version = res_lib_cfg_nodestatuget_ptr;
+	error = res_lib_cfg_nodestatusget_version->header.error;
+	if (error != CS_OK) {
+		goto error_put;
+	}
+
+	if (res_lib_cfg_nodestatusget_version->version != version) {
+		/*
+		 * corosync sent us something we don't really understand.
+		 */
+		error = CS_ERR_NOT_SUPPORTED;
+		goto error_put;
+	}
+
+	switch (version) {
+	case CFG_NODE_STATUS_V1:
+		memcpy(node_status, &res_lib_cfg_nodestatusget_v1.node_status,
+		    sizeof(struct corosync_cfg_node_status_v1));
+		break;
+	}
+
+error_put:
+	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
+
+	return (error);
+}
+
+
+cs_error_t
+corosync_cfg_trackstart (
+	corosync_cfg_handle_t cfg_handle,
+	uint8_t track_flags)
+{
+	struct cfg_inst *cfg_inst;
+	struct req_lib_cfg_trackstart req_lib_cfg_trackstart;
+	struct res_lib_cfg_trackstart res_lib_cfg_trackstart;
+	cs_error_t error;
+	struct iovec iov;
+
+	req_lib_cfg_trackstart.header.size = sizeof (struct req_lib_cfg_trackstart);
+	req_lib_cfg_trackstart.header.id = MESSAGE_REQ_CFG_TRACKSTART;
+	req_lib_cfg_trackstart.track_flags = track_flags;
+
+	error = hdb_error_to_cs(hdb_handle_get (&cfg_hdb, cfg_handle,
+		(void *)&cfg_inst));
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	iov.iov_base = (void *)&req_lib_cfg_trackstart,
+	iov.iov_len = sizeof (struct req_lib_cfg_trackstart),
+
+	error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
+		&iov,
+		1,
+		&res_lib_cfg_trackstart,
+		sizeof (struct res_lib_cfg_trackstart), CS_IPC_TIMEOUT_MS));
+
+	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
+
+	return (error == CS_OK ? res_lib_cfg_trackstart.header.error : error);
+}
+
+cs_error_t
+corosync_cfg_trackstop (
+	corosync_cfg_handle_t cfg_handle)
+{
+	struct cfg_inst *cfg_inst;
+	struct req_lib_cfg_trackstop req_lib_cfg_trackstop;
+	struct res_lib_cfg_trackstop res_lib_cfg_trackstop;
+	cs_error_t error;
+	struct iovec iov;
+
+	error = hdb_error_to_cs (hdb_handle_get (&cfg_hdb, cfg_handle,
+		(void *)&cfg_inst));
+	if (error != CS_OK) {
+		return (error);
+	}
+
+	req_lib_cfg_trackstop.header.size = sizeof (struct req_lib_cfg_trackstop);
+	req_lib_cfg_trackstop.header.id = MESSAGE_REQ_CFG_TRACKSTOP;
+
+	iov.iov_base = (void *)&req_lib_cfg_trackstop,
+	iov.iov_len = sizeof (struct req_lib_cfg_trackstop),
+
+	error = qb_to_cs_error (qb_ipcc_sendv_recv (cfg_inst->c,
+		&iov,
+		1,
+		&res_lib_cfg_trackstop,
+		sizeof (struct res_lib_cfg_trackstop), CS_IPC_TIMEOUT_MS));
+
+	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
+
+	return (error == CS_OK ? res_lib_cfg_trackstop.header.error : error);
+}
+
+cs_error_t
 corosync_cfg_kill_node (
 	corosync_cfg_handle_t cfg_handle,
 	unsigned int nodeid,
@@ -407,7 +556,7 @@
 
 	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
 
-        return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
+	return (error == CS_OK ? res_lib_cfg_killnode.header.error : error);
 }
 
 cs_error_t
@@ -442,7 +591,7 @@
 
 	(void)hdb_handle_put (&cfg_hdb, cfg_handle);
 
-        return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
+	return (error == CS_OK ? res_lib_cfg_tryshutdown.header.error : error);
 }
 
 cs_error_t
diff -Nru corosync-3.1.0/lib/libcfg.versions corosync-3.1.2/lib/libcfg.versions
--- corosync-3.1.0/lib/libcfg.versions	2019-06-10 08:21:37.000000000 +0200
+++ corosync-3.1.2/lib/libcfg.versions	2021-03-29 14:07:44.000000000 +0200
@@ -11,7 +11,8 @@
 		corosync_cfg_track;
 		corosync_cfg_track_stop;
 		corosync_cfg_ring_status_get;
+		corosync_cfg_node_status_get;
 		corosync_cfg_ring_reenable;
-		corosync_cfg_service_load;
-		corosync_cfg_service_unload;
+		corosync_cfg_trackstart;
+		corosync_cfg_trackstop;
 };
diff -Nru corosync-3.1.0/lib/libcfg.verso corosync-3.1.2/lib/libcfg.verso
--- corosync-3.1.0/lib/libcfg.verso	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/lib/libcfg.verso	2021-03-29 14:07:44.000000000 +0200
@@ -1 +1 @@
-7.1.0
+7.3.0
diff -Nru corosync-3.1.0/lib/Makefile.in corosync-3.1.2/lib/Makefile.in
--- corosync-3.1.0/lib/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/lib/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -328,7 +328,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/Makefile.in corosync-3.1.2/Makefile.in
--- corosync-3.1.0/Makefile.in	2020-10-20 16:15:26.000000000 +0200
+++ corosync-3.1.2/Makefile.in	2021-04-06 12:03:23.000000000 +0200
@@ -510,7 +510,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/man/cmap_keys.7 corosync-3.1.2/man/cmap_keys.7
--- corosync-3.1.0/man/cmap_keys.7	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/man/cmap_keys.7	2021-03-29 14:07:44.000000000 +0200
@@ -148,6 +148,11 @@
 to unblock quorum if notes are known to be down. For pcs use only.
 
 .TP
+cfg.shutdown_timeout
+Sets the timeout within which daemons that are registered for cfg callbacks must respond
+to a corosync_cfg_try_shutdown() request. the default is 5000 mS
+
+.TP
 config.reload_in_progress
 This value will be set to 1 (or created) when a corosync.conf reload is started,
 and set to 0 when the reload is completed. This allows interested subsystems
diff -Nru corosync-3.1.0/man/corosync-cfgtool.8 corosync-3.1.2/man/corosync-cfgtool.8
--- corosync-3.1.0/man/corosync-cfgtool.8	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/man/corosync-cfgtool.8	2021-03-29 14:07:44.000000000 +0200
@@ -35,7 +35,7 @@
 .SH "NAME"
 corosync-cfgtool \- An administrative tool for corosync.
 .SH "SYNOPSIS"
-.B corosync\-cfgtool [[\-i IP_address] [\-b] \-s] [\-R] [\-L] [\-k nodeid] [\-a nodeid] [\-h] [\-H]
+.B corosync\-cfgtool [[\-i IP_address] [\-b] [\-s] [\-n] [\-R] [\-L] [\-k nodeid] [\-a nodeid] [\-h] [\-H] [\--force]
 .SH "DESCRIPTION"
 .B corosync\-cfgtool
 A tool for displaying and configuring active parameters within corosync.
@@ -48,7 +48,7 @@
 Displays the status of the current links on this node for UDP/UDPU, with extended status
 for KNET.
 After each link, the nodes on that link are displayed in order with their status,
-for example there are 3 nodes with KNET transportation:
+for example there are 3 nodes with KNET transport:
 
 LINK ID 0
         addr    = 192.168.100.80
@@ -58,14 +58,14 @@
                 nodeid  3:      connected
 .TP
 .B -b
-Displays the brief status of the current links on this node (KNET only) when used
+Displays the brief status of the current links on this node when used
 with "-s". If any interfaces are faulty, 1 is returned by the binary. If all interfaces
 are active 0 is returned to the shell.
 After each link, the nodes on that link are displayed in order with their status
 encoded into a single digit, or characters 'n', 'd' and '?' with special meaning.
 1=link enabled, 2=link connected, So a 3 in a node position indicates that the
 link is both enabled and connected. Status represented by character 'n' is used for
-localhost link. Character '?' means that Crosync was unable to get status of link from knet (log
+localhost link. Character '?' means that Corosync was unable to get status of link from knet (log
 should contain more information). Character 'd' shouldn't appear and it means that Corosync
 was unable to configure a link and it is result of some error which should have been logged.
 
@@ -75,6 +75,32 @@
         addr    = 192.168.100.80
         status  = n33
 .TP
+.B -n
+Displays the status of the current nodes in the system with their link status(es).
+.P
+.nf
+Local node ID 1, transport knet
+nodeid: 2 reachable   onwire (min/max/cur): 0, 1, 1
+   LINK: 0 (192.168.1.101->192.168.1.102)  enabled connected mtu: 1397
+   LINK: 1 (192.168.4.1->192.168.4.2)  enabled mtu: 469
+   LINK: 2 (192.168.9.1->192.168.9.2)  enabled mtu: 469
+.fi
+.P
+Only reachable nodes are displayed so "reachable" should always be there.
+.br
+'onwire' versions are the knet on-wire versions that are supported/in use (where appropriate).
+.br
+IP addresses are the local and remote IP addresses (for UDP[U] only the local IP address is shown)
+.br
+enabled - means the link has been brought up
+.br
+connected - means that the link is connected to the remote node
+.br
+dynconnected - is not currently implemented
+.br
+mtu - shows the size of data packets. Should be the link packet size less a small amount
+for protocol overheads and encryption
+.TP
 .B -R
 Tell all instances of corosync in this cluster to reload corosync.conf.
 
@@ -97,6 +123,12 @@
 .TP
 .B -H
 Shutdown corosync cleanly on this node.
+corosync-cfgtool -H will request a shutdown from corosync, which means it will
+consult any interested daemons before shutting down and the shutdown maybe vetoed if a
+daemon regards the shutdown as inappropriate.
+If --force is added to the command line then corosync will shutdown regardless
+of the daemons' opinions on the matter.
+
 .SH "SEE ALSO"
 .BR corosync_overview (7),
 .SH "AUTHOR"
diff -Nru corosync-3.1.0/man/corosync.conf.5 corosync-3.1.2/man/corosync.conf.5
--- corosync-3.1.0/man/corosync.conf.5	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/man/corosync.conf.5	2021-03-29 14:07:44.000000000 +0200
@@ -802,6 +802,17 @@
 sched enabled (Linux with CONFIG_RT_GROUP_SCHED kernel option).
 
 .TP
+allow_knet_handle_fallback
+If knet handle creation fails using privileged operations, allow fallback to
+creating knet handle using unprivileged operations. Defaults to no, meaning
+if privileged knet handle creation fails, corosync will refuse to start.
+
+The knet handle will always be created using privileged operations if possible,
+setting this to yes only allows fallback to unprivileged operations. This fallback
+may result in performance issues, but if running in an unprivileged environment,
+e.g. as a normal user or in unprivileged container, this may be required.
+
+.TP
 state_dir
 Existing directory where corosync should chdir into. Corosync stores
 important state files and blackboxes there.
diff -Nru corosync-3.1.0/man/Makefile.in corosync-3.1.2/man/Makefile.in
--- corosync-3.1.0/man/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/man/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -262,7 +262,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/pkgconfig/corosync.pc.in corosync-3.1.2/pkgconfig/corosync.pc.in
--- corosync-3.1.0/pkgconfig/corosync.pc.in	2019-06-10 08:21:37.000000000 +0200
+++ corosync-3.1.2/pkgconfig/corosync.pc.in	2021-03-11 14:42:58.000000000 +0100
@@ -2,6 +2,7 @@
 exec_prefix=${prefix}
 libdir=@LIBDIR@
 includedir=${prefix}/include
+logdir=@LOGDIR@
 
 Name: corosync
 Version: @LIBVERSION@
diff -Nru corosync-3.1.0/pkgconfig/Makefile.am corosync-3.1.2/pkgconfig/Makefile.am
--- corosync-3.1.0/pkgconfig/Makefile.am	2020-10-15 17:09:56.000000000 +0200
+++ corosync-3.1.2/pkgconfig/Makefile.am	2021-03-11 14:42:58.000000000 +0100
@@ -62,6 +62,7 @@
 		-e 's#@''PREFIX@#$(exec_prefix)#g' \
 		-e 's#@''LIBDIR@#$(libdir)#g' \
 		-e 's#@''LIBVERSION@#$(VERSION)#g' \
+		-e 's#@''LOGDIR@#$(LOGDIR)#g' \
 	    $< > $@-t
 	chmod a-w $@-t
 	mv $@-t $@
diff -Nru corosync-3.1.0/pkgconfig/Makefile.in corosync-3.1.2/pkgconfig/Makefile.in
--- corosync-3.1.0/pkgconfig/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/pkgconfig/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -252,7 +252,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -578,6 +577,7 @@
 		-e 's#@''PREFIX@#$(exec_prefix)#g' \
 		-e 's#@''LIBDIR@#$(libdir)#g' \
 		-e 's#@''LIBVERSION@#$(VERSION)#g' \
+		-e 's#@''LOGDIR@#$(LOGDIR)#g' \
 	    $< > $@-t
 	chmod a-w $@-t
 	mv $@-t $@
diff -Nru corosync-3.1.0/.tarball-version corosync-3.1.2/.tarball-version
--- corosync-3.1.0/.tarball-version	2020-10-20 16:15:49.000000000 +0200
+++ corosync-3.1.2/.tarball-version	2021-04-06 12:03:45.000000000 +0200
@@ -1 +1 @@
-3.1.0
+3.1.2
diff -Nru corosync-3.1.0/test/Makefile.am corosync-3.1.2/test/Makefile.am
--- corosync-3.1.0/test/Makefile.am	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/test/Makefile.am	2021-03-29 14:07:44.000000000 +0200
@@ -38,7 +38,7 @@
 			  testquorum testvotequorum1 testvotequorum2	\
 			  stress_cpgfdget stress_cpgcontext cpgbound testsam \
 			  testcpgzc cpgbenchzc testzcgc stress_cpgzc \
-			  testquorummodel
+			  testquorummodel testcfg
 
 noinst_SCRIPTS		= ploadstart
 
@@ -57,6 +57,7 @@
 cpgbench_LDADD		= $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la
 cpgbenchzc_LDADD	= $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la
 testsam_LDADD		= $(LIBQB_LIBS) $(top_builddir)/lib/libsam.la
+testcfg_LDADD		= $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la
 
 if HAVE_CRC32
 noinst_PROGRAMS	        += cpghum cpgverify
diff -Nru corosync-3.1.0/test/Makefile.in corosync-3.1.2/test/Makefile.in
--- corosync-3.1.0/test/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/test/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -116,7 +116,8 @@
 	testvotequorum2$(EXEEXT) stress_cpgfdget$(EXEEXT) \
 	stress_cpgcontext$(EXEEXT) cpgbound$(EXEEXT) testsam$(EXEEXT) \
 	testcpgzc$(EXEEXT) cpgbenchzc$(EXEEXT) testzcgc$(EXEEXT) \
-	stress_cpgzc$(EXEEXT) testquorummodel$(EXEEXT) $(am__EXEEXT_1)
+	stress_cpgzc$(EXEEXT) testquorummodel$(EXEEXT) \
+	testcfg$(EXEEXT) $(am__EXEEXT_1)
 @HAVE_CRC32_TRUE@am__append_1 = cpghum cpgverify
 subdir = test
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
@@ -175,6 +176,10 @@
 stress_cpgzc_OBJECTS = stress_cpgzc.$(OBJEXT)
 stress_cpgzc_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(top_builddir)/lib/libcpg.la
+testcfg_SOURCES = testcfg.c
+testcfg_OBJECTS = testcfg.$(OBJEXT)
+testcfg_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+	$(top_builddir)/lib/libcfg.la
 testcpg_SOURCES = testcpg.c
 testcpg_OBJECTS = testcpg.$(OBJEXT)
 testcpg_DEPENDENCIES = $(am__DEPENDENCIES_1) \
@@ -247,13 +252,15 @@
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
 SOURCES = cpgbench.c cpgbenchzc.c cpgbound.c cpghum.c cpgverify.c \
-	stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcpg.c \
-	testcpg2.c testcpgzc.c testquorum.c testquorummodel.c \
-	testsam.c testvotequorum1.c testvotequorum2.c testzcgc.c
+	stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcfg.c \
+	testcpg.c testcpg2.c testcpgzc.c testquorum.c \
+	testquorummodel.c testsam.c testvotequorum1.c \
+	testvotequorum2.c testzcgc.c
 DIST_SOURCES = cpgbench.c cpgbenchzc.c cpgbound.c cpghum.c cpgverify.c \
-	stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcpg.c \
-	testcpg2.c testcpgzc.c testquorum.c testquorummodel.c \
-	testsam.c testvotequorum1.c testvotequorum2.c testzcgc.c
+	stress_cpgcontext.c stress_cpgfdget.c stress_cpgzc.c testcfg.c \
+	testcpg.c testcpg2.c testcpgzc.c testquorum.c \
+	testquorummodel.c testsam.c testvotequorum1.c \
+	testvotequorum2.c testzcgc.c
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -354,7 +361,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -456,6 +462,7 @@
 cpgbench_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la
 cpgbenchzc_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la
 testsam_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libsam.la
+testcfg_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcfg.la
 @HAVE_CRC32_TRUE@cpghum_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz
 @HAVE_CRC32_TRUE@cpgverify_LDADD = $(LIBQB_LIBS) $(top_builddir)/lib/libcpg.la -lz
 LINT_FILES1 := $(filter-out sa_error.c, $(wildcard *.c))
@@ -536,6 +543,10 @@
 	@rm -f stress_cpgzc$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(stress_cpgzc_OBJECTS) $(stress_cpgzc_LDADD) $(LIBS)
 
+testcfg$(EXEEXT): $(testcfg_OBJECTS) $(testcfg_DEPENDENCIES) $(EXTRA_testcfg_DEPENDENCIES) 
+	@rm -f testcfg$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(testcfg_OBJECTS) $(testcfg_LDADD) $(LIBS)
+
 testcpg$(EXEEXT): $(testcpg_OBJECTS) $(testcpg_DEPENDENCIES) $(EXTRA_testcpg_DEPENDENCIES) 
 	@rm -f testcpg$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(testcpg_OBJECTS) $(testcpg_LDADD) $(LIBS)
@@ -586,6 +597,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgcontext.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgfdget.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stress_cpgzc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcfg.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpg.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpg2.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testcpgzc.Po@am__quote@
diff -Nru corosync-3.1.0/test/testcfg.c corosync-3.1.2/test/testcfg.c
--- corosync-3.1.0/test/testcfg.c	1970-01-01 01:00:00.000000000 +0100
+++ corosync-3.1.2/test/testcfg.c	2021-03-29 14:07:44.000000000 +0200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021 Red Hat Inc
+ *
+ * All rights reserved.
+ *
+ * Author: Christine Caulfield <ccaulfie@redhat.com>
+ *
+ * This software licensed under BSD license, the text of which follows:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the MontaVista Software, Inc. nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <corosync/corotypes.h>
+#include <corosync/cfg.h>
+
+static void shutdown_callback(corosync_cfg_handle_t handle, corosync_cfg_shutdown_flags_t flags)
+{
+	/* Prevent shutdown */
+	printf("In shutdown callback  - denying corosync shutdown\n");
+	corosync_cfg_replyto_shutdown(handle, COROSYNC_CFG_SHUTDOWN_FLAG_NO);
+}
+
+static void *dispatch_thread(void *arg)
+{
+	corosync_cfg_handle_t handle = (corosync_cfg_handle_t) arg;
+	int res = CS_OK;
+	while (res == CS_OK) {
+		res = corosync_cfg_dispatch(handle, CS_DISPATCH_ONE);
+	}
+	fprintf(stderr, "ERROR: Corosync shut down\n");
+	return (void*)0;
+}
+
+
+int main (int argc, char *argv[]) {
+	corosync_cfg_handle_t cfg_handle;
+	corosync_cfg_handle_t cfg_handle1;
+	unsigned int local_nodeid;
+	int i;
+	int res;
+	struct corosync_cfg_node_status_v1 ns;
+	pthread_t thread;
+	corosync_cfg_callbacks_t callbacks = {
+		.corosync_cfg_shutdown_callback = shutdown_callback
+	};
+
+	res = corosync_cfg_initialize(&cfg_handle, &callbacks);
+	if (res != CS_OK) {
+		fprintf(stderr, "corosync_Cfg_initialize(0) failed: %d\n", res);
+		return 1;
+	}
+
+	/* Start a new handle & thread to prevent the shutdown we request later on */
+	res = corosync_cfg_initialize(&cfg_handle1, &callbacks);
+	if (res != CS_OK) {
+		fprintf(stderr, "corosync_cfg_initialize(1) failed: %d\n", res);
+		return 1;
+	}
+	res = corosync_cfg_trackstart(cfg_handle1, 0);
+	if (res != CS_OK) {
+		fprintf(stderr, "corosync_cfg_initialize(1) failed: %d\n", res);
+		return 1;
+	}
+	res = pthread_create(&thread, NULL, dispatch_thread, (void*)cfg_handle1);
+	if (res != 0) {
+		perror("pthread_create failed");
+		return 1;
+	}
+
+	/* Exercise a few functions */
+	res = corosync_cfg_local_get(cfg_handle, &local_nodeid);
+	if (res != CS_OK) {
+		fprintf(stderr, "corosync_cfg_local_get failed: %d\n", res);
+		return 1;
+	}
+
+	printf("Local nodeid is %d\n", local_nodeid);
+
+	/*
+	 * Test node_status_get.
+	 * node status for the local node looks odd (cos it's the loopback connection), so
+	 * we try for a node ID one less or more than us just to get output that looks
+	 * sensible to the user.
+	 */
+	res = corosync_cfg_node_status_get(cfg_handle, local_nodeid-1, CFG_NODE_STATUS_V1, &ns);
+	if (res != CS_OK) {
+		res = corosync_cfg_node_status_get(cfg_handle, local_nodeid+1, CFG_NODE_STATUS_V1, &ns);
+	}
+	if (res != CS_OK) {
+		fprintf(stderr, "corosync_cfg_node_status_get failed: %d\n", res);
+		return 1;
+	}
+	printf("Node Status for nodeid %d\n", ns.nodeid);
+	printf("   reachable: %d\n", ns.reachable);
+	printf("   remote: %d\n", ns.remote);
+	printf("   onwire_min: %d\n", ns.onwire_min);
+	printf("   onwire_max: %d\n", ns.onwire_max);
+	printf("   onwire_ver: %d\n", ns.onwire_ver);
+	for (i = 0; i<CFG_MAX_LINKS; i++) {
+		if (ns.link_status[i].enabled) {
+				printf("   Link %d\n", i);
+				printf("      connected: %d\n", ns.link_status[i].connected);
+				printf("      mtu: %d\n", ns.link_status[i].mtu);
+				printf("      src: %s\n", ns.link_status[i].src_ipaddr);
+				printf("      dst: %s\n", ns.link_status[i].dst_ipaddr);
+		}
+	}
+
+	/* This shutdown request should be denied by the thread */
+	res = corosync_cfg_try_shutdown(cfg_handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST);
+
+	if (res == CS_OK) {
+		fprintf(stderr, "ERROR: corosync_cfg_try_shutdown suceeded. should have been prevented\n");
+	}
+	if (res != CS_ERR_BUSY && res != CS_OK) {
+		fprintf(stderr, "corosync_cfg_try_shutdown failed: %d\n", res);
+		return 1;
+	}
+	return 0;
+}
diff -Nru corosync-3.1.0/tools/corosync-cfgtool.c corosync-3.1.2/tools/corosync-cfgtool.c
--- corosync-3.1.0/tools/corosync-cfgtool.c	2020-10-20 16:14:16.000000000 +0200
+++ corosync-3.1.2/tools/corosync-cfgtool.c	2021-03-29 14:07:44.000000000 +0200
@@ -47,6 +47,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <limits.h>
+#include <getopt.h>
 
 #include <corosync/corotypes.h>
 #include <corosync/totem/totem.h>
@@ -71,6 +72,7 @@
 enum user_action {
 	ACTION_NOOP=0,
 	ACTION_LINKSTATUS_GET,
+	ACTION_NODESTATUS_GET,
 	ACTION_RELOAD_CONFIG,
 	ACTION_REOPEN_LOG_FILES,
 	ACTION_SHUTDOW,
@@ -89,35 +91,35 @@
 }
 
 static int
-linkstatusget_do (char *interface_name, int brief)
+nodestatusget_do (enum user_action action, int brief)
 {
 	cs_error_t result;
 	corosync_cfg_handle_t handle;
 	cmap_handle_t cmap_handle;
-	unsigned int interface_count;
-	char **interface_names;
-	char **interface_status;
-	uint32_t nodeid_list[KNET_MAX_HOST];
 	char iter_key[CMAP_KEYNAME_MAXLEN];
-	unsigned int i;
 	cmap_iter_handle_t iter;
+	unsigned int local_nodeid;
+	unsigned int local_nodeid_index=0;
+	unsigned int other_nodeid_index=0;
 	unsigned int nodeid;
 	int nodeid_match_guard;
 	cmap_value_types_t type;
 	size_t value_len;
-	int rc = EXIT_SUCCESS;
-	int len, s = 0, t;
-	char stat_ch;
 	char *str;
-	totem_transport_t transport_number = TOTEM_TRANSPORT_KNET;
-	int no_match = 1;
+	char *transport_str = NULL;
+	uint32_t nodeid_list[KNET_MAX_HOST];
+	int s = 0;
+	int rc = EXIT_SUCCESS;
+	int transport_number = TOTEM_TRANSPORT_KNET;
+	int i,j;
+	struct corosync_cfg_node_status_v1 node_status;
 
-	printf ("Printing link status.\n");
 	result = corosync_cfg_initialize (&handle, NULL);
 	if (result != CS_OK) {
 		fprintf (stderr, "Could not initialize corosync configuration API error %d\n", result);
 		exit (EXIT_FAILURE);
 	}
+
 	result = cmap_initialize (&cmap_handle);
 	if (result != CS_OK) {
 		fprintf (stderr, "Could not initialize corosync cmap API error %d\n", result);
@@ -132,7 +134,19 @@
 		if (strcmp (str, "udp") == 0) {
 			transport_number = TOTEM_TRANSPORT_UDP;
 		}
-		free(str);
+		transport_str = str;
+	}
+	if (!transport_str) {
+		transport_str = strdup("knet"); /* It's the default */
+	}
+
+	result = corosync_cfg_local_get(handle, &local_nodeid);
+	if (result != CS_OK) {
+		fprintf (stderr, "Could not get the local node id, the error is: %d\n", result);
+		free(transport_str);
+		cmap_finalize(cmap_handle);
+		corosync_cfg_finalize(handle);
+		return EXIT_FAILURE;
 	}
 
 	/* Get a list of nodes. We do it this way rather than using votequorum as cfgtool
@@ -141,6 +155,9 @@
 	result = cmap_iter_init(cmap_handle, "nodelist.node.", &iter);
 	if (result != CS_OK) {
 		fprintf (stderr, "Could not get nodelist from cmap. error %d\n", result);
+		free(transport_str);
+		cmap_finalize(cmap_handle);
+		corosync_cfg_finalize(handle);
 		exit (EXIT_FAILURE);
 	}
 
@@ -154,140 +171,120 @@
 			continue;
 		}
 		if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
+			if (nodeid == local_nodeid) {
+				local_nodeid_index = s;
+			} else {
+				/* Bit of an odd one this. but local node only uses one link (of course, to itself)
+				   so if we want to know which links are active across the cluster we need to look
+				   at another node (any other) node's link list */
+				other_nodeid_index = s;
+			}
 			nodeid_list[s++] = nodeid;
 		}
 	}
-
-	/* totemknet returns nodes in nodeid order - even though it doesn't tell us
-	   what the nodeid is. So sort our node list and we can then look up
-	   knet node pos to get an actual nodeid.
-	   Yep, I really should have totally rewritten the cfg interface for this.
-	*/
+	/* It's nice to have these in nodeid order */
 	qsort(nodeid_list, s, sizeof(uint32_t), node_compare);
 
-	result = corosync_cfg_local_get(handle, &nodeid);
-	if (result != CS_OK) {
-		fprintf (stderr, "Could not get the local node id, the error is: %d\n", result);
-	}
-	else {
-		printf ("Local node ID " CS_PRI_NODE_ID "\n", nodeid);
-	}
-
-	result = corosync_cfg_ring_status_get (handle,
-				&interface_names,
-				&interface_status,
-				&interface_count);
-	if (result != CS_OK) {
-		fprintf (stderr, "Could not get the link status, the error is: %d\n", result);
-	} else {
-		for (i = 0; i < interface_count; i++) {
-			char *cur_iface_name_space = strchr(interface_names[i], ' ');
-			int show_current_iface;
-
-			s = 0;
-			/*
-			 * Interface_name is "<linkid> <IP address>"
-			 * separate them out
-			 */
-			if (!cur_iface_name_space) {
-				continue;
-			}
-			*cur_iface_name_space = '\0';
+	cmap_finalize(cmap_handle);
 
-			show_current_iface = 1;
-			if (interface_name != NULL && interface_name[0] != '\0' &&
-			    strcmp(interface_name, interface_names[i]) != 0 &&
-			    strcmp(interface_name, cur_iface_name_space + 1) != 0) {
-				show_current_iface = 0;
-			}
+	printf ("Local node ID " CS_PRI_NODE_ID ", transport %s\n", local_nodeid, transport_str);
 
-			if (show_current_iface) {
-				no_match = 0;
-				printf ("LINK ID %s\n", interface_names[i]);
-				printf ("\taddr\t= %s\n", cur_iface_name_space + 1);
-				/*
-				 * UDP(U) interface_status is always OK and doesn't contain
-				 * detailed information (only knet does).
-				 */
-				if ((!brief) && (transport_number == TOTEM_TRANSPORT_KNET)) {
-					len = strlen(interface_status[i]);
-					printf ("\tstatus:\n");
-					while (s < len) {
-						nodeid = nodeid_list[s];
-						printf("\t\tnodeid %2d:\t", nodeid);
-						stat_ch = interface_status[i][s];
-
-						/* Set return code to 1 if status is not localhost or connected. */
-						if (rc == EXIT_SUCCESS) {
-							if ((stat_ch != 'n') && (stat_ch != '3')) {
-								rc = EXIT_FAILURE;
+        /* If node status requested then do print node-based info */
+	if (action == ACTION_NODESTATUS_GET) {
+		for (i=0; i<s; i++) {
+			result = corosync_cfg_node_status_get(handle, nodeid_list[i], CFG_NODE_STATUS_V1, &node_status);
+			if (result == CS_OK) {
+				/* Only display node info if it is reachable (and not us) */
+				if (node_status.reachable && node_status.nodeid != local_nodeid) {
+					printf("nodeid: %d", node_status.nodeid);
+					printf(" reachable");
+					if (node_status.remote) {
+						printf(" remote");
+					}
+					if (node_status.external) {
+						printf(" external");
+					}
+#ifdef HAVE_KNET_ONWIRE_VER
+					if (transport_number == TOTEM_TRANSPORT_KNET) {
+						printf("   onwire (min/max/cur): %d, %d, %d",
+						       node_status.onwire_min,
+						       node_status.onwire_max,
+						       node_status.onwire_ver);
+					}
+#endif
+					printf("\n");
+					for (j=0; j<CFG_MAX_LINKS; j++) {
+						if (node_status.link_status[j].enabled) {
+							printf("   LINK: %d", j);
+							printf(" (%s%s%s)",
+							       node_status.link_status[j].src_ipaddr,
+							       transport_number==TOTEM_TRANSPORT_KNET?"->":"",
+							       node_status.link_status[j].dst_ipaddr);
+							if (node_status.link_status[j].enabled) {
+								printf(" enabled");
+							}
+							if (node_status.link_status[j].connected) {
+								printf(" connected");
 							}
+							if (node_status.link_status[j].dynconnected) {
+								printf(" dynconnected");
+							}
+							printf(" mtu: %d\n", node_status.link_status[j].mtu);
 						}
+					}
+					printf("\n");
+				}
+			}
+		}
+	}
+	/* Print in link order */
+	else {
+		struct corosync_cfg_node_status_v1 node_info[s];
+		memset(node_info, 0, sizeof(node_info));
 
-						if (stat_ch >= '0' && stat_ch <= '9') {
-							t = stat_ch - '0';
-
-							/*
-							 * bit 0 - enabled
-							 * bit 1 - connected
-							 * bit 2 - dynconnected
-							 */
-							if (t & 0x2) {
-								printf("connected");
-							} else {
-								printf("disconnected");
-							}
+		for (i=0; i<s; i++) {
+			result = corosync_cfg_node_status_get(handle, nodeid_list[i], CFG_NODE_STATUS_V1, &node_info[i]);
+			if (result != CS_OK) {
+				fprintf (stderr, "Could not get the node status for nodeid %d, the error is: %d\n", nodeid_list[i], result);
+			}
+		}
 
-							if (!(t & 0x1)) {
-								printf(" (not enabled)");
-							}
-							printf("\n");
-						} else if (stat_ch == 'n') {
-							printf("localhost\n");
-						} else if (stat_ch == '?') {
-							printf("knet error\n");
-						} else if (stat_ch == 'd') {
-							printf("config error\n");
-						} else {
-							printf("can't decode status character '%c'\n", stat_ch);
+		for (i=0; i<CFG_MAX_LINKS; i++) {
+			if (node_info[other_nodeid_index].link_status[i].enabled) {
+				printf("LINK ID %d\n", i);
+				printf("\taddr\t= %s\n", node_info[other_nodeid_index].link_status[i].src_ipaddr);
+				if (brief) {
+					printf("\tstatus\t= ");
+					for (j=0; j<s; j++) {
+						char status = (node_info[j].link_status[i].enabled |
+							       (node_info[j].link_status[i].connected << 1)) + '0';
+						if (status == '0') {
+							status = 'n';
 						}
-						s++;
+						printf("%c", status);
 					}
+					printf("\n");
 				} else {
-					printf ("\tstatus\t= %s\n", interface_status[i]);
-
-					/* Set return code to 1 if status is not localhost or connected. */
-					if ((rc == EXIT_SUCCESS) && (transport_number == TOTEM_TRANSPORT_KNET)) {
-						len = strlen(interface_status[i]);
-						while (s < len) {
-							stat_ch = interface_status[i][s];
-							if ((stat_ch != 'n') && (stat_ch != '3')) {
-								rc = EXIT_FAILURE;
-								break;
+					printf("\tstatus:\n");
+					for (j=0; j<s; j++) {
+						printf("\t\tnodeid: %3d:\t", node_info[j].nodeid);
+						if (j == local_nodeid_index) {
+							printf("localhost");
+						} else {
+							if (node_info[j].link_status[i].connected) {
+								printf("connected");
+							} else {
+								printf("disconnected");
 							}
-							s++;
 						}
+						printf("\n");
 					}
 				}
 			}
 		}
-
-		/* No match for value of -i option */
-		if (no_match) {
-			rc = EXIT_FAILURE;
-			fprintf(stderr, "Can't match any IP address or link id\n");
-		}
-
-		for (i = 0; i < interface_count; i++) {
-			free(interface_status[i]);
-			free(interface_names[i]);
-		}
-		free(interface_status);
-		free(interface_names);
 	}
-
-	(void)cmap_finalize (cmap_handle);
-	(void)corosync_cfg_finalize (handle);
+	free(transport_str);
+	corosync_cfg_finalize(handle);
 	return rc;
 }
 
@@ -345,13 +342,19 @@
 	return (rc);
 }
 
-static void shutdown_do(void)
+static void shutdown_do(int force)
 {
 	cs_error_t result;
 	corosync_cfg_handle_t handle;
 	corosync_cfg_callbacks_t callbacks;
+	int flag;
 
 	callbacks.corosync_cfg_shutdown_callback = NULL;
+	if (force) {
+		flag = COROSYNC_CFG_SHUTDOWN_FLAG_REGARDLESS;
+	} else {
+		flag = COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST;
+	}
 
 	result = corosync_cfg_initialize (&handle, &callbacks);
 	if (result != CS_OK) {
@@ -360,7 +363,7 @@
 	}
 
 	printf ("Shutting down corosync\n");
-	cs_repeat(result, 30, corosync_cfg_try_shutdown (handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST));
+	cs_repeat(result, 30, corosync_cfg_try_shutdown (handle, flag));
 	if (result != CS_OK) {
 		fprintf (stderr, "Could not shutdown (error = %d)\n", result);
 	}
@@ -445,18 +448,19 @@
 	printf ("A tool for displaying and configuring active parameters within corosync.\n");
 	printf ("options:\n");
 	printf ("\t-i\tFinds only information about the specified interface IP address or link id when used with -s..\n");
-	printf ("\t-s\tDisplays the status of the current links on this node(UDP/UDPU), with extended status for KNET.\n");
-	printf ("\t-b\tDisplays the brief status of the current links on this node when used with -s.(KNET only)\n");
+	printf ("\t-s\tDisplays the status of the current links on this node.\n");
+	printf ("\t-n\tDisplays the status of the connected nodes and their links.\n");
+	printf ("\t-b\tDisplays the brief status of the current links on this node when used with -s.\n");
 	printf ("\t-R\tTell all instances of corosync in this cluster to reload corosync.conf.\n");
 	printf ("\t-L\tTell corosync to reopen all logging files.\n");
 	printf ("\t-k\tKill a node identified by node id.\n");
 	printf ("\t-a\tDisplay the IP address(es) of a node\n");
 	printf ("\t-h\tPrint basic usage.\n");
 	printf ("\t-H\tShutdown corosync cleanly on this node.\n");
+	printf ("\t\t--force will shut down corosync regardless of daemon vetos\n");
 }
 
 int main (int argc, char *argv[]) {
-	const char *options = "i:sbrRLk:a:hH";
 	int opt;
 	unsigned int nodeid = 0;
 	char interface_name[128] = "";
@@ -464,9 +468,30 @@
 	enum user_action action = ACTION_NOOP;
 	int brief = 0;
 	long long int l;
+	int option_index = 0;
+	int force_shutdown  = 0;
+	const char *options = "i:snbrRLk:a:hH";
+	struct option long_options[] = {
+		{"if",       required_argument, 0, 'i'},
+		{"status",   no_argument,       0, 's'},
+		{"nodes",    no_argument,       0, 'n'},
+		{"brief",    no_argument,       0, 'b'},
+		{"reload",   no_argument,       0, 'R'},
+		{"reopen",   no_argument,       0, 'L'},
+		{"kill",     required_argument, 0, 'k'},
+		{"address",  required_argument, 0, 'a'},
+		{"shutdown", no_argument,       0, 'H'},
+		{"force",    no_argument,       0, 0},
+		{0,          0,                 0, 0}
+	};
 
-	while ( (opt = getopt(argc, argv, options)) != -1 ) {
+		while ( (opt = getopt_long(argc, argv, options, long_options, &option_index)) != -1 ) {
 		switch (opt) {
+			case 0: // options with no short equivalent - just --force ATM
+			if (strcmp(long_options[option_index].name, "force") == 0) {
+				force_shutdown = 1;
+			}
+			break;
 		case 'i':
 			strncpy(interface_name, optarg, sizeof(interface_name));
 			interface_name[sizeof(interface_name) - 1] = '\0';
@@ -474,6 +499,9 @@
 		case 's':
 			action = ACTION_LINKSTATUS_GET;
 			break;
+		case 'n':
+			action = ACTION_NODESTATUS_GET;
+			break;
 		case 'b':
 			brief = 1;
 			break;
@@ -512,7 +540,10 @@
 	}
 	switch(action) {
 	case ACTION_LINKSTATUS_GET:
-		rc = linkstatusget_do(interface_name, brief);
+		rc = nodestatusget_do(action, brief);
+		break;
+	case ACTION_NODESTATUS_GET:
+		rc = nodestatusget_do(action, brief);
 		break;
 	case ACTION_RELOAD_CONFIG:
 		rc = reload_config_do();
@@ -524,7 +555,7 @@
 		killnode_do(nodeid);
 		break;
 	case ACTION_SHUTDOW:
-		shutdown_do();
+		shutdown_do(force_shutdown);
 		break;
 	case ACTION_SHOWADDR:
 		rc = showaddrs_do(nodeid);
diff -Nru corosync-3.1.0/tools/Makefile.in corosync-3.1.2/tools/Makefile.in
--- corosync-3.1.0/tools/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/tools/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -343,7 +343,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
diff -Nru corosync-3.1.0/.version corosync-3.1.2/.version
--- corosync-3.1.0/.version	2020-10-20 16:15:47.000000000 +0200
+++ corosync-3.1.2/.version	2021-04-06 12:03:42.000000000 +0200
@@ -1 +1 @@
-3.1.0
+3.1.2
diff -Nru corosync-3.1.0/vqsim/Makefile.in corosync-3.1.2/vqsim/Makefile.in
--- corosync-3.1.0/vqsim/Makefile.in	2020-10-20 16:15:27.000000000 +0200
+++ corosync-3.1.2/vqsim/Makefile.in	2021-04-06 12:03:24.000000000 +0200
@@ -282,7 +282,6 @@
 PACKAGE_URL = @PACKAGE_URL@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 PATH_SEPARATOR = @PATH_SEPARATOR@
-PKGCONFIG = @PKGCONFIG@
 PKG_CONFIG = @PKG_CONFIG@
 PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
 PKG_CONFIG_PATH = @PKG_CONFIG_PATH@

unblock corosync/3.1.2-1

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: