Commit 2f5c2e377d for strongswan.org

commit 2f5c2e377d7e14115522552f6421a89ade0b4bfe
Author: Duc Anh Luu <luuducanh05051995@gmail.com>
Date:   Thu Oct 8 08:45:39 2026 +0700

    swanctl: Print log messages that contain newlines

    vici_find_str() only returns printable strings, so log messages that
    contain newlines (e.g. dumps of binary data on log levels > 2) were
    printed as empty lines by --initiate and --terminate, and not at all by
    --log (which does not log on levels > 1, though).  Get the raw message
    instead and print each line with the same prefix, replacing any other
    non-printable characters.

    Closes strongswan/strongswan#2066
    Closes strongswan/strongswan#3165

diff --git a/src/swanctl/commands/initiate.c b/src/swanctl/commands/initiate.c
index e0fffb907d..7faf3013a2 100644
--- a/src/swanctl/commands/initiate.c
+++ b/src/swanctl/commands/initiate.c
@@ -15,6 +15,7 @@
  */

 #include "command.h"
+#include "swanctl.h"

 #include <errno.h>

@@ -27,9 +28,11 @@ CALLBACK(log_cb, void,
 	}
 	else
 	{
-		printf("[%s] %s\n",
-			   vici_find_str(msg, "   ", "group"),
-			   vici_find_str(msg, "", "msg"));
+		char prefix[16];
+
+		snprintf(prefix, sizeof(prefix), "[%s] ",
+				 vici_find_str(msg, "   ", "group"));
+		print_msg(msg, prefix);
 	}
 }

diff --git a/src/swanctl/commands/log.c b/src/swanctl/commands/log.c
index 8322223129..9318a81771 100644
--- a/src/swanctl/commands/log.c
+++ b/src/swanctl/commands/log.c
@@ -15,6 +15,7 @@
  */

 #include "command.h"
+#include "swanctl.h"

 #include <errno.h>
 #include <unistd.h>
@@ -28,22 +29,12 @@ CALLBACK(log_cb, void,
 	}
 	else
 	{
-		char *current, *next;
+		char prefix[32];

-		current = vici_find_str(msg, NULL, "msg");
-		while (current)
-		{
-			next = strchr(current, '\n');
-			printf("%.2d[%s] ", vici_find_int(msg, 0, "thread"),
-				   vici_find_str(msg, "   ", "group"));
-			if (next == NULL)
-			{
-				printf("%s\n", current);
-				break;
-			}
-			printf("%.*s\n", (int)(next - current), current);
-			current = next + 1;
-		}
+		snprintf(prefix, sizeof(prefix), "%.2d[%s] ",
+				 vici_find_int(msg, 0, "thread"),
+				 vici_find_str(msg, "   ", "group"));
+		print_msg(msg, prefix);
 	}
 }

diff --git a/src/swanctl/commands/terminate.c b/src/swanctl/commands/terminate.c
index 69491b278e..bb4a5ec620 100644
--- a/src/swanctl/commands/terminate.c
+++ b/src/swanctl/commands/terminate.c
@@ -15,6 +15,7 @@
  */

 #include "command.h"
+#include "swanctl.h"

 #include <errno.h>

@@ -27,9 +28,11 @@ CALLBACK(log_cb, void,
 	}
 	else
 	{
-		printf("[%s] %s\n",
-			   vici_find_str(msg, "   ", "group"),
-			   vici_find_str(msg, "", "msg"));
+		char prefix[16];
+
+		snprintf(prefix, sizeof(prefix), "[%s] ",
+				 vici_find_str(msg, "   ", "group"));
+		print_msg(msg, prefix);
 	}
 }

diff --git a/src/swanctl/swanctl.c b/src/swanctl/swanctl.c
index 4fb628838b..215cd41763 100644
--- a/src/swanctl/swanctl.c
+++ b/src/swanctl/swanctl.c
@@ -80,6 +80,33 @@ void print_label(const char *prefix, const char *value)
 	}
 }

+/*
+ * Described in header
+ */
+void print_msg(vici_res_t *res, const char *prefix)
+{
+	chunk_t msg, line, sane;
+	char *pos;
+	int len;
+
+	msg.ptr = vici_find(res, &len, "msg");
+	msg.len = len;
+
+	while (msg.ptr)
+	{
+		line = msg;
+		pos = memchr(msg.ptr, '\n', msg.len);
+		if (pos)
+		{
+			line.len = pos - (char*)msg.ptr;
+		}
+		msg = chunk_skip(msg, line.len + 1);
+		chunk_printable(line, &sane, ' ');
+		printf("%s%.*s\n", prefix, (int)sane.len, (char*)sane.ptr ?: "");
+		chunk_free(&sane);
+	}
+}
+
 /**
  * Cleanup library atexit()
  */
diff --git a/src/swanctl/swanctl.h b/src/swanctl/swanctl.h
index ba331a02a4..528568237c 100644
--- a/src/swanctl/swanctl.h
+++ b/src/swanctl/swanctl.h
@@ -25,6 +25,7 @@
 #define SWANCTL_H_

 #include <settings/settings.h>
+#include <libvici.h>

 /**
  * Base directory for credentials and config
@@ -114,4 +115,15 @@ settings_t *load_swanctl_conf(char *file);
  */
 void print_label(const char *prefix, const char *value);

+/**
+ * Print the "msg" value of a vici log message, each line with the given
+ * prefix.  The message is not a printable string if it contains newlines
+ * (e.g. for dumps of binary data), so the raw value is retrieved and any
+ * other non-printable characters are replaced.
+ *
+ * @param res		log message
+ * @param prefix	prefix to print before each line
+ */
+void print_msg(vici_res_t *res, const char *prefix);
+
 #endif /** SWANCTL_H_ @}*/