From aa346fd058d47b238ae1b86250f414bcab2e7927 Mon Sep 17 00:00:00 2001 From: Pekka Ekman Date: Sat, 30 Jul 2016 12:34:56 +0300 Subject: [PATCH] Add D-Bus proxy --- Makefile | 1 + README.md | 18 ++++++++++++++ netns-exec-dbus | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100755 netns-exec-dbus diff --git a/Makefile b/Makefile index 2363115..00e706b 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ $(PROG): $(OBJS) install: $(PROG) install -D -m4755 -t$(BINDIR) $(PROG) + install -m755 -t$(BINDIR) netns-exec-dbus uninstall: rm -fv $(BINDIR)/$(PROG) diff --git a/README.md b/README.md index 3592ea8..0db4aea 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,23 @@ Show help: netns-exec -h netns-exec --help +If you have problems with D-Bus, use `netns-exec-dbus` instead of +`netns-exec`. It takes the same parameters. See below for explanation. + + +D-Bus proxy +----------- + +D-Bus doesn't work inside the network namespace if the D-Bus daemon is +using an abstract Unix domain socket. The script `netns-exec-dbus` +enables the use of D-Bus by creating a simple proxy that listens on a +regular Unix domain socket, which works across namespaces. It uses +[socat], which must be installed and in `$PATH`. It starts the command +with the environment variable `DBUS_SESSION_BUS_ADDRESS` set to point +to the proxy socket, which should make the program use the proxy +socket. The proxy is only started when necessary, and it and its +socket are automatically destroyed after the command terminates. + Building and installing ----------------------- @@ -45,3 +62,4 @@ a machine where this is a problem. [iproute2]: http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 +[socat]: http://www.dest-unreach.org/socat/ diff --git a/netns-exec-dbus b/netns-exec-dbus new file mode 100755 index 0000000..74717a5 --- /dev/null +++ b/netns-exec-dbus @@ -0,0 +1,65 @@ +#!/bin/sh + +# find D-Bus session bus addresses +dbus_addr="$DBUS_SESSION_BUS_ADDRESS" +if [ -z "$dbus_addr" ]; then + machine_id="$(cat /etc/machine-id 2>/dev/null)" + display_num="${DISPLAY#*:}" + display_num="${display_num%.*}" + if [ -n "$machine_id" ] && [ -n "$display_num" ]; then + file="$HOME/.dbus/session-bus/$machine_id-$display_num" + dbus_addr="$(grep -m 1 '^DBUS_SESSION_BUS_ADDRESS=' "$file")" + dbus_addr="${dbus_addr#DBUS_SESSION_BUS_ADDRESS=}" + fi +fi + +# check if the addresses contain a normal (non-abstract) unix domain +# socket transport +has_normal_unix_transport () { + local IFS + IFS=';' + for addr in $dbus_addr; do + case "$addr" in + unix:path=*|unix:*,path=*) + return 0 ;; + esac + done + return 1 +} + +# don't start the proxy if there is no d-bus address or if there is a +# normal unix transport, which works fine without a proxy +if [ -n "$dbus_addr" ] && ! has_normal_unix_transport; then + # find abstract unix transport + IFS=';' + for addr in $dbus_addr; do + case "$addr" in + unix:abstract=*|unix:*,abstract=*) + # parse address, get socket name and guid + name= + guid_opt= + IFS=',' + for part in ${addr#unix:}; do + case "$part" in + abstract=*) + name="${part#abstract=}" ;; + guid=*) + guid_opt=",$part" ;; + esac + done + + if [ -n "$name" ]; then + # start proxy and kill it when shell exits + proxy_path="/tmp/dbus-proxy-$$" + socat UNIX-LISTEN:"$proxy_path",fork ABSTRACT-CONNECT:"$name" & + trap "kill -TERM $! && wait" 0 + export DBUS_SESSION_BUS_ADDRESS="unix:path=$proxy_path$guid_opt" + fi + break + ;; + esac + done +fi + + +netns-exec "$@"