From c1eda74d1f9a0d54ee0ccf22f99da3ec94797a80 Mon Sep 17 00:00:00 2001 From: Rahul Date: Tue, 7 Jul 2026 17:33:26 -0700 Subject: [PATCH] hook-docker: bracket IPv6 hosts in dockerd syslog log driver URL Bare IPv6 addresses passed via the `syslog_host=` kernel cmdline were not bracketed in the dockerd syslog log driver URL, producing a malformed value that dockerd cannot parse. Use net.JoinHostPort so IPv6 is bracketed correctly (e.g. `udp://[fd00:80:66::1]:514`); IPv4 and hostname inputs are unchanged. Also skip configuring the syslog log driver when the syslog host is empty. Signed-off-by: Rahul Ganesh Signed-off-by: Rahul --- images/hook-docker/main.go | 23 ++++++++++++++++++----- images/hook-docker/main_test.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/images/hook-docker/main.go b/images/hook-docker/main.go index 4a7ff764..61c53fc3 100644 --- a/images/hook-docker/main.go +++ b/images/hook-docker/main.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "net" "os" "os/exec" "path/filepath" @@ -37,13 +38,13 @@ func run() error { fmt.Println("Starting the Docker Engine") d := dockerConfig{ - Debug: true, - LogDriver: "syslog", - LogOpts: map[string]string{ - "syslog-address": fmt.Sprintf("udp://%v:514", cfg.syslogHost), - }, + Debug: true, InsecureRegistries: cfg.insecureRegistries, } + if addr := syslogAddress(cfg.syslogHost); addr != "" { + d.LogDriver = "syslog" + d.LogOpts = map[string]string{"syslog-address": addr} + } path := "/etc/docker" // Create the directory for the docker config err = os.MkdirAll(path, os.ModeDir) @@ -89,6 +90,18 @@ func main() { } } +// syslogAddress builds the syslog log driver's UDP address for the given host. +// It returns an empty string when host is empty (caller should skip configuring +// the syslog log driver in that case). IPv6 addresses are bracketed via +// net.JoinHostPort so the resulting URL parses correctly (e.g. +// "udp://[fd00::1]:514" rather than "udp://fd00::1:514"). +func syslogAddress(host string) string { + if host == "" { + return "" + } + return "udp://" + net.JoinHostPort(host, "514") +} + // writeToDisk writes the dockerConfig to loc. func (d dockerConfig) writeToDisk(loc string) error { b, err := json.Marshal(d) diff --git a/images/hook-docker/main_test.go b/images/hook-docker/main_test.go index 7ce280fd..04cacdc6 100644 --- a/images/hook-docker/main_test.go +++ b/images/hook-docker/main_test.go @@ -7,6 +7,26 @@ import ( "testing" ) +func TestSyslogAddress(t *testing.T) { + tests := map[string]struct { + host string + want string + }{ + "empty host returns empty": {host: "", want: ""}, + "ipv4 host": {host: "192.168.1.10", want: "udp://192.168.1.10:514"}, + "ipv6 host is bracketed": {host: "fd00:80:66::1", want: "udp://[fd00:80:66::1]:514"}, + "ipv6 loopback": {host: "::1", want: "udp://[::1]:514"}, + "hostname passes through": {host: "syslog.example.com", want: "udp://syslog.example.com:514"}, + } + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + if got := syslogAddress(tt.host); got != tt.want { + t.Fatalf("syslogAddress(%q) = %q, want %q", tt.host, got, tt.want) + } + }) + } +} + func TestWriteToDisk(t *testing.T) { tests := map[string]struct { cfg dockerConfig